From c5c76d3f9da28d3fbcbec5d691c0286ea3c66f71 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 3 Sep 2023 19:24:14 +0300 Subject: [PATCH] Various QoL changes --- .../amd64/Bootstrap/Multiboot/2/Multiboot.cpp | 2 +- .../i386/Bootstrap/Multiboot/2/Multiboot.cpp | 2 +- .../i386/cpu/SymmetricMultiprocessing.cpp | 26 ++- Architecture/i386/cpu/apic.hpp | 2 + Core/CPU.cpp | 219 ++++++------------ Core/Memory/Memory.cpp | 22 +- include/cpu.hpp | 2 +- include/memory.hpp | 30 ++- 8 files changed, 138 insertions(+), 167 deletions(-) diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp index cff0bf0..2571499 100644 --- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp @@ -197,7 +197,7 @@ EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) } } debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); - debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + debug("More info:\nAddress: %p\nPitch: %d\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot.cpp b/Architecture/i386/Bootstrap/Multiboot/2/Multiboot.cpp index 8e17323..da9d92a 100644 --- a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot.cpp +++ b/Architecture/i386/Bootstrap/Multiboot/2/Multiboot.cpp @@ -197,7 +197,7 @@ EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) } } debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); - debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + debug("More info:\nAddress: %p\nPitch: %d\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); diff --git a/Architecture/i386/cpu/SymmetricMultiprocessing.cpp b/Architecture/i386/cpu/SymmetricMultiprocessing.cpp index cd95ace..50055e0 100644 --- a/Architecture/i386/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/i386/cpu/SymmetricMultiprocessing.cpp @@ -41,20 +41,34 @@ enum SMPTrampolineAddress std::atomic_bool CPUEnabled = false; #pragma GCC diagnostic ignored "-Wmissing-field-initializers" -static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0}; +static __aligned(PAGE_SIZE) CPUData CPUs[MAX_CPU] = {0}; SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; } SafeFunction CPUData *GetCurrentCPU() { - uint64_t ret = 0; - if (!(&CPUs[ret])->IsActive) + if (unlikely(!Interrupts::apic[0])) + return &CPUs[0]; /* No APIC means we are on the BSP. */ + + APIC::APIC *apic = (APIC::APIC *)Interrupts::apic[0]; + int CoreID = 0; + if (CPUEnabled.load(std::memory_order_acquire) == true) { - // error("CPU %d is not active!", ret); FIXME + if (apic->x2APIC) + CoreID = int(CPU::x32::rdmsr(CPU::x32::MSR_X2APIC_APICID)); + else + CoreID = apic->Read(APIC::APIC_ID) >> 24; + } + + if (unlikely((&CPUs[CoreID])->IsActive != true)) + { + error("CPU %d is not active!", CoreID); + assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */ return &CPUs[0]; } - assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM); - return &CPUs[ret]; + + assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */ + return &CPUs[CoreID]; } namespace SMP diff --git a/Architecture/i386/cpu/apic.hpp b/Architecture/i386/cpu/apic.hpp index 9f93484..a3001fd 100644 --- a/Architecture/i386/cpu/apic.hpp +++ b/Architecture/i386/cpu/apic.hpp @@ -319,6 +319,8 @@ namespace APIC uint64_t APICBaseAddress = 0; public: + decltype(x2APICSupported) &x2APIC = x2APICSupported; + uint32_t Read(uint32_t Register); void Write(uint32_t Register, uint32_t Value); void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value); diff --git a/Core/CPU.cpp b/Core/CPU.cpp index 7dc6e70..b26857b 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -24,6 +24,13 @@ #include "../kernel.h" +#if defined(a64) +using namespace CPU::x64; +#elif defined(a32) +using namespace CPU::x32; +#elif defined(aa64) +#endif + namespace CPU { static bool SSEEnabled = false; @@ -199,18 +206,19 @@ namespace CPU return PT; } - void InitializeFeatures(long Core) + struct SupportedFeat { - static int BSP = 0; - bool PGESupport = false; - bool SSESupport = false; -#if defined(a64) - bool UMIPSupport = false; - bool SMEPSupport = false; - bool SMAPSupport = false; + bool PGE = false; + bool SSE = false; + bool UMIP = false; + bool SMEP = false; + bool SMAP = false; + bool FSGSBASE = false; + }; - x64::CR0 cr0 = x64::readcr0(); - x64::CR4 cr4 = x64::readcr4(); + SupportedFeat GetCPUFeat() + { + SupportedFeat feat{}; if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) { @@ -219,11 +227,12 @@ namespace CPU cpuid1.Get(); cpuid7.Get(); - PGESupport = cpuid1.EDX.PGE; - SSESupport = cpuid1.EDX.SSE; - SMEPSupport = cpuid7.EBX.SMEP; - SMAPSupport = cpuid7.EBX.SMAP; - UMIPSupport = cpuid7.ECX.UMIP; + feat.PGE = cpuid1.EDX.PGE; + feat.SSE = cpuid1.EDX.SSE; + feat.SMEP = cpuid7.EBX.SMEP; + feat.SMAP = cpuid7.EBX.SMAP; + feat.UMIP = cpuid7.ECX.UMIP; + feat.FSGSBASE = cpuid7.EBX.FSGSBASE; } else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) { @@ -231,83 +240,94 @@ namespace CPU CPU::x86::Intel::CPUID0x00000007_0 cpuid7_0; cpuid1.Get(); cpuid7_0.Get(); - PGESupport = cpuid1.EDX.PGE; - SSESupport = cpuid1.EDX.SSE; - SMEPSupport = cpuid7_0.EBX.SMEP; - SMAPSupport = cpuid7_0.EBX.SMAP; - UMIPSupport = cpuid7_0.ECX.UMIP; + feat.PGE = cpuid1.EDX.PGE; + feat.SSE = cpuid1.EDX.SSE; + feat.SMEP = cpuid7_0.EBX.SMEP; + feat.SMAP = cpuid7_0.EBX.SMAP; + feat.UMIP = cpuid7_0.ECX.UMIP; + feat.FSGSBASE = cpuid7_0.EBX.FSGSBase; } + return feat; + } + + void InitializeFeatures(int Core) + { + static int BSP = 0; + SupportedFeat feat = GetCPUFeat(); + + CR0 cr0 = readcr0(); + CR4 cr4 = readcr4(); + if (Config.SIMD == false) { debug("Disabling SSE support..."); - SSESupport = false; + feat.SSE = false; } - if (PGESupport) + if (feat.PGE) { debug("Enabling global pages support..."); if (!BSP) KPrint("Global Pages is supported."); - cr4.PGE = 1; + cr4.PGE = true; } bool SSEEnableAfter = false; /* Not sure if my code is not working properly or something else is the issue. */ if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) && - SSESupport) + feat.SSE) { debug("Enabling SSE support..."); if (!BSP) KPrint("SSE is supported."); - cr0.EM = 0; - cr0.MP = 1; - cr4.OSFXSR = 1; - cr4.OSXMMEXCPT = 1; + cr0.EM = false; + cr0.MP = true; + cr4.OSFXSR = true; + cr4.OSXMMEXCPT = true; CPUData *CoreData = GetCPU(Core); CoreData->Data.FPU.mxcsr = 0b0001111110000000; CoreData->Data.FPU.mxcsrmask = 0b1111111110111111; CoreData->Data.FPU.fcw = 0b0000001100111111; - CPU::x64::fxrstor(&CoreData->Data.FPU); + fxrstor(&CoreData->Data.FPU); SSEEnableAfter = true; } - cr0.NW = 0; - cr0.CD = 0; - cr0.WP = 1; + cr0.NW = false; + cr0.CD = false; + cr0.WP = true; - x64::writecr0(cr0); + writecr0(cr0); if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 && strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0) { - // FIXME: I don't think this is reporting correctly. This has to be fixed asap. debug("Enabling UMIP, SMEP & SMAP support..."); - if (UMIPSupport) + if (feat.UMIP) { if (!BSP) KPrint("UMIP is supported."); - debug("UMIP is supported."); - // cr4.UMIP = 1; + fixme("UMIP is supported."); + // cr4.UMIP = true; } - if (SMEPSupport) + if (feat.SMEP) { if (!BSP) KPrint("SMEP is supported."); - debug("SMEP is supported."); - // cr4.SMEP = 1; + fixme("SMEP is supported."); + // cr4.SMEP = true; } - if (SMAPSupport) + if (feat.SMAP) { if (!BSP) KPrint("SMAP is supported."); - debug("SMAP is supported."); - // cr4.SMAP = 1; + fixme("SMAP is supported."); + // cr4.SMAP = true; } } else @@ -321,117 +341,24 @@ namespace CPU } } + if (feat.FSGSBASE) + { + if (!BSP) + KPrint("FSGSBASE is supported."); + fixme("FSGSBASE is supported."); + cr4.FSGSBASE = true; + } + debug("Writing CR4..."); - x64::writecr4(cr4); + writecr4(cr4); debug("Wrote CR4."); debug("Enabling PAT support..."); - x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); + wrmsr(MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); if (!BSP++) trace("Features for BSP initialized."); if (SSEEnableAfter) SSEEnabled = true; -#elif defined(a32) - - x32::CR0 cr0 = x32::readcr0(); - x32::CR4 cr4 = x32::readcr4(); - - if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) - { - CPU::x86::AMD::CPUID0x00000001 cpuid1; - cpuid1.Get(); - - PGESupport = cpuid1.EDX.PGE; - SSESupport = cpuid1.EDX.SSE; - } - else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) - { - CPU::x86::Intel::CPUID0x00000001 cpuid1; - cpuid1.Get(); - PGESupport = cpuid1.EDX.PGE; - SSESupport = cpuid1.EDX.SSE; - } - - if (Config.SIMD == false) - { - debug("Disabling SSE support..."); - SSESupport = false; - } - - if (PGESupport) - { - debug("Enabling global pages support..."); - if (!BSP) - KPrint("Global Pages is supported."); - cr4.PGE = 1; - } - - bool SSEEnableAfter = false; - - /* Not sure if my code is not working properly or something else is the issue. */ - if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0 && - strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) && - SSESupport) - { - debug("Enabling FPU..."); - bool FPU = false; - { - x32::CR0 _cr0; - // __asm__ __volatile__( - // "mov %%cr0, %0\n" - // "and $0xfffffff8, %0\n" - // "mov %0, %%cr0\n" - // "fninit\n" - // "fwait\n" - // "mov %%cr0, %0\n" - // : "=r"(_cr0.raw) - // : - // : "memory"); - _cr0 = x32::readcr0(); - if ((_cr0.EM) == 0) - { - FPU = true; - debug("FPU is supported"); - } - } - - if (FPU) - KPrint("FPU is supported."); - - debug("Enabling SSE support..."); - if (!BSP) - KPrint("SSE is supported."); - cr0.EM = 0; - cr0.MP = 1; - cr4.OSFXSR = 1; - cr4.OSXMMEXCPT = 1; - - CPUData *CoreData = GetCPU(Core); - CoreData->Data.FPU.mxcsr = 0b0001111110000000; - CoreData->Data.FPU.mxcsrmask = 0b1111111110111111; - CoreData->Data.FPU.fcw = 0b0000001100111111; - CPU::x64::fxrstor(&CoreData->Data.FPU); - - SSEEnableAfter = true; - } - - cr0.NW = 0; - cr0.CD = 0; - cr0.WP = 1; - - x32::writecr0(cr0); - debug("Writing CR4..."); - x32::writecr4(cr4); - debug("Wrote CR4."); - - debug("Enabling PAT support..."); - x32::wrmsr(x32::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); - if (!BSP++) - trace("Features for BSP initialized."); - if (SSEEnableAfter) - SSEEnabled = true; -#elif defined(aa64) -#endif } uint64_t Counter() diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 976ab94..db59db7 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -99,7 +99,7 @@ NIF void MapFromZero(PageTable *PT) va.Unmap((void *)0); } -NIF void MapFramebuffer(PageTable *PT) +NIF void MapFramebuffer(PageTable *PT, bool PSE, bool OneGB) { debug("Mapping Framebuffer"); Virtual va = Virtual(PT); @@ -109,10 +109,20 @@ NIF void MapFramebuffer(PageTable *PT) if (!bInfo.Framebuffer[itrfb].BaseAddress) break; - va.OptimizedMap((void *)bInfo.Framebuffer[itrfb].BaseAddress, - (void *)bInfo.Framebuffer[itrfb].BaseAddress, - (size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height), - PTFlag::RW | PTFlag::US | PTFlag::G); + size_t fbSize = bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height; + + if (PSE && OneGB) + { + va.OptimizedMap(bInfo.Framebuffer[itrfb].BaseAddress, + bInfo.Framebuffer[itrfb].BaseAddress, + fbSize, PTFlag::RW | PTFlag::US | PTFlag::G); + } + else + { + va.Map(bInfo.Framebuffer[itrfb].BaseAddress, + bInfo.Framebuffer[itrfb].BaseAddress, + fbSize, PTFlag::RW | PTFlag::US | PTFlag::G); + } itrfb++; } } @@ -337,7 +347,7 @@ NIF void InitializeMemoryManagement() #endif MapFromZero(KernelPageTable); - MapFramebuffer(KernelPageTable); + MapFramebuffer(KernelPageTable, PSESupport, Page1GBSupport); MapKernel(KernelPageTable); trace("Applying new page table from address %#lx", KernelPageTable); diff --git a/include/cpu.hpp b/include/cpu.hpp index 48c8eb7..89f9bac 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -203,7 +203,7 @@ namespace CPU void *PageTable(void *PT = nullptr); /** @brief To be used only once. */ - void InitializeFeatures(long Core); + void InitializeFeatures(int Core); /** @brief Get CPU counter value. */ uint64_t Counter(); diff --git a/include/memory.hpp b/include/memory.hpp index 66ba079..c8abb76 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -63,7 +63,7 @@ extern uintptr_t _kernel_bss_start, _kernel_bss_end; // To pages #define TO_PAGES(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE) // From pages -#define FROM_PAGES(d) ((d)*PAGE_SIZE) +#define FROM_PAGES(d) ((d) * PAGE_SIZE) #if defined(a64) || defined(aa64) #define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000 @@ -790,7 +790,9 @@ namespace Memory * @return true if page has the specified flag. * @return false if page is has the specified flag. */ - bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKiB); + bool Check(void *VirtualAddress, + PTFlag Flag = PTFlag::P, + MapType Type = MapType::FourKiB); /** * @brief Get physical address of the page. @@ -822,7 +824,10 @@ namespace Memory * @param Flags Flags of the page. Check PTFlag enum. * @param Type Type of the page. Check MapType enum. */ - void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P, MapType Type = MapType::FourKiB); + void Map(void *VirtualAddress, + void *PhysicalAddress, + uint64_t Flag = PTFlag::P, + MapType Type = MapType::FourKiB); /** * @brief Map multiple pages. @@ -833,7 +838,11 @@ namespace Memory * @param Flags Flags of the page. Check PTFlag enum. * @param Type Type of the page. Check MapType enum. */ - __always_inline inline void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type = MapType::FourKiB) + __always_inline inline void Map(void *VirtualAddress, + void *PhysicalAddress, + size_t Length, + uint64_t Flags, + MapType Type = MapType::FourKiB) { int PageSize = PAGE_SIZE_4K; @@ -845,7 +854,11 @@ namespace Memory PageSize = PAGE_SIZE_1G; for (uintptr_t i = 0; i < Length; i += PageSize) - this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags, Type); + { + this->Map((void *)((uintptr_t)VirtualAddress + i), + (void *)((uintptr_t)PhysicalAddress + i), + Flags, Type); + } } /** @@ -863,7 +876,12 @@ namespace Memory * @param FailOnModulo If true, the function will return NoMapType if the length is not a multiple of the page size. * @return The best page size to map the pages. */ - __always_inline inline MapType OptimizedMap(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, bool Fit = false, bool FailOnModulo = false) + __always_inline inline MapType OptimizedMap(void *VirtualAddress, + void *PhysicalAddress, + size_t Length, + uint64_t Flags, + bool Fit = false, + bool FailOnModulo = false) { if (unlikely(Fit)) {