Kernel: Pass current cpu index as a GDT limit

I had no idea LSL was an instruction. This cleans up code to get the
current cpu by a lot and does not require extra segment usage :D
This commit is contained in:
2026-05-02 18:10:10 +03:00
parent d49d260a09
commit 3874e0ed1e
9 changed files with 23 additions and 42 deletions

View File

@@ -12,7 +12,7 @@ namespace Kernel::API
struct SharedPage
{
uint8_t __sequence[0x100];
uint16_t gdt_cpu_offset;
uint32_t features;

View File

@@ -133,6 +133,12 @@ namespace Kernel
void set_gsbase(uintptr_t addr);
#endif
static uint16_t cpu_index_offset() { return m_cpu_index_offset; }
void set_cpu_index(uint8_t index)
{
write_entry(m_cpu_index_offset, 0, index, 0xF2, 0x4);
}
private:
GDT() = default;
@@ -151,11 +157,13 @@ namespace Kernel
private:
#if ARCH(x86_64)
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), tss low, tss high
static constexpr uint16_t m_tss_offset = 0x30;
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), cpu-index, tss low, tss high
static constexpr uint16_t m_cpu_index_offset = 0x30;
static constexpr uint16_t m_tss_offset = 0x38;
#elif ARCH(i686)
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
static constexpr uint16_t m_tss_offset = 0x40;
BAN::Array<SegmentDescriptor, 10> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, cpu-index, tss
static constexpr uint16_t m_cpu_index_offset = 0x40;
static constexpr uint16_t m_tss_offset = 0x48;
#endif
TaskStateSegment m_tss;
const GDTR m_gdtr {

View File

@@ -178,9 +178,7 @@ namespace Kernel
bool m_is_userspace { false };
bool m_delete_process { false };
bool m_has_custom_fsbase { false };
vaddr_t m_fsbase { 0 };
bool m_has_custom_gsbase { false };
vaddr_t m_gsbase { 0 };
SchedulerQueue::Node* m_scheduler_node { nullptr };

View File

@@ -32,6 +32,8 @@ namespace Kernel
gdt->write_entry(0x38, 0x00000000, 0x00000, 0xF2, 0xC); // gsbase
#endif
gdt->write_entry(m_cpu_index_offset, 0, 0, 0, 0);
gdt->write_tss();
return gdt;

View File

@@ -3314,7 +3314,6 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_set_fsbase(void* addr)
{
auto& thread = Thread::current();
thread.m_has_custom_fsbase = true;
thread.set_fsbase(reinterpret_cast<vaddr_t>(addr));
Processor::load_fsbase();
return 0;
@@ -3328,7 +3327,6 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_set_gsbase(void* addr)
{
auto& thread = Thread::current();
thread.m_has_custom_gsbase = true;
thread.set_gsbase(reinterpret_cast<vaddr_t>(addr));
Processor::load_gsbase();
return 0;

View File

@@ -217,8 +217,7 @@ namespace Kernel
memset(reinterpret_cast<void*>(s_shared_page_vaddr), 0, PAGE_SIZE);
auto& shared_page = *reinterpret_cast<volatile API::SharedPage*>(s_shared_page_vaddr);
for (size_t i = 0; i <= 0xFF; i++)
shared_page.__sequence[i] = i;
shared_page.gdt_cpu_offset = GDT::cpu_index_offset();
shared_page.features = 0;
ASSERT(Processor::count() + sizeof(Kernel::API::SharedPage) <= PAGE_SIZE);

View File

@@ -303,22 +303,7 @@ namespace Kernel
{
if (!is_userspace() || !has_process())
return;
#if ARCH(x86_64)
if (m_has_custom_gsbase)
return;
#elif ARCH(i686)
if (m_has_custom_fsbase)
return;
#endif
const vaddr_t vaddr = process().shared_page_vaddr() + Processor::current_index();
#if ARCH(x86_64)
set_gsbase(vaddr);
#elif ARCH(i686)
set_fsbase(vaddr);
#endif
Processor::gdt().set_cpu_index(Processor::current_index());
}
BAN::ErrorOr<Thread*> Thread::pthread_create(entry_t entry, void* arg)

View File

@@ -27,12 +27,7 @@ int sched_getcpu(void)
{
if (g_shared_page == nullptr)
return -1;
uint8_t cpu;
#if defined(__x86_64__)
asm volatile("movb %%gs:0, %0" : "=r"(cpu));
#elif defined(__i686__)
asm volatile("movb %%fs:0, %0" : "=q"(cpu));
#endif
return cpu;
uint16_t limit;
asm volatile("lsl %1, %0" : "=r"(limit) : "r"(g_shared_page->gdt_cpu_offset));
return limit;
}

View File

@@ -30,13 +30,9 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
const auto get_cpu =
[]() -> uint8_t {
uint8_t cpu;
#if defined(__x86_64__)
asm volatile("movb %%gs:0, %0" : "=r"(cpu));
#elif defined(__i686__)
asm volatile("movb %%fs:0, %0" : "=q"(cpu));
#endif
return cpu;
uint16_t limit;
asm volatile("lsl %1, %0" : "=r"(limit) : "r"(g_shared_page->gdt_cpu_offset));
return limit;
};
for (;;)