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:
@@ -12,7 +12,7 @@ namespace Kernel::API
|
||||
|
||||
struct SharedPage
|
||||
{
|
||||
uint8_t __sequence[0x100];
|
||||
uint16_t gdt_cpu_offset;
|
||||
|
||||
uint32_t features;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 (;;)
|
||||
|
||||
Reference in New Issue
Block a user