From 95108d1c0aab1cb57f158ca2ebb09ab3c10f361f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Sun, 16 Jan 2022 23:59:38 +0100 Subject: [PATCH] Parse acpi data table --- src/kernel/boot/kmain.c | 8 +-- src/kernel/cpu/acpi.c | 133 +++++++++++++++++++++++++++++++++++++++ src/kernel/cpu/cpu.c | 14 ++++- src/kernel/include/cpu.h | 25 +++++++- 4 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 src/kernel/cpu/acpi.c diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index 9311b1b..19c2f37 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -20,7 +20,7 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) kernel_boot_data.commandline, kernel_boot_data.bootloader); - cpu_init(); + early_cpu_init(); debug_info("Set up boot CPU\n"); memory_init(); debug_info("Set up memory management\n"); @@ -28,15 +28,13 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) terminal_init(); debug_info("Set up debug terminal\n"); + cpu_init(); + debug_info("Boot complete\n"); TEMP_test_scheduler(); - debug("Read MSR APIC_BASE: %lx\n", read_msr(0x0000001B)); - debug("Read MSR SYSCALL_TARGET: %lx\n", read_msr(0xC0000082)); - write_msr(0xC0000082, 0x1234567890abcdef); - debug("Read MSR SYSCALL_TARGET: %lx\n", read_msr(0xC0000082)); start_scheduler(); diff --git a/src/kernel/cpu/acpi.c b/src/kernel/cpu/acpi.c new file mode 100644 index 0000000..de4100b --- /dev/null +++ b/src/kernel/cpu/acpi.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +// ACPI Specification https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf + +struct rsdp // 5.2.5.3 +{ + char signature[8]; + uint8_t checksum; + char OEMID[6]; + uint8_t revision; + uint32_t rsdt_p; + uint32_t length; // only if revision >= 2 + uint64_t xsdt_p; // only if revision >= 2 + uint8_t checksum2; // only if revision >= 2 + uint8_t reserved[3]; // only if revision >= 2 +}__attribute__((packed)); + +struct sdt_header // 5.2.6 +{ + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char OEMID[6]; + char OEMtable[8]; + uint32_t OEMrevision; + uint32_t creatorID; + uint32_t creatorRevision; + uint8_t data[]; +}__attribute__((packed)); + +struct madt_header // 5.2.12 +{ + uint32_t controllerAddress; + uint32_t flags; + uint8_t fields[]; +}__attribute__((packed)); + +struct madt_field +{ + uint8_t type; + uint8_t length; + uint8_t data[]; +}__attribute__((packed)); + +// MADT field type: 0 +#define MADT_TYPE_LAPIC 0 +struct madt_data_lapic +{ // 5.2.12.2 + uint8_t id; + uint8_t apic; + uint32_t flags; +}__attribute__((packed)); + +// MADT field type: 1 +#define MADT_TYPE_IOAPIC 1 +struct madt_data_ioapic +{ // 5.2.12.3 + uint8_t id; + uint8_t reserved; + uint32_t address; + uint32_t base; +}__attribute__((packed)); + +// MADT field type: 2 +#define MADT_TYPE_ISO 2 +struct madt_data_iso +{ // 5.2.12.5 + uint8_t bus; + uint8_t source; + uint32_t interrupt; + uint16_t flags; +}__attribute__((packed)); + + +void acpi_parse() +{ + int cpu_i=0; + + struct rsdp *rsdp = kernel_boot_data.rsdp; + struct sdt_header *rsdt = P2V(rsdp->rsdt_p); + + uint32_t *table = (void *)rsdt->data; + int entries = (rsdt->length - sizeof(struct sdt_header))/sizeof(uint32_t); + for(int i = 0; i < entries; i++) + { + struct sdt_header *h = P2V(table[i]); + if(h->length == 0) continue; + + if(!strncmp(h->signature, "APIC", 4)) // 5.2.12 + { + struct madt_header *madt = P2V(h->data); + for( + struct madt_field *f = (void *)madt->fields; + (size_t)f <= (size_t)h + h->length; + f = incptr(f, f->length) + ) + { + switch(f->type) { + case MADT_TYPE_LAPIC: + { + struct madt_data_lapic *lapic = (void *)f->data; + struct cpu *cpu = P2V(pmm_alloc()); + cpus[cpu_i++] = cpu; + cpu->id = lapic->id; + cpu->apic_id = lapic->apic; + cpu->flags = lapic->flags; + break; + } + case MADT_TYPE_IOAPIC: + { + struct madt_data_ioapic *_ioapic = (void *)f->data; + ioapic.id = _ioapic->id; + ioapic.addr = _ioapic->address; + ioapic.base = _ioapic->base; + break; + } + case MADT_TYPE_ISO: + { + struct madt_data_iso *iso = (void *)f->data; + irq_redirects[iso->source] = iso->interrupt; + break; + } + default: + } + } + } + } +} \ No newline at end of file diff --git a/src/kernel/cpu/cpu.c b/src/kernel/cpu/cpu.c index fd506bc..03e7f7b 100644 --- a/src/kernel/cpu/cpu.c +++ b/src/kernel/cpu/cpu.c @@ -1,6 +1,18 @@ +#include #include +#include + +struct cpu *cpus[16]; +struct ioapic ioapic = {0,0,0}; +uint8_t irq_redirects[MAX_IRQS] = \ + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; + +void early_cpu_init() +{ + interrupt_init(); +} void cpu_init() { - interrupt_init(); + acpi_parse(); } \ No newline at end of file diff --git a/src/kernel/include/cpu.h b/src/kernel/include/cpu.h index 2b28c96..f51e8f4 100644 --- a/src/kernel/include/cpu.h +++ b/src/kernel/include/cpu.h @@ -1,10 +1,33 @@ #pragma once +#include + +#define MAX_CPUS 16 +#define MAX_IRQS 24 + +struct cpu { + uint8_t id; + uint8_t apic_id; + uint32_t flags; +}; +struct ioapic { + uint8_t id; + uint32_t addr; + uint32_t base; +}; + +extern struct cpu *cpus[MAX_CPUS]; +extern struct ioapic ioapic; +extern uint8_t irq_redirects[MAX_IRQS]; // cpu/cpu.c +void early_cpu_init(); void cpu_init(); // cpu/registers.S void load_idt(void *); void write_cr3(uint64_t); uint64_t read_msr(uint32_t); -uint64_t write_msr(uint32_t msr, uint64_t value); \ No newline at end of file +uint64_t write_msr(uint32_t msr, uint64_t value); + +// cpu/acpi.c +void acpi_parse(); \ No newline at end of file