Parse acpi data table
This commit is contained in:
parent
6a033344b5
commit
95108d1c0a
@ -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();
|
||||
|
||||
|
133
src/kernel/cpu/acpi.c
Normal file
133
src/kernel/cpu/acpi.c
Normal 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:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,18 @@
|
||||
#include <cpu.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();
|
||||
}
|
||||
|
||||
void cpu_init()
|
||||
{
|
||||
acpi_parse();
|
||||
}
|
@ -1,6 +1,26 @@
|
||||
#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
|
||||
void early_cpu_init();
|
||||
void cpu_init();
|
||||
|
||||
// cpu/registers.S
|
||||
@ -8,3 +28,6 @@ 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);
|
||||
|
||||
// cpu/acpi.c
|
||||
void acpi_parse();
|
Loading…
x
Reference in New Issue
Block a user