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/io/apic.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp
${CMAKE_SOURCE_DIR}/src/global/core-att.s
)
SET(lib_files
@ -57,6 +56,7 @@ SET(src_no_sse
)
SET(src_as
${CMAKE_SOURCE_DIR}/src/global/core-att.s
)
SET(src_preamble
@ -78,6 +78,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
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_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
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!)
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();
void LogDump();
void Initialize();
void Init();
// Get the byte of the end of the table.
size_t GetEndOfTable();
// Get all of the entries in the table, as an array.

View File

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

View File

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

View File

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

View File

@ -2,6 +2,9 @@
#include <kernel/video/draw.h>
#include <driver/keyboard.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 ***
@ -21,7 +24,6 @@ static bool KernelLoaded = false;
address_space_t KernelAddressSpace;
size_t KernelAddr = (size_t) &LoadAddr;
size_t KernelEnd = (size_t) &end;
@ -42,7 +44,7 @@ char* InternalBuffer;
* 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.NowServing = 0;
KernelAddressSpace.PML4 = nullptr;
@ -86,13 +88,15 @@ extern "C" int Main(void) {
SetForegroundColor(0x00FFFFFF);
ACPI::RSDP::instance->Init(0);
ACPI::MADT::instance->Init();
Device::APIC::driver->Init();
CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar);
InternalBufferID = SetupKBCallback(&TrackInternalBuffer);
for (;;) { }
return 0;
}
extern "C" void PrintPressedChar(KeyboardData data) {

View File

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

View File

@ -61,23 +61,28 @@ void* RSDP::GetFACP(RSDT* Root) {
void RSDP::Init(size_t RSDP) {
UNUSED(RSDP);
SerialPrintf("[ACPI] Loading ACPI subsystem..");
SerialPrintf("[ ACPI] Loading ACPI subsystem..\r\n");
Descriptor = (DescriptorV2*) GetRSDP();
Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT);
SerialPrintf("[RSDP] Dumping RSDT..");
auto* table = reinterpret_cast<RSDP::RSDT*>(TO_DIRECT(Descriptor->Header.RSDT));
size_t entries = (table->Header.Length - sizeof(table->Header)) / 4;
SerialPrintf("[ RSDP] Dumping RSDT. Table at 0x%p..\r\n", (size_t) Table);
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 (size_t i = 0; i < entries; i++) {
if (table->OtherSDTs[i] == 0x0)
if (Table->OtherSDTs[i] == 0x0)
continue;
ACPIHeader* header = reinterpret_cast<ACPIHeader*>(table->OtherSDTs[i]);
SerialPrintf("[RSDP] Entry %d: Signature %.4s, OEM %.6s\n", i, header->Signature, header->OEMID);
ACPIHeader* header = (ACPIHeader*) ((size_t) 0 + (uint32_t) Table->OtherSDTs[i]);
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];
ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES];
extern "C" void initcpu() {
extern "C" [[noreturn]] void initcpu() {
// Init APIC
WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10));
Device::APIC::driver->Enable();
@ -39,9 +39,9 @@ Core::Core(size_t APIC, size_t ID) {
Bootstrap();
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");
}
@ -94,12 +94,7 @@ void Core::Init() {
}
void Core::Bootstrap() {
size_t coreStarterLen = endCore - startCore;
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);
// TODO
}
void Core::SetupData(size_t Core) {

View File

@ -73,48 +73,11 @@ void PrepareCPU() {
SetupInitialGDT();
SetupIDT();
//SetupExtensions();
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() {
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));
Core::GetCurrent()->StackTrace(6);
Core::GetCurrent()->StackTrace(10);
ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault
}

View File

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

View File

@ -71,16 +71,16 @@ static int liballoc_free(void* ptr, size_t count) {
#define ALIGN(ptr) \
if ( ALIGNMENT > 1 ) \
{ \
uintptr_t diff; \
uintptr_t ldiff; \
ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \
diff = (uintptr_t)ptr & (ALIGNMENT-1); \
ldiff = (uintptr_t)ptr & (ALIGNMENT-1); \
if ( diff != 0 ) \
{ \
diff = ALIGNMENT - diff; \
ptr = (void*)((uintptr_t)ptr + diff); \
ldiff = ALIGNMENT - ldiff; \
ptr = (void*)((uintptr_t)ptr + ldiff); \
} \
*((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \
diff + ALIGN_INFO; \
ldiff + ALIGN_INFO; \
}

View File

@ -58,6 +58,16 @@ void InitPaging() {
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,
BootldrAddress);
for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE)

View File

@ -175,7 +175,7 @@ void InitMemoryManager() {
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);
}