Parse acpi data table

This commit is contained in:
Thomas Lovén 2022-01-16 23:59:38 +01:00
parent 6a033344b5
commit 95108d1c0a
4 changed files with 173 additions and 7 deletions

View File

@ -20,7 +20,7 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
kernel_boot_data.commandline, kernel_boot_data.commandline,
kernel_boot_data.bootloader); kernel_boot_data.bootloader);
cpu_init(); early_cpu_init();
debug_info("Set up boot CPU\n"); debug_info("Set up boot CPU\n");
memory_init(); memory_init();
debug_info("Set up memory management\n"); debug_info("Set up memory management\n");
@ -28,15 +28,13 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
terminal_init(); terminal_init();
debug_info("Set up debug terminal\n"); debug_info("Set up debug terminal\n");
cpu_init();
debug_info("Boot complete\n"); debug_info("Boot complete\n");
TEMP_test_scheduler(); 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(); start_scheduler();

133
src/kernel/cpu/acpi.c Normal file
View File

@ -0,0 +1,133 @@
#include <cpu.h>
#include <multiboot.h>
#include <memory.h>
#include <string.h>
#include <debug.h>
// 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:
}
}
}
}
}

View File

@ -1,6 +1,18 @@
#include <cpu.h>
#include <cpu/interrupts.h> #include <cpu/interrupts.h>
#include <ports.h>
void cpu_init() 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(); interrupt_init();
} }
void cpu_init()
{
acpi_parse();
}

View File

@ -1,6 +1,26 @@
#pragma once #pragma once
#include <stdint.h>
#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 // cpu/cpu.c
void early_cpu_init();
void cpu_init(); void cpu_init();
// cpu/registers.S // cpu/registers.S
@ -8,3 +28,6 @@ void load_idt(void *);
void write_cr3(uint64_t); void write_cr3(uint64_t);
uint64_t read_msr(uint32_t); uint64_t read_msr(uint32_t);
uint64_t write_msr(uint32_t msr, uint64_t value); uint64_t write_msr(uint32_t msr, uint64_t value);
// cpu/acpi.c
void acpi_parse();