From afe01f08f5797cb69bcf8e2207ef8ff9a25d1f9b Mon Sep 17 00:00:00 2001 From: nothotscott Date: Sat, 3 Apr 2021 00:13:56 -0500 Subject: [PATCH] MADT parsed --- build.ps1 | 2 +- src/kernel/kernel.h | 5 +++ src/kernel/setup.c | 12 +++-- src/kernel/x86_64/acpi.h | 18 ++++---- src/kernel/x86_64/idt.asm | 2 +- src/kernel/x86_64/io.asm | 17 +++++++ src/kernel/x86_64/io.h | 2 + src/kernel/x86_64/madt.c | 58 ++++++++++++++++++++++++ src/kernel/x86_64/madt.h | 94 +++++++++++++++++++++++++++++++++++++++ src/kernel/x86_64/pci.c | 3 +- src/kernel/x86_64/pit.h | 2 +- 11 files changed, 197 insertions(+), 18 deletions(-) create mode 100644 src/kernel/x86_64/madt.c create mode 100644 src/kernel/x86_64/madt.h diff --git a/build.ps1 b/build.ps1 index 52d3f4e..fe4cb9c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -92,7 +92,7 @@ function launch-qemu { ) $program_args = "-drive file=$ABSOLUTE_WIN/$BUILD_DIR/$OSNAME.img " $program_args += "-drive if=pflash,format=raw,unit=0,readonly=on,file=$OVMF_DIR_WIN/$OVMF_NAME " - $program_args += "-machine type=q35 -cpu qemu64 -m 512M -net none -serial stdio -no-reboot " + $program_args += "-machine type=q35 -cpu qemu64 -smp 2 -m 512M -net none -serial stdio -no-reboot " if ($debug -eq $true) { powershell.exe "Start-Process qemu-system-x86_64.exe -ArgumentList '$program_args -s -S'" } else { diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index d5cef9d..0763bbf 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -30,6 +30,11 @@ position++; \ } +typedef struct LinkedNode { + void* data; + struct LinkedNode* next; +} LinkedNode; + // From kernel.ld linker script extern void** _kernel_start; diff --git a/src/kernel/setup.c b/src/kernel/setup.c index 2af1bc5..179fed9 100644 --- a/src/kernel/setup.c +++ b/src/kernel/setup.c @@ -18,6 +18,7 @@ #include "x86_64/pit.h" #include "x86_64/acpi.h" #include "x86_64/pci.h" +#include "x86_64/madt.h" #include "x86_64/syscall.h" @@ -63,12 +64,15 @@ void setup_interrupts() { idt_load(); } -void setup_pci() { +void setup_acpi() { struct RSDP2* rsdp = g_interface->rsdp; struct SDTHeader* xsdt = (struct SDTHeader*)rsdp->xsdt_base; struct MCFGHeader* mcfg = (struct MCFGHeader*)acpi_get_table(xsdt, "MCFG"); + struct MADTHeader* madt = (struct MADTHeader*)acpi_get_table(xsdt, "APIC"); pci_init(mcfg); - pci_print(); + io_enable_apic(); + madt_init(madt); + //pci_print(); } void setup_syscall(){ @@ -86,8 +90,8 @@ void setup() { debug_output("Setup gdt\n"); setup_interrupts(); debug_output("Setup interrupts\n"); - setup_pci(); - debug_output("Setup PCI\n"); + setup_acpi(); + debug_output("Setup ACPI\n"); setup_syscall(); debug_output("Setup syscall\n"); diff --git a/src/kernel/x86_64/acpi.h b/src/kernel/x86_64/acpi.h index bcd3765..3ce27ba 100644 --- a/src/kernel/x86_64/acpi.h +++ b/src/kernel/x86_64/acpi.h @@ -39,18 +39,16 @@ struct SDTHeader { // Memory Mapped Configuration Space Access Header struct MCFGHeader { - char signature[4]; - uint32_t length; - uint8_t revision; - uint8_t checksum; - uint8_t oem_id[6]; - uint8_t oem_table_id[8]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; - uint8_t reserved[8]; + struct SDTHeader header; + uint8_t reserved[8]; } __attribute__((packed)); +// Multiple APIC Description Table Header +struct MADTHeader { + struct SDTHeader header; + uint32_t apic_address; + uint32_t flags; +} __attribute__((packed)); // Looks up and returns the ACPI table starting at [xsdt] with the [signature] struct SDTHeader* acpi_get_table(struct SDTHeader* xsdt, char* signature); \ No newline at end of file diff --git a/src/kernel/x86_64/idt.asm b/src/kernel/x86_64/idt.asm index 10005d9..4b3be8e 100644 --- a/src/kernel/x86_64/idt.asm +++ b/src/kernel/x86_64/idt.asm @@ -2,7 +2,7 @@ ;; File: idt.asm ;; Description: x86_64 Interrupt Descriptor Table functions ;; -;; Copyright 2020 Scott Maday +;; Copyright 2020-2021 Scott Maday ;; Check the LICENSE file that came with this program for licensing terms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/kernel/x86_64/io.asm b/src/kernel/x86_64/io.asm index cc93779..4ce28d8 100644 --- a/src/kernel/x86_64/io.asm +++ b/src/kernel/x86_64/io.asm @@ -6,6 +6,23 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +GLOBAL io_enable_apic +io_enable_apic: + push rax + push rcx + push rdx + + mov ecx, 0x1b ; IA32_APIC_BASE_MSR? + rdmsr + or eax, 0x800 ; IA32_APIC_BASE_MSR_ENABLE? + wrmsr + + pop rdx + pop rcx + pop rax + ret + + GLOBAL outb outb: ; rdi=[port], rsi=[value] mov rdx, rdi ; port diff --git a/src/kernel/x86_64/io.h b/src/kernel/x86_64/io.h index f9f9820..359f6c5 100644 --- a/src/kernel/x86_64/io.h +++ b/src/kernel/x86_64/io.h @@ -19,6 +19,8 @@ #define IO_PIC_EOI 0x20 +// Enables APIC +void io_enable_apic(); // Sends value out onto the processor bus on port extern void outb(uint16_t port, uint8_t value); diff --git a/src/kernel/x86_64/madt.c b/src/kernel/x86_64/madt.c new file mode 100644 index 0000000..7b2a829 --- /dev/null +++ b/src/kernel/x86_64/madt.c @@ -0,0 +1,58 @@ +/* + * File: apic.c + * ***************************************************************************** + * Copyright 2021 Scott Maday + * Check the LICENSE file that came with this program for licensing terms + */ + +#include "memory/paging.h" +#include "acpi.h" +#include "madt.h" + + +// Array of processors +static struct MADTLocalProcessor* s_processors[MADT_MAX_PROCESSORS]; +static size_t s_processors_num = 0; + + +#include +void madt_init(struct MADTHeader* madt) { + for(size_t t = 0; t < madt->header.length - sizeof(struct MADTHeader); /* Do not increment here */ ){ + struct MADTRecord* record = (struct MADTRecord*)((uint64_t)madt + sizeof(struct MADTHeader) + t); + paging_identity_map_page(record); + printf("Record type: %d size: %d\n", record->type, record->length); + t += record->length; // increment here + switch(record->type) { + case MADT_TYPE_LOCAL_PROCESSOR: + { + struct MADTLocalProcessor* processor = (struct MADTLocalProcessor*)record; + s_processors[s_processors_num] = processor; + s_processors_num++; + printf(" Processor ID: %d APIC-ID: %d Flags: %d\n", processor->processor_id, processor->apic_id, processor->flags); + } + break; + case MADT_TYPE_IOAPIC: + { + struct MADTIOAPIC* io_apic = (struct MADTIOAPIC*)record; + void* apic_ptr = (void*)(uint64_t)io_apic->apic_address; + paging_identity_map_page(apic_ptr); + printf(" IO APIC: 0x%x\n", apic_ptr); + } + break; + case MADT_TYPE_INTERRUPT_SOURCE_OVERRIDE: + { + struct MADTInterruptSourceOverride* iso = (struct MADTInterruptSourceOverride*)record; + printf(" Interrupt Source Override source: 0x%d\n", iso->source); + } + break; + case MADT_TYPE_NONMASKABLE_INTERRUPT: + { + struct MADTNonMaskableInterrupt* nmi = (struct MADTNonMaskableInterrupt*)record; + printf(" Non-Maskable Interrupt ID: %d\n", nmi->apic_id); + } + break; + case MADT_TYPE_LOCAL_APICADDRESS_OVERRIDE: + break; + } + } +} \ No newline at end of file diff --git a/src/kernel/x86_64/madt.h b/src/kernel/x86_64/madt.h new file mode 100644 index 0000000..c4254b5 --- /dev/null +++ b/src/kernel/x86_64/madt.h @@ -0,0 +1,94 @@ +/* + * File: madt.h + * Description: Parse's the MADT (APIC signature) table + * MADT stands for Multiple APIC Description Table + * The file is named this instead of apic so that it's not + * lexically confused with acpi. + * ***************************************************************************** + * Copyright 2021 Scott Maday + * Check the LICENSE file that came with this program for licensing terms + */ + +#pragma once + +#include "acpi.h" + +#define MADT_MAX_PROCESSORS 256 +#define MADT_IO_APICS 256 + +struct MADTRecord { + uint8_t type; + uint8_t length; +} __attribute__((packed)); + +// Type 0: Single physical processor and its local interrupt controller +struct MADTLocalProcessor { + struct MADTRecord record; + uint8_t processor_id; + uint8_t apic_id; + uint32_t flags; +} __attribute__((packed)); +// Type 1: IO APIC, the global system interrupt base is the first interrupt number that this IO APIC handles +struct MADTIOAPIC { + struct MADTRecord record; + uint8_t apic_id; + uint8_t reserved; + uint32_t apic_address; + uint32_t global_interrupt_base; +} __attribute__((packed)); +// Type 2: Interrupt Source Override explaining how IRQ sources are mapped to global system interrupts +struct MADTInterruptSourceOverride { + struct MADTRecord record; + uint8_t bus; // Always 0 (ISA) + uint8_t source; + uint32_t global_interrupt; + uint16_t flags; +} __attribute__((packed)); +// Type 4: Non-maskable interrupt(NMI), which is connected to each processor where it exists +struct MADTNonMaskableInterrupt { + struct MADTRecord record; + uint8_t apic_id; + uint16_t flags; + uint8_t lint; +} __attribute__((packed)); +// Type 5: Local APIC Address Override which provides 64 bit systems with an override of the physical address of the local APIC +// There should only be 1 of these +struct MADTLocalAPICAddressOverride { + struct MADTRecord record; + uint8_t reserved[2]; + uint64_t local_apic_address; +} __attribute__((packed)); + + +enum MADTType { + MADT_TYPE_LOCAL_PROCESSOR = 0, + MADT_TYPE_IOAPIC = 1, + MADT_TYPE_INTERRUPT_SOURCE_OVERRIDE = 2, + MADT_TYPE_NONMASKABLE_INTERRUPT = 4, + MADT_TYPE_LOCAL_APICADDRESS_OVERRIDE = 5 +}; + +enum MADTIOAPICTriggerMode { + MADT_IOAPIC_TRIGGER_MODE_EDGE, + MADT_IOAPIC_TRIGGER_MODE_LEVEL +}; +enum MADTIOAPICPolarity { + MADT_IOAPIC_POLARITY_ACTIVEHIGH, + MADT_IOAPIC_POLARITY_ACTIVELOW +}; +enum MADTIOAPICDestinationMode { + MADT_IOAPIC_DESTINATIONMODE_PHYSICAL, + MADT_IOAPIC_DESTINATIONMODE_LOGICAL +}; +enum MADTIOAPICDeliveryMode { + MADT_IOAPIC_DELIVERY_MODE_FIXED, + MADT_IOAPIC_DELIVERY_MODE_LOWESTPRIORITY, + MADT_IOAPIC_DELIVERY_MODE_SMI, + MADT_IOAPIC_DELIVERY_MODE_NMI = 0b100, + MADT_IOAPIC_DELIVERY_MODE_INIT, + MADT_IOAPIC_DELIVERY_MODE_EXTINT = 0b111, +}; + + +// Initializes ACPI from [madt] +void madt_init(struct MADTHeader* madt); \ No newline at end of file diff --git a/src/kernel/x86_64/pci.c b/src/kernel/x86_64/pci.c index c9a055e..cdb0d48 100644 --- a/src/kernel/x86_64/pci.c +++ b/src/kernel/x86_64/pci.c @@ -11,13 +11,14 @@ #include "pci.h" +// Array of PCI devices static struct PCIDeviceHeader* s_pci_devices[PCI_MAX_LANES]; static size_t s_pci_devices_num = 0; void pci_init(struct MCFGHeader* mcfg) { //printf("MCFG Length %d\n", mcfg->length); - for(size_t t = 0; t < mcfg->length - sizeof(struct MCFGHeader); t += sizeof(struct PCIDeviceConfigurationDescriptor)){ + for(size_t t = 0; t < mcfg->header.length - sizeof(struct MCFGHeader); t += sizeof(struct PCIDeviceConfigurationDescriptor)){ struct PCIDeviceConfigurationDescriptor* descriptor = (struct PCIDeviceConfigurationDescriptor*)((uint64_t)mcfg + sizeof(struct MCFGHeader) + t); for(uint8_t bus_i = descriptor->bus_start; bus_i < descriptor->bus_end; bus_i++) { void* bus = (void*)descriptor->base + ((uint64_t)bus_i << 20); diff --git a/src/kernel/x86_64/pit.h b/src/kernel/x86_64/pit.h index ab03d4f..ab3486f 100644 --- a/src/kernel/x86_64/pit.h +++ b/src/kernel/x86_64/pit.h @@ -11,7 +11,7 @@ #define PIT_BASE_FREQUENCY 1193182 #define PIT_MAX_DIVISOR 65535 -#define PIT_DEFAULT_DIVISOR PIT_MAX_DIVISOR / 10 +#define PIT_DEFAULT_DIVISOR PIT_MAX_DIVISOR #define PIT_PORT 0x40