The realization that we already run on all cores..

This commit is contained in:
Curle 2022-07-08 23:23:49 +01:00
parent 3113fb08c3
commit d681320463
16 changed files with 123 additions and 100 deletions

View File

@ -39,7 +39,6 @@ SET(src_files
${CMAKE_SOURCE_DIR}/src/drivers/devices/input/keyboard.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/input/keyboard.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/io/apic.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/io/apic.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp
${CMAKE_SOURCE_DIR}/src/global/core-att.s
) )
SET(lib_files SET(lib_files
@ -57,6 +56,7 @@ SET(src_no_sse
) )
SET(src_as SET(src_as
${CMAKE_SOURCE_DIR}/src/global/core-att.s
) )
SET(src_preamble SET(src_preamble
@ -78,6 +78,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
add_executable(kernel) add_executable(kernel)
target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_as} PUBLIC ${src_epilogue}) target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_epilogue})
target_compile_options(kernel PRIVATE -ffreestanding -O0 -Wall -Wextra -Wall -Werror -fPIC -fno-exceptions -fno-omit-frame-pointer -mno-red-zone -fno-stack-protector $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> -ggdb3) target_compile_options(kernel PRIVATE -ffreestanding -O0 -Wall -Wextra -Wall -Werror -fPIC -fno-exceptions -fno-omit-frame-pointer -mno-red-zone -fno-stack-protector $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> -ggdb3)
target_link_options(kernel PRIVATE -T ${CMAKE_SOURCE_DIR}/linker.ld -ffreestanding -O2 -nostdlib -nostartfiles -lgcc) target_link_options(kernel PRIVATE -T ${CMAKE_SOURCE_DIR}/linker.ld -ffreestanding -O2 -nostdlib -nostartfiles -lgcc)

View File

@ -38,10 +38,55 @@ It will compile the kernel, and create an OS image with `mkbootimg`.
### Linux ### Linux
The system for linux is a lot easier, but you *do* need an x86_64-elf-gcc cross compiler. You can get one from the AUR on Arch-based distros (like Manjaro), or make one yourself using [the OSDev Wiki guide](https://wiki.osdev.org/GCC_Cross-Compiler) The system for linux is a lot easier, but you *do* need an x86_64-elf-gcc cross compiler. You can get one from the AUR on Arch-based distros (like Manjaro), or make one yourself using [the OSDev Wiki guide](https://wiki.osdev.org/GCC_Cross-Compiler)
Simply run the `init.sh` to generate a makefile, then `make` to create the image file.
On the Chroma side, Simply run the `init.sh` to generate a makefile, then `make` to create the image file.
The generated IMG works in QEMU, or on a physical test device (unlike a lot of other hobby OSes!) The generated IMG works in QEMU, or on a physical test device (unlike a lot of other hobby OSes!)
This means you can use any emulator or hypervisor to run it. This means you can use any emulator or hypervisor to run it.
## Project structure
The repository has a lot of files and folders after setting up a workspace. This is a guide to all the files and folders.
```
File Location | Description
/
├── bin/ | Binary Output folder
│ └── img/ | Image Output folder.
│ └── chroma.img | Disk Image file, as an alternative to ISO below.
│ |
├── inc/ | Global header include folder.
│ ├── driver/ | Header files for the default driver implementations.
│ ├── editor/ | Header files for the builtin editor and debugger.
│ ├── kernel/ | Header files for the Chroma kernel itself.
│ └── lainlib/ | Header files for the Lainlib standard library.
│ |
├── src/ | Source files.
│ ├── assets/ | Assorted linkable files that will be bundled with the built image.
│ ├── drivers/ | Handling of the default driver implementations.
│ ├── editor/ | Handling of the builtin editor and debugger.
│ ├── global/ | Various files used in global objects (ie. the C RunTime, new core bootstrapping, etc)
│ ├── lainlib/ | Handling of the Lainlib standard library.
│ ├── system/ | Core Kernel files.
│ ├── video/ | Writing and drawing on the screen.
│ └── kernel.cpp | The primary kernel entry point.
│ |
├── tools/ | Auxiliary tools used in the buildsystem.
│ └── mkbootimg/ | Creates a bootable .img file based on the chroma.json configuration file below.
│ |
├── .gitignore | Git Repository Ignored Files
├── build_and_run.sh | shell script that builds the img file and runs it using run.sh below.
├── choma.bxrc | bxrc (Bochs Runtime Config) file for the Bochs emulator and debugger.
├── chroma.iso | ISO disc image file that can be loaded into a VM or onto a boot disk.
├── chroma.json | MkBootImg configuration file
├── CMakeLists.txt | Buildscript and CMake project configuration file.
├── LICENSE | Chroma's License. MIT License.
├── linker.ld | GCC linkerscript that places files and addresses at their expected positions.
├── post.sh | Postprocessing script; Generates the final img file, and attempts to update a VirtualBox configuration named "Chroma" to run this new file instead.
├── pre.sh | First-time setup script; generates the font file binary and generates the CMake buildscripts.
├── README.md | This file.
└── run.bat | Attempts to start a Virtualbox VM named "chroma".
```

View File

@ -90,7 +90,7 @@ namespace ACPI {
MADT(); MADT();
void LogDump(); void LogDump();
void Initialize(); void Init();
// Get the byte of the end of the table. // Get the byte of the end of the table.
size_t GetEndOfTable(); size_t GetEndOfTable();
// Get all of the entries in the table, as an array. // Get all of the entries in the table, as an array.

View File

@ -47,7 +47,7 @@ namespace ACPI {
// RSDP Entries themselves. // RSDP Entries themselves.
struct RSDT { struct RSDT {
ACPIHeader Header; ACPIHeader Header;
uint32_t* OtherSDTs; uint32_t OtherSDTs[];
} __attribute__((packed)); } __attribute__((packed));
RSDP(); RSDP();

View File

@ -59,14 +59,14 @@ bool APIC::IsReady() {
} }
void APIC::Init() { void APIC::Init() {
SerialPrintf("[ACPI] Enabling APICs..."); SerialPrintf("[ ACPI] Enabling APICs...\r\n");
Address = (void*) ACPI::MADT::instance->LocalAPICBase; Address = (void*) ACPI::MADT::instance->LocalAPICBase;
// TODO: Check whether the identity mapping covers this address // TODO: Check whether the identity mapping covers this address
if (Address == nullptr) { if (Address == nullptr) {
SerialPrintf("[ACPI] Unable to locate APICs."); SerialPrintf("[ ACPI] Unable to locate APICs.\r\n");
for (;;) { } for (;;) { }
} }
@ -78,9 +78,9 @@ void APIC::Init() {
WritePort(0x21, 0xFF, 1); WritePort(0x21, 0xFF, 1);
WritePort(0xA1, 0xFF, 1); WritePort(0xA1, 0xFF, 1);
SerialPrintf("[ACPI] Enabling Global APIC.."); SerialPrintf("[ ACPI] Enabling Global APIC..\r\n");
IOAPICs = ACPI::MADT::instance->GetIOApicEntries(); IOAPICs = ACPI::MADT::instance->GetIOApicEntries();
SerialPrintf("[ACPI] Enabling Interrupt Source Overrides.."); SerialPrintf("[ ACPI] Enabling Interrupt Source Overrides..\r\n");
ISOs = ACPI::MADT::instance->GetISOEntries(); ISOs = ACPI::MADT::instance->GetISOEntries();
Ready = true; Ready = true;

View File

@ -18,7 +18,9 @@
.extern initcpu .extern initcpu
.extern coreidt .extern coreidt
.extern CoreGDT
.extern ProtectedGDT
.extern LongGDT
# 16-bit startup. # 16-bit startup.
# Initialize registers. # Initialize registers.
@ -35,9 +37,9 @@ startCore:
mov %ax, %fs mov %ax, %fs
mov %ax, %gs mov %ax, %gs
mov %ax, %ss mov %ax, %ss
.code64
lgdtl gdt_protected lgdt ProtectedGDT
.code16
mov %cr0, %eax mov %cr0, %eax
or $0x1, %ax or $0x1, %ax
mov %eax, %cr0 mov %eax, %cr0
@ -74,8 +76,9 @@ startCore32:
mov %cr0, %eax mov %cr0, %eax
or $2147483648, %eax # 1 << 31 or $2147483648, %eax # 1 << 31
mov %eax, %cr0 mov %eax, %cr0
.code64
lgdt gdt_long lgdt LongGDT
.code32
ljmp $0x8, $startCore64 ljmp $0x8, $startCore64
# Long mode setup. # Long mode setup.
@ -95,7 +98,7 @@ startCore64:
mov %ax, %ds mov %ax, %ds
mov %ax, %gs mov %ax, %gs
lgdt CoreGDT lgdt LongGDT
lidt coreidt lidt coreidt
mov $0x0, %rbp mov $0x0, %rbp

View File

@ -2,6 +2,9 @@
#include <kernel/video/draw.h> #include <kernel/video/draw.h>
#include <driver/keyboard.h> #include <driver/keyboard.h>
#include <editor/main.h> #include <editor/main.h>
#include "kernel/system/acpi/rsdt.h"
#include "kernel/system/acpi/madt.h"
#include "driver/io/apic.h"
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
@ -21,7 +24,6 @@ static bool KernelLoaded = false;
address_space_t KernelAddressSpace; address_space_t KernelAddressSpace;
size_t KernelAddr = (size_t) &LoadAddr; size_t KernelAddr = (size_t) &LoadAddr;
size_t KernelEnd = (size_t) &end; size_t KernelEnd = (size_t) &end;
@ -42,7 +44,7 @@ char* InternalBuffer;
* This is a temporary measure to experiment with the Editor system. * This is a temporary measure to experiment with the Editor system.
*/ */
extern "C" int Main(void) { extern "C" [[noreturn]] int Main(void) {
KernelAddressSpace.Lock.NextTicket = 0; KernelAddressSpace.Lock.NextTicket = 0;
KernelAddressSpace.Lock.NowServing = 0; KernelAddressSpace.Lock.NowServing = 0;
KernelAddressSpace.PML4 = nullptr; KernelAddressSpace.PML4 = nullptr;
@ -86,13 +88,15 @@ extern "C" int Main(void) {
SetForegroundColor(0x00FFFFFF); SetForegroundColor(0x00FFFFFF);
ACPI::RSDP::instance->Init(0);
ACPI::MADT::instance->Init();
Device::APIC::driver->Init();
CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar); CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar);
InternalBufferID = SetupKBCallback(&TrackInternalBuffer); InternalBufferID = SetupKBCallback(&TrackInternalBuffer);
for (;;) { } for (;;) { }
return 0;
} }
extern "C" void PrintPressedChar(KeyboardData data) { extern "C" void PrintPressedChar(KeyboardData data) {

View File

@ -18,8 +18,8 @@ size_t MADT::GetEndOfTable() {
return ((size_t) &Header->Header) + Header->Header.Length; return ((size_t) &Header->Header) + Header->Header.Length;
} }
void MADT::Initialize() { void MADT::Init() {
SerialPrintf("[ACPI] Loading Multiple APIC Descriptor Tables.."); SerialPrintf("[ ACPI] Loading Multiple APIC Descriptor Tables..\r\n");
Address = ACPI::RSDP::instance->FindEntry("APIC"); Address = ACPI::RSDP::instance->FindEntry("APIC");
Header = reinterpret_cast<MADTHeader*>(Address); Header = reinterpret_cast<MADTHeader*>(Address);

View File

@ -61,23 +61,28 @@ void* RSDP::GetFACP(RSDT* Root) {
void RSDP::Init(size_t RSDP) { void RSDP::Init(size_t RSDP) {
UNUSED(RSDP); UNUSED(RSDP);
SerialPrintf("[ACPI] Loading ACPI subsystem.."); SerialPrintf("[ ACPI] Loading ACPI subsystem..\r\n");
Descriptor = (DescriptorV2*) GetRSDP(); Descriptor = (DescriptorV2*) GetRSDP();
Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT); Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT);
SerialPrintf("[RSDP] Dumping RSDT.."); SerialPrintf("[ RSDP] Dumping RSDT. Table at 0x%p..\r\n", (size_t) Table);
auto* table = reinterpret_cast<RSDP::RSDT*>(TO_DIRECT(Descriptor->Header.RSDT)); size_t entries = (Table->Header.Length - sizeof(Table->Header)) / 4;
size_t entries = (table->Header.Length - sizeof(table->Header)) / 4; SerialPrintf("[ RSDP] Found %u entries.\r\n", entries);
// For each entry: if valid, search for the specified name. // For each entry: if valid, search for the specified name.
for (size_t i = 0; i < entries; i++) { for (size_t i = 0; i < entries; i++) {
if (table->OtherSDTs[i] == 0x0) if (Table->OtherSDTs[i] == 0x0)
continue; continue;
ACPIHeader* header = reinterpret_cast<ACPIHeader*>(table->OtherSDTs[i]); ACPIHeader* header = (ACPIHeader*) ((size_t) 0 + (uint32_t) Table->OtherSDTs[i]);
SerialPrintf("[RSDP] Entry %d: Signature %.4s, OEM %.6s\n", i, header->Signature, header->OEMID); char signature[5];
memcpy(signature, header->Signature, 4);
signature[4] = '\0';
char oem[7];
memcpy(oem, header->OEMID, 6);
oem[6] = '\0';
SerialPrintf("[ RSDP] Entry %d: Signature %s, OEM %s\n", i, signature, oem);
} }
} }

View File

@ -17,7 +17,7 @@ Core Core::Processors[Constants::Core::MAX_CORES];
TSS64 Tasks[Constants::Core::MAX_CORES]; TSS64 Tasks[Constants::Core::MAX_CORES];
ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES]; ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES];
extern "C" void initcpu() { extern "C" [[noreturn]] void initcpu() {
// Init APIC // Init APIC
WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10)); WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10));
Device::APIC::driver->Enable(); Device::APIC::driver->Enable();
@ -39,9 +39,9 @@ Core::Core(size_t APIC, size_t ID) {
Bootstrap(); Bootstrap();
SetupData(ID); SetupData(ID);
Device::APIC::driver->InitializeCore(APIC, CORE_BOOTSTRAP); Device::APIC::driver->InitializeCore(APIC, reinterpret_cast<size_t>(initcpu));
while (Ready != true) { while (!Ready) {
__asm__ ("nop"); __asm__ ("nop");
} }
@ -94,12 +94,7 @@ void Core::Init() {
} }
void Core::Bootstrap() { void Core::Bootstrap() {
size_t coreStarterLen = endCore - startCore; // TODO
for (size_t i = 0; i < coreStarterLen + 2; i += PAGE_SIZE)
MapVirtualPage(AddressSpace, CORE_BOOTSTRAP + i, CORE_BOOTSTRAP + i, 0);
memcpy((void*) CORE_BOOTSTRAP, &startCore, coreStarterLen);
} }
void Core::SetupData(size_t Core) { void Core::SetupData(size_t Core) {

View File

@ -73,48 +73,11 @@ void PrepareCPU() {
SetupInitialGDT(); SetupInitialGDT();
SetupIDT(); SetupIDT();
//SetupExtensions(); //SetupExtensions();
InitInterrupts(); InitInterrupts();
} }
/*void SetupExtensions() {
// Enable SSE
size_t CR0 = ReadControlRegister(0);
CR0 &= ~(1 << 2);
CR0 |= 1;
WriteControlRegister(0, CR0);
// Enable OSXSAVE and gang
size_t CR4 = ReadControlRegister(4);
CR4 |= (1 << 9);
CR4 |= (1 << 10);
CR4 |= (1 << 18);
WriteControlRegister(4, CR4);
// Enable AVX (and AVX-512 in future)
CR0 = ReadExtendedControlRegister(0);
SerialPrintf("XCR0 is currently %x.\n", CR0);
CR0 |= (1 << 0);
CR0 |= (1 << 1);
CR0 |= (1 << 2);
CR0 |= (1 << 5);
CR0 |= (1 << 6);
CR0 |= (1 << 7);
SerialPrintf("About to write xcr0: %x\n", CR0);
WriteExtendedControlRegister(0, CR0);
}
*/
void SetupInitialGDT() { void SetupInitialGDT() {
size_t TSSBase = (uint64_t) (&TSSEntries); size_t TSSBase = (uint64_t) (&TSSEntries);

View File

@ -368,7 +368,7 @@ __attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t Erro
SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2)); SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2));
Core::GetCurrent()->StackTrace(6); Core::GetCurrent()->StackTrace(10);
ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault
} }

View File

@ -1,6 +1,4 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <kernel/system/memory.h> #include <kernel/system/memory.h>
#include <kernel/system/io.h> #include <kernel/system/io.h>

View File

@ -69,29 +69,29 @@ static int liballoc_free(void* ptr, size_t count) {
/** This macro will conveniently align our pointer upwards */ /** This macro will conveniently align our pointer upwards */
#define ALIGN(ptr) \ #define ALIGN(ptr) \
if ( ALIGNMENT > 1 ) \ if ( ALIGNMENT > 1 ) \
{ \ { \
uintptr_t diff; \ uintptr_t ldiff; \
ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \
diff = (uintptr_t)ptr & (ALIGNMENT-1); \ ldiff = (uintptr_t)ptr & (ALIGNMENT-1); \
if ( diff != 0 ) \ if ( diff != 0 ) \
{ \ { \
diff = ALIGNMENT - diff; \ ldiff = ALIGNMENT - ldiff; \
ptr = (void*)((uintptr_t)ptr + diff); \ ptr = (void*)((uintptr_t)ptr + ldiff); \
} \ } \
*((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \ *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \
diff + ALIGN_INFO; \ ldiff + ALIGN_INFO; \
} }
#define UNALIGN(ptr) \ #define UNALIGN(ptr) \
if ( ALIGNMENT > 1 ) \ if ( ALIGNMENT > 1 ) \
{ \ { \
uintptr_t diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ uintptr_t diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \
if ( diff < (ALIGNMENT + ALIGN_INFO) ) \ if ( diff < (ALIGNMENT + ALIGN_INFO) ) \
{ \ { \
ptr = (void*)((uintptr_t)ptr - diff); \ ptr = (void*)((uintptr_t)ptr - diff); \
} \ } \
} }

View File

@ -58,6 +58,16 @@ void InitPaging() {
MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS);
} }
SerialPrintf("[ Mem] Identity mapping the entire BIOS memory map.\r\n");
for (MMapEnt* MapEntry = &bootldr.mmap; (size_t) MapEntry < (size_t) &bootldr + bootldr.size; MapEntry++) {
size_t entry_from = MMapEnt_Ptr(MapEntry);
size_t entry_to = MMapEnt_Ptr(MapEntry) + MMapEnt_Size(MapEntry);
for (size_t i = entry_from; i < entry_to; i += PAGE_SIZE) {
MapVirtualPageNoDirect(&KernelAddressSpace, i, i, DEFAULT_PAGE_FLAGS);
MapVirtualPageNoDirect(&KernelAddressSpace, i, TO_DIRECT(i), DEFAULT_PAGE_FLAGS);
}
}
SerialPrintf("[ Mem] Mapping 0x%x bytes of bootloader structure, starting at 0x%p\r\n", bootldr.size, SerialPrintf("[ Mem] Mapping 0x%x bytes of bootloader structure, starting at 0x%p\r\n", bootldr.size,
BootldrAddress); BootldrAddress);
for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE) for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE)

View File

@ -175,7 +175,7 @@ void InitMemoryManager() {
MemoryPages = FreeMemorySize / PAGE_SIZE; MemoryPages = FreeMemorySize / PAGE_SIZE;
SerialPrintf("[ Mem] %u MB of memory detected.\r\n", (FreeMemorySize / 1024) / 1024); SerialPrintf("[ Mem] %u MB of usable memory detected, %u MB total.\r\n", (FreeMemorySize / 1024) / 1024, (FullMemorySize / 1024) / 1024);
} }