diff --git a/kernel/Makefile b/kernel/Makefile index 7bf1df2..060fbb9 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -17,7 +17,7 @@ CFLAGS += -I. \ -DUACPI_BAREBONES_MODE ifeq ($(ARCH),x86_64) -CFLAGS += -I./hal/x86_64/uACPI/include + CFLAGS += -Ihal/x86_64/uACPI/include endif ifeq ($(PUTCHAR_),fb) @@ -58,8 +58,7 @@ SRCFILES := $(wildcard *.c) \ $(wildcard flanterm/src/flanterm_backends/*.c) ifeq ($(ARCH),x86_64) -SRCFILES += $(wildcard hal/x86_64/uACPI/source/*.c) -SRCFILES += $(wildcard hal/x86_64/port-uACPI/*.c) + SRCFILES += $(wildcard hal/x86_64/uACPI/source/*.c) endif CFILES := $(filter %.c,$(SRCFILES)) diff --git a/kernel/hal/x86_64/acpi.c b/kernel/hal/x86_64/acpi.c index 25e4bf6..dd2c75f 100644 --- a/kernel/hal/x86_64/acpi.c +++ b/kernel/hal/x86_64/acpi.c @@ -1,24 +1,59 @@ #include #include -#include "uacpi/uacpi.h" -#include "uacpi/utilities.h" #include "hal/hal.h" #include "kprintf.h" #include "dlmalloc/malloc.h" +#include "compiler/attr.h" +#include "acpi.h" +#include "assert.h" +#include "util/util.h" +#include "bootinfo/bootinfo.h" +#include "uacpi/uacpi.h" -#define PREINIT_BUFFER_SIZE 0x1000 +// uACPI -struct acpi_madt *MADT; +void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char *s) { + char *t = NULL; + switch (lvl) { + case UACPI_LOG_INFO: t = "Info"; break; + case UACPI_LOG_WARN: t = "Warn"; break; + case UACPI_LOG_DEBUG: t = "Dbg"; break; + case UACPI_LOG_ERROR: t = "Err"; break; + case UACPI_LOG_TRACE: t = "Trc"; break; + } + LOG("uACPI", "%s %s", t, s); +} + +void uacpi_kernel_unmap(void *addr, uacpi_size len) { + // . +} + +void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) { + return (void *)(BOOT_INFO.hhdm_off + addr); +} + +uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out) { + *out = BOOT_INFO.rsdp; + return UACPI_STATUS_OK; +} void acpi_init(void) { - uacpi_status ret; + uacpi_status r; - void *preinit_buffer = dlmalloc(PREINIT_BUFFER_SIZE); - ret = uacpi_setup_early_table_access(preinit_buffer, PREINIT_BUFFER_SIZE); - if (uacpi_unlikely_error(ret)) { - ERR("acpi", "init err %s\n", uacpi_status_to_string(ret)); + size_t tmpbufsize = 0x1000; + void *tmpbuf = dlmalloc(tmpbufsize); + if (tmpbuf == NULL) { + ERR("hal", "could not allocate uACPI tmp buf\n"); hal_hang(); } + r = uacpi_setup_early_table_access(tmpbuf, tmpbufsize); + if (uacpi_unlikely_error(r)) { + ERR("hal", "uACPI init early table failed\n"); + hal_hang(); + } LOG("hal", "acpi init\n"); } + +/* uint32_t acpi_remapirq(uint32_t irq) { */ +/* } */ diff --git a/kernel/hal/x86_64/acpi.h b/kernel/hal/x86_64/acpi.h index f90366f..e49edb5 100644 --- a/kernel/hal/x86_64/acpi.h +++ b/kernel/hal/x86_64/acpi.h @@ -1,10 +1,9 @@ #ifndef HAL_ACPI_H_ #define HAL_ACPI_H_ -#include "uacpi/uacpi.h" - -extern struct acpi_madt *MADT; +#include void acpi_init(void); +uint32_t acpi_remapirq(uint32_t irq); #endif // HAL_ACPI_H_ diff --git a/kernel/hal/x86_64/apic.c b/kernel/hal/x86_64/apic.c new file mode 100644 index 0000000..987c447 --- /dev/null +++ b/kernel/hal/x86_64/apic.c @@ -0,0 +1,179 @@ +#include +#include +#include "apic.h" +#include "uacpi/tables.h" +#include "uacpi/acpi.h" +#include "kprintf.h" +#include "hal/hal.h" +#include "dlmalloc/malloc.h" +#include "bootinfo/bootinfo.h" +#include "assert.h" +#include "util/util.h" +#include "cpu.h" +#include "util/mmio.h" + +#define IOAPIC_IOREGSEL 0x00 +#define IOAPIC_IOWIN 0x10 + +#define IOAPIC_IOAPICID 0x00 +#define IOAPIC_IOAPICVER 0x01 +#define IOAPIC_IOAPICARB 0x02 +#define IOAPIC_IOREDTBL 0x10 + +#define LAPIC_ID 0x0020 +#define LAPIC_VER 0x0030 +#define LAPIC_TPR 0x0080 +#define LAPIC_APR 0x0090 +#define LAPIC_PPR 0x00A0 +#define LAPIC_EOI 0x00B0 +#define LAPIC_RRD 0x00C0 +#define LAPIC_LDR 0x00D0 +#define LAPIC_DFR 0x00E0 +#define LAPIC_SVR 0x00F0 +#define LAPIC_ISR 0x0100 +#define LAPIC_TMR 0x0180 +#define LAPIC_IRR 0x0200 +#define LAPIC_ESR 0x0280 +#define LAPIC_ICRLO 0x0300 +#define LAPIC_ICRHI 0x0310 +#define LAPIC_TIMER 0x0320 +#define LAPIC_THERMAL 0x0330 +#define LAPIC_PERF 0x0340 +#define LAPIC_LINT0 0x0350 +#define LAPIC_LINT1 0x0360 +#define LAPIC_ERROR 0x0370 +#define LAPIC_TICR 0x0380 +#define LAPIC_TCCR 0x0390 +#define LAPIC_TDCR 0x03E0 + +#define ICR_FIXED 0x00000000 +#define ICR_LOWEST 0x00000100 +#define ICR_SMI 0x00000200 +#define ICR_NMI 0x00000400 +#define ICR_INIT 0x00000500 +#define ICR_STARTUP 0x00000600 +#define ICR_PHYS 0x00000000 +#define ICR_LOGC 0x00000800 +#define ICR_IDLE 0x00000000 +#define ICR_SEND_PENDING 0x00001000 +#define ICR_DEASSERT 0x00000000 +#define ICR_ASSERT 0x00004000 +#define ICR_EDGE 0x00000000 +#define ICR_LEVEL 0x00008000 +#define ICR_NO_SHORTHAND 0x00000000 +#define ICR_SELF 0x00040000 +#define ICR_ALL_INC_SELF 0x00080000 +#define ICR_ALL_EXCL_SELF 0x000C0000 + +#define ICR_DEST_SHIFT 24 + +typedef struct LApic { + struct LApic *next; + uint8_t id; +} LApic; + +struct acpi_madt *MADT = NULL; +uint8_t *IOAPIC; +uint8_t *LAPIC; +LApic *LAPICS = NULL; + +void ioapic_write(uint8_t *base, uint8_t reg, uint32_t data) { + mmiowrite32(base + IOAPIC_IOREGSEL, reg); + mmiowrite32(base + IOAPIC_IOWIN, data); +} + +uint32_t ioapic_read(uint8_t *base, uint8_t reg) { + mmiowrite32(base + IOAPIC_IOREGSEL, reg); + return mmioread32(base + IOAPIC_IOWIN); +} + +void ioapic_setentry(uint8_t *base, uint8_t idx, uint64_t data) { + ioapic_write(base, IOAPIC_IOREDTBL + idx * 2, (uint32_t) data); + ioapic_write(base, IOAPIC_IOREDTBL + idx * 2 + 1, (uint32_t) (data >> 32)); +} + +void ioapic_init(void) { + uint32_t x = ioapic_read(IOAPIC, IOAPIC_IOAPICVER); + uint32_t count = ((x >> 16) & 0xff) + 1; + LOG("hal", "IOAPIC pins = %d\n", count); + + for (uint32_t i = 0; i < count; i++) { + ioapic_setentry(IOAPIC, i, 1 << 16); + } +} + +uint32_t lapic_read(uint32_t reg) { + return mmioread32(LAPIC + reg); +} + +void lapic_write(uint32_t reg, uint32_t data) { + mmiowrite32(LAPIC + reg, data); +} + +void lapic_init(void) { + lapic_write(LAPIC_TPR, 0); + lapic_write(LAPIC_DFR, 0xffffffff); + lapic_write(LAPIC_LDR, 0x01000000); + lapic_write(LAPIC_SVR, 0x100 | 0xff); +} + +uint32_t lapic_getid(void) { + return lapic_read(LAPIC_ID) >> 24; +} + +void lapic_sendinit(uint32_t id) { + lapic_write(LAPIC_ICRHI, id << ICR_DEST_SHIFT); + lapic_write(LAPIC_ICRLO, ICR_INIT | ICR_PHYS | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND); + while (lapic_read(LAPIC_ICRLO) & ICR_SEND_PENDING); +} + +void lapic_sendstartup(uint32_t id, uint32_t vec) { + lapic_write(LAPIC_ICRHI, id << ICR_DEST_SHIFT); + lapic_write(LAPIC_ICRLO, vec | ICR_STARTUP | ICR_PHYS | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND); + while (lapic_read(LAPIC_ICRLO) & ICR_SEND_PENDING); +} + +void apic_init(void) { + uacpi_status r; + + uacpi_table madt; + r = uacpi_table_find_by_signature("APIC", &madt); + if (r != UACPI_STATUS_OK) { + ERR("hal", "could not find MADT\n"); + hal_hang(); + } + MADT = madt.ptr; + + LAPIC = (uint8_t *)(MADT->local_interrupt_controller_address + BOOT_INFO.hhdm_off); + + uint64_t cur = (uint64_t)&MADT->entries; + uint64_t end = cur + MADT->hdr.length; + + while (cur < end) { + struct acpi_entry_hdr *ent = (struct acpi_entry_hdr *)cur; + + if (ent->type == ACPI_MADT_ENTRY_TYPE_IOAPIC) { + struct acpi_madt_ioapic *ioapic = (struct acpi_madt_ioapic *)ent; + IOAPIC = (uint8_t *)(ioapic->address + BOOT_INFO.hhdm_off); + LOG("hal", "IOAPIC p=%p v=%p id=%d gsi=%d\n", ioapic->address, IOAPIC, ioapic->id, ioapic->gsi_base); + } else if (ent->type == ACPI_MADT_ENTRY_TYPE_LAPIC) { + struct acpi_madt_lapic *lapic = (struct acpi_madt_lapic *)ent; + + LApic *new = dlmalloc(sizeof(*new)); + ASSERT("hal", new != NULL, "out of memory\n"); + new->id = lapic->id; + LL_APPEND(LAPICS, new); + LOG("hal", "LAPIC id=%d\n", lapic->id); + } else if (ent->type == ACPI_MADT_ENTRY_TYPE_LAPIC_ADDRESS_OVERRIDE) { + struct acpi_madt_lapic_address_override *override= (struct acpi_madt_lapic_address_override *)ent; + uint8_t *prev = LAPIC; + LAPIC = (uint8_t *)(override->address + BOOT_INFO.hhdm_off); + LOG("hal", "LAPIC override %p -> %p (v)\n", prev, LAPIC); + } + + cur += ent->length; + } + + lapic_init(); + ioapic_init(); +} diff --git a/kernel/hal/x86_64/apic.h b/kernel/hal/x86_64/apic.h new file mode 100644 index 0000000..3512300 --- /dev/null +++ b/kernel/hal/x86_64/apic.h @@ -0,0 +1,6 @@ +#ifndef HAL_APIC_H_ +#define HAL_APIC_H_ + +void apic_init(void); + +#endif // HAL_APIC_H_ diff --git a/kernel/hal/x86_64/hal.c b/kernel/hal/x86_64/hal.c index 8c87ea6..54961b4 100644 --- a/kernel/hal/x86_64/hal.c +++ b/kernel/hal/x86_64/hal.c @@ -5,7 +5,9 @@ #include "serial.h" #include "gdt.h" #include "acpi.h" -#include "isr.h" +#include "intr.h" +#include "pic.h" +#include "apic.h" void hal_init(void) { if (!serial_init()) { @@ -22,7 +24,9 @@ __attribute__((noreturn)) void hal_hang(void) { } void hal_init_withmalloc(void) { - /* acpi_init(); */ - isr_init(); + acpi_init(); + pic_init(); + apic_init(); + intr_init(); } diff --git a/kernel/hal/x86_64/intr.S b/kernel/hal/x86_64/intr.S deleted file mode 100644 index 520b0eb..0000000 --- a/kernel/hal/x86_64/intr.S +++ /dev/null @@ -1,9 +0,0 @@ -.global hal_intr_enable -hal_intr_enable: - sti - ret - -.global hal_intr_disable -hal_intr_disable: - cli - ret diff --git a/kernel/hal/x86_64/intr.c b/kernel/hal/x86_64/intr.c new file mode 100644 index 0000000..5ab9b76 --- /dev/null +++ b/kernel/hal/x86_64/intr.c @@ -0,0 +1,183 @@ +#include +#include +#include "intr.h" +#include "io.h" +#include "gdt.h" +#include "hal/hal.h" +#include "kprintf.h" +#include "compiler/attr.h" + +void hal_intr_disable(void) { + asm volatile("cli"); +} + +void hal_intr_enable(void) { + asm volatile("sti"); +} + +typedef struct { + uint16_t intrlow; + uint16_t kernelcs; + uint8_t ist; + uint8_t attrs; + uint16_t intrmid; + uint32_t intrhigh; + uint32_t resv; +} PACKED IdtGate; + +typedef struct { + uint16_t limit; + uint64_t base; +} PACKED Idt; + +#define ENTRIES 256 +ALIGNED(0x10) static IdtGate idtgates[ENTRIES] = {0}; +static Idt idt = {0}; + +void idt_setentry(int i, uint64_t handler, uint8_t ist, uint8_t flags) { + idtgates[i].intrlow = handler & 0xffff; + idtgates[i].kernelcs = KCODE; + idtgates[i].ist = ist; + idtgates[i].attrs = flags; + idtgates[i].intrmid = (handler >> 16) & 0xFFFF; + idtgates[i].intrhigh = (handler >> 32) & 0xFFFFFFFF; + idtgates[i].resv = 0; +} + +void idt_init(void) { + idt.base = (uint64_t)&idtgates; + idt.limit = ENTRIES * sizeof(IdtGate) - 1; + asm volatile("lidt %0" :: "m"(idt) : "memory"); + + LOG("hal", "idt init\n"); +} + +typedef struct { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; +} PACKED CpuRegs; + +typedef struct { + uint64_t cr8; + uint64_t cr4; + uint64_t cr3; + uint64_t cr2; + uint64_t cr0; +} PACKED CpuCtrlRegs; + +typedef struct { + CpuCtrlRegs ctrl; + CpuRegs regs; + uint64_t trapnum; + uint64_t errnum; + + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} PACKED IntrStackFrame; + +extern void *ISR_REDIRTABLE[]; + +static const char *exceptions[] = { + "#DE", "#DB", "NMI", + "#BP", "#OF", "#BR", + "#UD", "#NM", "#DF", + "CSO", "#TS", "#NP", + "#SS", "#GP", "#PF", + "RES", "#MF", "#AC", + "#MC", "#XM", "#VE", + "#CP", +}; + +extern void intr_vec0(void); +extern void intr_vec1(void); +extern void intr_vec2(void); +extern void intr_vec3(void); +extern void intr_vec4(void); +extern void intr_vec5(void); +extern void intr_vec6(void); +extern void intr_vec7(void); +extern void intr_vec8(void); +extern void intr_vec10(void); +extern void intr_vec11(void); +extern void intr_vec12(void); +extern void intr_vec13(void); +extern void intr_vec14(void); +extern void intr_vec16(void); +extern void intr_vec17(void); +extern void intr_vec18(void); +extern void intr_vec19(void); +extern void intr_vec20(void); +extern void intr_vec21(void); +extern void intr_vec32(void); +extern void intr_vec33(void); +extern void intr_vec39(void); + +void intr_init(void) { + idt_setentry(0, (uint64_t)&intr_vec0, 0, 0x8E); + idt_setentry(1, (uint64_t)&intr_vec1, 0, 0x8E); + idt_setentry(2, (uint64_t)&intr_vec2, 2, 0x8E); + idt_setentry(3, (uint64_t)&intr_vec3, 0, 0x8E); + idt_setentry(4, (uint64_t)&intr_vec4, 0, 0x8E); + idt_setentry(5, (uint64_t)&intr_vec5, 0, 0x8E); + idt_setentry(6, (uint64_t)&intr_vec6, 0, 0x8E); + idt_setentry(7, (uint64_t)&intr_vec7, 0, 0x8E); + idt_setentry(8, (uint64_t)&intr_vec8, 1, 0x8E); + idt_setentry(10, (uint64_t)&intr_vec10, 0, 0x8E); + idt_setentry(11, (uint64_t)&intr_vec11, 0, 0x8E); + idt_setentry(12, (uint64_t)&intr_vec12, 0, 0x8E); + idt_setentry(13, (uint64_t)&intr_vec13, 0, 0x8E); + idt_setentry(14, (uint64_t)&intr_vec14, 0, 0x8E); + idt_setentry(16, (uint64_t)&intr_vec16, 0, 0x8E); + idt_setentry(17, (uint64_t)&intr_vec17, 0, 0x8E); + idt_setentry(18, (uint64_t)&intr_vec18, 0, 0x8E); + idt_setentry(19, (uint64_t)&intr_vec19, 0, 0x8E); + idt_setentry(20, (uint64_t)&intr_vec20, 0, 0x8E); + idt_setentry(21, (uint64_t)&intr_vec21, 0, 0x8E); + idt_setentry(32, (uint64_t)&intr_vec32, 0, 0x8E); + idt_setentry(33, (uint64_t)&intr_vec33, 0, 0x8E); + idt_setentry(39, (uint64_t)&intr_vec39, 0, 0x8E); + + idt_init(); +} + +void intr_dumpframe(IntrStackFrame *frame) { + kprintf("r15=%016lx r14=%016lx r13=%016lx r12=%016lx\n" + "r11=%016lx r10=%016lx r9 =%016lx r8 =%016lx\n" + "rsi=%016lx rdi=%016lx rbp=%016lx rdx=%016lx\n" + "rcx=%016lx rbx=%016lx rax=%016lx\n" + "cr8=%016lx cr4=%016lx cr3=%016lx cr2=%016lx\n" + "cr0=%016lx rip=%016lx cs =%016lx rfl=%016lx\n" + "rsp=%016lx ss =%016lx trp=%016lx err=%016lx\n", + frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12, + frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8, + frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx, + frame->regs.rcx, frame->regs.rbx, frame->regs.rax, + frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3, + frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags, + frame->rsp, frame->ss, frame->trapnum, frame->errnum + ); +} + +void intr_handleintr(IntrStackFrame *frame) { + hal_intr_disable(); + ERR("ERROR", "%s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum); + intr_dumpframe(frame); + hal_hang(); +} + diff --git a/kernel/hal/x86_64/intr.h b/kernel/hal/x86_64/intr.h new file mode 100644 index 0000000..6bf61bf --- /dev/null +++ b/kernel/hal/x86_64/intr.h @@ -0,0 +1,8 @@ +#ifndef HAL_INTR_H_ +#define HAL_INTR_H_ + +#define INTR_IRQBASE 0x20 + +void intr_init(void); + +#endif // HAL_INTR_H_ diff --git a/kernel/hal/x86_64/isr0.S b/kernel/hal/x86_64/intr0.S similarity index 73% rename from kernel/hal/x86_64/isr0.S rename to kernel/hal/x86_64/intr0.S index 318ec96..588a6db 100644 --- a/kernel/hal/x86_64/isr0.S +++ b/kernel/hal/x86_64/intr0.S @@ -1,28 +1,28 @@ -.extern isr_handleintr +.extern intr_handleintr -.global isr_vec0 -.global isr_vec1 -.global isr_vec2 -.global isr_vec3 -.global isr_vec4 -.global isr_vec5 -.global isr_vec6 -.global isr_vec7 -.global isr_vec8 -.global isr_vec10 -.global isr_vec11 -.global isr_vec12 -.global isr_vec13 -.global isr_vec14 -.global isr_vec16 -.global isr_vec17 -.global isr_vec18 -.global isr_vec19 -.global isr_vec20 -.global isr_vec21 -.global isr_vec32 -.global isr_vec33 -.global isr_vec39 +.global intr_vec0 +.global intr_vec1 +.global intr_vec2 +.global intr_vec3 +.global intr_vec4 +.global intr_vec5 +.global intr_vec6 +.global intr_vec7 +.global intr_vec8 +.global intr_vec10 +.global intr_vec11 +.global intr_vec12 +.global intr_vec13 +.global intr_vec14 +.global intr_vec16 +.global intr_vec17 +.global intr_vec18 +.global intr_vec19 +.global intr_vec20 +.global intr_vec21 +.global intr_vec32 +.global intr_vec33 +.global intr_vec39 .macro _PUSHAQ push %rax @@ -99,77 +99,77 @@ .macro _vecintr_bodygen cld mov %rsp, %rdi - call isr_handleintr + call intr_handleintr _vecintr_restore iretq .endm -isr_vec0: +intr_vec0: _vecintr_plain_save 0, 0 _vecintr_bodygen -isr_vec1: +intr_vec1: _vecintr_plain_save 1, 0 _vecintr_bodygen -isr_vec2: +intr_vec2: _vecintr_plain_save 2, 0 _vecintr_bodygen -isr_vec3: +intr_vec3: _vecintr_plain_save 3, 0 _vecintr_bodygen -isr_vec4: +intr_vec4: _vecintr_plain_save 4, 0 _vecintr_bodygen -isr_vec5: +intr_vec5: _vecintr_plain_save 5, 0 _vecintr_bodygen -isr_vec6: +intr_vec6: _vecintr_plain_save 6, 0 _vecintr_bodygen -isr_vec7: +intr_vec7: _vecintr_plain_save 7, 0 _vecintr_bodygen -isr_vec8: +intr_vec8: _vecintr_errorcode_present_save 8 _vecintr_bodygen -isr_vec10: +intr_vec10: _vecintr_errorcode_present_save 10 _vecintr_bodygen -isr_vec11: +intr_vec11: _vecintr_errorcode_present_save 11 _vecintr_bodygen -isr_vec12: +intr_vec12: _vecintr_errorcode_present_save 12 _vecintr_bodygen -isr_vec13: +intr_vec13: _vecintr_errorcode_present_save 13 _vecintr_bodygen -isr_vec14: +intr_vec14: _vecintr_errorcode_present_save 14 _vecintr_bodygen -isr_vec16: +intr_vec16: _vecintr_plain_save 16, 0 _vecintr_bodygen -isr_vec17: +intr_vec17: _vecintr_errorcode_present_save 17 _vecintr_bodygen -isr_vec18: +intr_vec18: _vecintr_plain_save 18, 0 _vecintr_bodygen -isr_vec19: +intr_vec19: _vecintr_plain_save 19, 0 _vecintr_bodygen -isr_vec20: +intr_vec20: _vecintr_plain_save 20, 0 _vecintr_bodygen -isr_vec21: +intr_vec21: _vecintr_errorcode_present_save 21 _vecintr_bodygen -isr_vec32: +intr_vec32: _vecintr_plain_save 32, 0 _vecintr_bodygen -isr_vec33: +intr_vec33: _vecintr_plain_save 33, 0 _vecintr_bodygen -isr_vec39: +intr_vec39: _vecintr_plain_save 39, 0 _vecintr_bodygen diff --git a/kernel/hal/x86_64/isr.c b/kernel/hal/x86_64/isr.c deleted file mode 100644 index aa589d4..0000000 --- a/kernel/hal/x86_64/isr.c +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include -#include "isr.h" -#include "io.h" -#include "gdt.h" -#include "hal/hal.h" -#include "kprintf.h" -#include "compiler/attr.h" - -typedef struct { - uint16_t isrlow; - uint16_t kernelcs; - uint8_t ist; - uint8_t attrs; - uint16_t isrmid; - uint32_t isrhigh; - uint32_t resv; -} PACKED IdtGate; - -typedef struct { - uint16_t limit; - uint64_t base; -} PACKED Idt; - -#define ENTRIES 256 -ALIGNED(0x10) static IdtGate idtgates[ENTRIES] = {0}; -static Idt idt = {0}; - -void idt_setentry(int i, uint64_t handler, uint8_t ist, uint8_t flags) { - idtgates[i].isrlow = handler & 0xffff; - idtgates[i].kernelcs = KCODE; - idtgates[i].ist = ist; - idtgates[i].attrs = flags; - idtgates[i].isrmid = (handler >> 16) & 0xFFFF; - idtgates[i].isrhigh = (handler >> 32) & 0xFFFFFFFF; - idtgates[i].resv = 0; -} - -void idt_init(void) { - idt.base = (uint64_t)&idtgates; - idt.limit = ENTRIES * sizeof(IdtGate) - 1; - asm volatile("lidt %0" :: "m"(idt) : "memory"); - - LOG("idt", "idt init\n"); -} - -typedef struct { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rsi; - uint64_t rdi; - uint64_t rbp; - uint64_t rdx; - uint64_t rcx; - uint64_t rbx; - uint64_t rax; -} PACKED CpuRegs; - -typedef struct { - uint64_t cr8; - uint64_t cr4; - uint64_t cr3; - uint64_t cr2; - uint64_t cr0; -} PACKED CpuCtrlRegs; - -typedef struct { - CpuCtrlRegs ctrl; - CpuRegs regs; - uint64_t trapnum; - uint64_t errnum; - - uint64_t rip; - uint64_t cs; - uint64_t rflags; - uint64_t rsp; - uint64_t ss; -} PACKED IntrStackFrame; - -extern void *ISR_REDIRTABLE[]; - -static const char *exceptions[] = { - "#DE", "#DB", "NMI", - "#BP", "#OF", "#BR", - "#UD", "#NM", "#DF", - "CSO", "#TS", "#NP", - "#SS", "#GP", "#PF", - "RES", "#MF", "#AC", - "#MC", "#XM", "#VE", - "#CP", -}; - -extern void isr_vec0(void); -extern void isr_vec1(void); -extern void isr_vec2(void); -extern void isr_vec3(void); -extern void isr_vec4(void); -extern void isr_vec5(void); -extern void isr_vec6(void); -extern void isr_vec7(void); -extern void isr_vec8(void); -extern void isr_vec10(void); -extern void isr_vec11(void); -extern void isr_vec12(void); -extern void isr_vec13(void); -extern void isr_vec14(void); -extern void isr_vec16(void); -extern void isr_vec17(void); -extern void isr_vec18(void); -extern void isr_vec19(void); -extern void isr_vec20(void); -extern void isr_vec21(void); -extern void isr_vec32(void); -extern void isr_vec33(void); -extern void isr_vec39(void); - -void isr_init(void) { - idt_setentry(0, (uint64_t)&isr_vec0, 0, 0x8E); - idt_setentry(1, (uint64_t)&isr_vec1, 0, 0x8E); - idt_setentry(2, (uint64_t)&isr_vec2, 2, 0x8E); - idt_setentry(3, (uint64_t)&isr_vec3, 0, 0x8E); - idt_setentry(4, (uint64_t)&isr_vec4, 0, 0x8E); - idt_setentry(5, (uint64_t)&isr_vec5, 0, 0x8E); - idt_setentry(6, (uint64_t)&isr_vec6, 0, 0x8E); - idt_setentry(7, (uint64_t)&isr_vec7, 0, 0x8E); - idt_setentry(8, (uint64_t)&isr_vec8, 1, 0x8E); - idt_setentry(10, (uint64_t)&isr_vec10, 0, 0x8E); - idt_setentry(11, (uint64_t)&isr_vec11, 0, 0x8E); - idt_setentry(12, (uint64_t)&isr_vec12, 0, 0x8E); - idt_setentry(13, (uint64_t)&isr_vec13, 0, 0x8E); - idt_setentry(14, (uint64_t)&isr_vec14, 0, 0x8E); - idt_setentry(16, (uint64_t)&isr_vec16, 0, 0x8E); - idt_setentry(17, (uint64_t)&isr_vec17, 0, 0x8E); - idt_setentry(18, (uint64_t)&isr_vec18, 0, 0x8E); - idt_setentry(19, (uint64_t)&isr_vec19, 0, 0x8E); - idt_setentry(20, (uint64_t)&isr_vec20, 0, 0x8E); - idt_setentry(21, (uint64_t)&isr_vec21, 0, 0x8E); - idt_setentry(32, (uint64_t)&isr_vec32, 0, 0x8E); - idt_setentry(33, (uint64_t)&isr_vec33, 0, 0x8E); - idt_setentry(39, (uint64_t)&isr_vec39, 0, 0x8E); - - idt_init(); -} - -void isr_dumpframe(IntrStackFrame *frame) { - kprintf("r15=%016llx r14=%016llx r13=%016llx r12=%016llx\n" - "r11=%016llx r10=%016llx r9 =%016llx r8 =%016llx\n" - "rsi=%016llx rdi=%016llx rbp=%016llx rdx=%016llx\n" - "rcx=%016llx rbx=%016llx rax=%016llx\n" - "cr8=%016llx cr4=%016llx cr3=%016llx cr2=%016llx\n" - "cr0=%016llx rip=%016llx cs =%016llx rfl=%016llx\n" - "rsp=%016llx ss =%016llx trp=%016llx err=%016llx\n", - frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12, - frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8, - frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx, - frame->regs.rcx, frame->regs.rbx, frame->regs.rax, - frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3, - frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags, - frame->rsp, frame->ss, frame->trapnum, frame->errnum - - ); -} - -void isr_handleintr(IntrStackFrame *frame) { - hal_intr_disable(); - ERR("ERROR", "%s, 0x%X\n", exceptions[frame->trapnum], frame->errnum); - isr_dumpframe(frame); - hal_hang(); -} - diff --git a/kernel/hal/x86_64/isr.h b/kernel/hal/x86_64/isr.h deleted file mode 100644 index 02bab1f..0000000 --- a/kernel/hal/x86_64/isr.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef HAL_ISR_H_ -#define HAL_ISR_H_ - -void isr_init(void); - -#endif // HAL_ISR_H_ diff --git a/kernel/hal/x86_64/pic.c b/kernel/hal/x86_64/pic.c new file mode 100644 index 0000000..4b321a5 --- /dev/null +++ b/kernel/hal/x86_64/pic.c @@ -0,0 +1,22 @@ +#include +#include +#include "pic.h" +#include "io.h" +#include "intr.h" + +void pic_init(void) { + io_out8(PIC1_CMD, ICW1_INIT | ICW1_ICW4); + io_out8(PIC2_CMD, ICW1_INIT | ICW1_ICW4); + + io_out8(PIC1_DATA, INTR_IRQBASE); + io_out8(PIC2_DATA, INTR_IRQBASE+8); + + io_out8(PIC1_DATA, 4); + io_out8(PIC2_DATA, 2); + + io_out8(PIC1_DATA, ICW4_8086); + io_out8(PIC2_DATA, ICW4_8086); + + io_out8(PIC1_DATA, 0xff); + io_out8(PIC2_DATA, 0xff); +} diff --git a/kernel/hal/x86_64/pic.h b/kernel/hal/x86_64/pic.h new file mode 100644 index 0000000..dea0213 --- /dev/null +++ b/kernel/hal/x86_64/pic.h @@ -0,0 +1,23 @@ +#ifndef HAL_PIC_H_ +#define HAL_PIC_H_ + +#define PIC1_CMD 0x0020 +#define PIC1_DATA 0x0021 +#define PIC2_CMD 0x00A0 +#define PIC2_DATA 0x00A1 + +#define ICW1_ICW4 0x01 +#define ICW1_SINGLE 0x02 +#define ICW1_ADI 0x04 +#define ICW1_LTIM 0x08 +#define ICW1_INIT 0x10 + +#define ICW4_8086 0x01 +#define ICW4_AUTO 0x02 +#define ICW4_BUFSLAVE 0x04 +#define ICW4_BUFMASTER 0x0C +#define ICW4_SFNM 0x10 + +void pic_init(void); + +#endif // HAL_PIC_H_ diff --git a/kernel/hal/x86_64/port-uACPI/port-uACPI.c b/kernel/hal/x86_64/port-uACPI/port-uACPI.c deleted file mode 100644 index 74471a0..0000000 --- a/kernel/hal/x86_64/port-uACPI/port-uACPI.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "uacpi/uacpi.h" -#include "dlmalloc/malloc.h" -#include "bootinfo/bootinfo.h" -#include "hal/x86_64/io.h" -#include "kprintf.h" -#include "compiler/builtins.h" - -void *uacpi_kernel_alloc(uacpi_size size) { - return dlmalloc(size); -} - -void uacpi_kernel_free(void *ptr) { - return dlfree(ptr); -} - -void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char *s) { - char *t; - switch (lvl) { - case UACPI_LOG_DEBUG: t = "Debug"; break; - case UACPI_LOG_TRACE: t = "Trace"; break; - case UACPI_LOG_INFO: t = "Info"; break; - case UACPI_LOG_WARN: t = "Warn"; break; - case UACPI_LOG_ERROR: t = "Error"; break; - default: - unreachable(); - break; - } - LOG("uACPI", "[%s] %s", t, s); -} - -void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) { - (void)len; - return (void *)(BOOT_INFO.hhdm_off + addr); -} - -void uacpi_kernel_unmap(void *addr, uacpi_size len) { - (void)addr; - (void)len; -} - -uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out) { - *out = BOOT_INFO.rsdp; - return UACPI_STATUS_OK; -} - diff --git a/kernel/hal/x86_64/uACPI/README.md b/kernel/hal/x86_64/uACPI/README.md index 1e534ea..e4c44ff 100644 --- a/kernel/hal/x86_64/uACPI/README.md +++ b/kernel/hal/x86_64/uACPI/README.md @@ -374,11 +374,12 @@ If you want to contribute: | [ilobilix](https://github.com/ilobilo/ilobilix) | Yet another monolithic Linux clone wannabe. Currently under a rewrite | 8,703,286 | AMD Ryzen 9 9950X3D | | [Crescent2](https://github.com/Qwinci/crescent2) | An NT driver compatible kernel and userspace | 6,818,418 | Intel Core i5-13600K | | [davix](https://github.com/dbstream/davix) | Yet another unix-like by some bored nerd | 6,364,623 | Intel Core i7-13700K | +| [Ironclad](https://ironclad-os.org) | Formally verified, hard real-time capable kernel written in SPARK and Ada | 6,196,937 | Intel Core i9-13900KS | | [Managarm](https://github.com/managarm/managarm) | Pragmatic microkernel-based OS with fully asynchronous I/O | 5,618,646 | Intel Core i7-14700K | | [ChronOS](https://github.com/BUGO07/chronos) | Another basic hobby os held together by duct tape, made in rust | 5,416,703 | Intel Core Ultra 7 265KF | | [pmOS](https://gitlab.com/mishakov/pmos) | Microkernel-based operating system written from scratch with uACPI running in userspace | 5,354,445 | AMD Ryzen 9 5900X | | [menix](https://github.com/menix-os/menix) | A minimal and expandable Unix-like operating system | 5,239,043 | Intel Core Ultra 7 265KF | -| [Ironclad](https://ironclad.nongnu.org) | Formally verified, hard real-time capable kernel written in SPARK and Ada | 4,802,816 | Intel Core i9-13900KS | +| [Orange](https://github.com/cpplover0/orange) | Unix-like x86_64 OS with some microkernel features | 4,204,053 | AMD Ryzen 5 3600 | | [Astral](https://github.com/mathewnd/astral) | Operating system written in C which aims be POSIX-compliant | 4,189,189 | Intel Core i5-13600K | | [Keyronex](https://github.com/Keyronex/Keyronex) | Layered kernel with fundamentally asynchronous I/O and working set model-based memory management | 4,013,691 | AMD Ryzen 5800X | | [Orange](https://github.com/cppLover0/Orange) | x86_64 Unix-like OS | 2,377,330 | AMD Ryzen 5 3600 | @@ -387,6 +388,7 @@ If you want to contribute: | [ElysiumOS](https://github.com/imwux/elysium-os) | Hybrid Unix-like kernel | 1,737,654 | AMD Ryzen 7 5800X3D | | [imaginarium](https://github.com/Khitiara/imaginarium) | Ziggy osdev experiments inspired by the NT kernel (using the zig general purpose allocator) | 1,504,436 | AMD Ryzen 7 3700X | | [BadgerOS](https://github.com/badgeteam/BadgerOS) | A monolithic lightweight UNIX clone | 1,018,518 | AMD Ryzen 5 3600 | +| [Retro Rocket](https://github.com/brainboxdotcc/retro-rocket) | A BASIC _powered_ 64-bit SMP multitasking OS | 441,329 | Intel Xeon E5-2680 | | [Hyra](https://github.com/sigsegv7/Hyra) | Monolithic UNIX-like OS by [OSMORA.ORG](https://osmora.org) | 199,873 | Intel Core i3-3220 | ## License diff --git a/kernel/hal/x86_64/uACPI/include/uacpi/tables.h b/kernel/hal/x86_64/uACPI/include/uacpi/tables.h index 5fbecee..422c781 100644 --- a/kernel/hal/x86_64/uACPI/include/uacpi/tables.h +++ b/kernel/hal/x86_64/uACPI/include/uacpi/tables.h @@ -9,6 +9,8 @@ extern "C" { // Forward-declared to avoid including the entire acpi.h here struct acpi_fadt; +struct acpi_entry_hdr; +struct acpi_sdt_hdr; typedef struct uacpi_table_identifiers { uacpi_object_name signature; @@ -136,6 +138,30 @@ uacpi_status uacpi_set_table_installation_handler( uacpi_table_installation_handler handler ); +typedef uacpi_iteration_decision (*uacpi_subtable_iteration_callback) + (uacpi_handle, struct acpi_entry_hdr*); + +/* + * Iterate every subtable of a table such as MADT or SRAT. + * + * 'hdr' is the pointer to the main table, 'hdr_size' is the number of bytes in + * the table before the beginning of the subtable records. 'cb' is the callback + * invoked for each subtable with the 'user' context pointer passed for every + * invocation. + * + * Example usage: + * uacpi_table tbl; + * + * uacpi_table_find_by_signature(ACPI_MADT_SIGNATURE, &tbl); + * uacpi_for_each_subtable( + * tbl.hdr, sizeof(struct acpi_madt), parse_madt, NULL + * ); + */ +uacpi_status uacpi_for_each_subtable( + struct acpi_sdt_hdr *hdr, size_t hdr_size, + uacpi_subtable_iteration_callback cb, void *user +); + #ifdef __cplusplus } #endif diff --git a/kernel/hal/x86_64/uACPI/include/uacpi/types.h b/kernel/hal/x86_64/uACPI/include/uacpi/types.h index 81c7a2e..3475a6e 100644 --- a/kernel/hal/x86_64/uACPI/include/uacpi/types.h +++ b/kernel/hal/x86_64/uACPI/include/uacpi/types.h @@ -29,7 +29,13 @@ typedef enum uacpi_iteration_decision { UACPI_ITERATION_DECISION_CONTINUE = 0, UACPI_ITERATION_DECISION_BREAK, - // Only applicable for uacpi_namespace_for_each_child + /* + * Ignore all of the children of the current node and proceed directly to + * its peer nodes. + * + * Only applicable for API that interacts with the AML namespace such as + * uacpi_namespace_for_each_child, uacpi_find_deivces, etc. + */ UACPI_ITERATION_DECISION_NEXT_PEER, } uacpi_iteration_decision; diff --git a/kernel/hal/x86_64/uACPI/include/uacpi/uacpi.h b/kernel/hal/x86_64/uACPI/include/uacpi/uacpi.h index e0904d5..1a80d72 100644 --- a/kernel/hal/x86_64/uACPI/include/uacpi/uacpi.h +++ b/kernel/hal/x86_64/uACPI/include/uacpi/uacpi.h @@ -6,7 +6,7 @@ #include #define UACPI_MAJOR 3 -#define UACPI_MINOR 0 +#define UACPI_MINOR 1 #define UACPI_PATCH 0 #ifdef UACPI_REDUCED_HARDWARE diff --git a/kernel/hal/x86_64/uACPI/source/tables.c b/kernel/hal/x86_64/uACPI/source/tables.c index 4b45d2a..83fcd32 100644 --- a/kernel/hal/x86_64/uACPI/source/tables.c +++ b/kernel/hal/x86_64/uACPI/source/tables.c @@ -1398,3 +1398,52 @@ uacpi_status uacpi_table_fadt(struct acpi_fadt **out_fadt) *out_fadt = &g_uacpi_rt_ctx.fadt; return UACPI_STATUS_OK; } + +uacpi_status uacpi_for_each_subtable( + struct acpi_sdt_hdr *hdr, size_t hdr_size, + uacpi_subtable_iteration_callback cb, void *user +) +{ + void *cursor; + size_t bytes_left; + + cursor = UACPI_PTR_ADD(hdr, hdr_size); + bytes_left = hdr->length - hdr_size; + + if (uacpi_unlikely(bytes_left > hdr->length)) + return UACPI_STATUS_INVALID_TABLE_LENGTH; + + while (bytes_left > sizeof(struct acpi_entry_hdr)) { + struct acpi_entry_hdr *subtable_hdr = cursor; + + if (uacpi_unlikely(subtable_hdr->length > bytes_left || + subtable_hdr->length < sizeof(*subtable_hdr))) { + uacpi_error( + "corrupted '%.4s' subtable length: %u (%zu bytes left)\n", + hdr->signature, subtable_hdr->length, bytes_left + ); + return UACPI_STATUS_INVALID_TABLE_LENGTH; + } + + switch (cb(user, subtable_hdr)) { + case UACPI_ITERATION_DECISION_CONTINUE: + break; + case UACPI_ITERATION_DECISION_BREAK: + return UACPI_STATUS_OK; + default: + return UACPI_STATUS_INVALID_ARGUMENT; + } + + cursor = UACPI_PTR_ADD(cursor, subtable_hdr->length); + bytes_left -= subtable_hdr->length; + } + + if (uacpi_unlikely(bytes_left != 0)) { + uacpi_warn( + "found %zu stray bytes in table '%.4s'\n", + bytes_left, hdr->signature + ); + } + + return UACPI_STATUS_OK; +} diff --git a/kernel/hal/x86_64/uACPI/tests/run_tests.py b/kernel/hal/x86_64/uACPI/tests/run_tests.py index 0e41a40..5f810a8 100755 --- a/kernel/hal/x86_64/uACPI/tests/run_tests.py +++ b/kernel/hal/x86_64/uACPI/tests/run_tests.py @@ -464,6 +464,7 @@ def main() -> int: bare_cases: List[TestCase] = [ BarebonesTestCase("basic-operation"), BarebonesTestCase("table-installation"), + BarebonesTestCase("foreach-subtable"), ] with TestHeaderFooter("Barebones Mode Tests"): diff --git a/kernel/hal/x86_64/uACPI/tests/runner/barebones_runner.c b/kernel/hal/x86_64/uACPI/tests/runner/barebones_runner.c index e500dbe..3cf1af4 100644 --- a/kernel/hal/x86_64/uACPI/tests/runner/barebones_runner.c +++ b/kernel/hal/x86_64/uACPI/tests/runner/barebones_runner.c @@ -54,6 +54,33 @@ static uint8_t test_mcfg[] = { 0x00, 0x00, 0x00, 0x00 }; +/* + * 4 Local APICs [0, 1, 2, 3] + * 2 IOAPICs [4, 5] + * 2 ISOs [0->2, 9->9] + * 4 NMIs [0, 1, 2, 3] + */ +static uint8_t test_apic[] = { + 0x41, 0x50, 0x49, 0x43, 0x90, 0x00, 0x00, 0x00, + 0x03, 0x1a, 0x48, 0x50, 0x51, 0x4f, 0x45, 0x4d, + 0x53, 0x4c, 0x49, 0x43, 0x2d, 0x4d, 0x50, 0x43, + 0x01, 0x00, 0x00, 0x00, 0x48, 0x50, 0x20, 0x20, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0xfe, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x02, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x04, 0x00, + 0x00, 0x00, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0c, 0x05, 0x00, 0x00, 0x10, 0xc0, 0xfe, + 0x18, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, + 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x04, 0x06, 0x00, 0x05, 0x00, 0x01, 0x04, 0x06, + 0x01, 0x05, 0x00, 0x01, 0x04, 0x06, 0x02, 0x05, + 0x00, 0x01, 0x04, 0x06, 0x03, 0x05, 0x00, 0x01 +}; + static void ensure_signature_is(const char *signature, uacpi_table tbl) { if (strncmp(tbl.hdr->signature, signature, 4) == 0) @@ -105,12 +132,123 @@ static void test_table_installation(void) uacpi_table_unref(&tbl); } +static uacpi_iteration_decision check_madt( + uacpi_handle user, struct acpi_entry_hdr *hdr +) +{ + size_t *idx = user; + struct acpi_madt_lapic *lapic; + struct acpi_madt_ioapic *ioapic; + struct acpi_madt_interrupt_source_override *iso; + struct acpi_madt_lapic_nmi *nmi; + + switch (*idx) { + case 0: + case 1: + case 2: + case 3: + if (hdr->type != ACPI_MADT_ENTRY_TYPE_LAPIC) + goto out_unexpected; + lapic = (struct acpi_madt_lapic*)hdr; + if (lapic->id != *idx) + error("unexpected LAPIC id %d (idx %d)\n", lapic->id, *idx); + break; + case 4: + case 5: + if (hdr->type != ACPI_MADT_ENTRY_TYPE_IOAPIC) + goto out_unexpected; + ioapic = (struct acpi_madt_ioapic*)hdr; + if (ioapic->id != *idx) + error("unexpected IOAPIC id %d (idx %d)\n", ioapic->id, *idx); + break; + case 6: + case 7: + if (hdr->type != ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE) + goto out_unexpected; + iso = (struct acpi_madt_interrupt_source_override*)hdr; + if ((*idx == 6 && iso->source != 0) || + (*idx == 7 && iso->source != 9)) + error("unexpected ISO source %d (idx %d)\n", iso->source, *idx); + break; + case 8: + case 9: + case 10: + case 11: + if (hdr->type != ACPI_MADT_ENTRY_TYPE_LAPIC_NMI) + goto out_unexpected; + nmi = (struct acpi_madt_lapic_nmi*)hdr; + if (nmi->uid != (*idx - 8)) + error("unexpected LAPIC NMI uid %d (idx %d)\n", nmi->uid, *idx); + break; + default: + goto out_unexpected; + } + + (*idx)++; + return UACPI_ITERATION_DECISION_CONTINUE; + +out_unexpected: + error("unexpected MADT entry type %d (idx = %zu)\n", hdr->type, *idx); + return UACPI_ITERATION_DECISION_BREAK; +} + +#define CHECK_SUBTEST_FAILED \ + if (st != UACPI_STATUS_INVALID_TABLE_LENGTH) \ + error("unexpected status %s\n", uacpi_status_to_string(st)); + +#define CHECK_SUBTEST_SUCCEEDED \ + if (idx != 12) \ + error("invalid number of iterations: %zu\n", idx); + +#define FOREACH_SUBTEST(check_cond) \ + idx = 0; \ + st = uacpi_for_each_subtable( \ + tbl.hdr, sizeof(struct acpi_madt), check_madt, &idx \ + ); \ + check_cond; \ + +static void test_foreach_subtable(void) +{ + uacpi_status st; + uacpi_table tbl; + size_t idx = 0; + + st = uacpi_table_install(test_apic, &tbl); + ensure_ok_status(st); + ensure_signature_is(ACPI_MADT_SIGNATURE, tbl); + uacpi_table_unref(&tbl); + + FOREACH_SUBTEST(CHECK_SUBTEST_SUCCEEDED); + + // Make the size slightly larger, make sure we don't crash + test_apic[4] += 1; + FOREACH_SUBTEST(CHECK_SUBTEST_SUCCEEDED); + + // Change the size to 1 byte and make sure we don't crash + test_apic[4] = 1; + FOREACH_SUBTEST(CHECK_SUBTEST_FAILED); + + // Cutoff subtable + test_apic[4] = sizeof(struct acpi_madt) + sizeof(struct acpi_entry_hdr) + 1; + FOREACH_SUBTEST(CHECK_SUBTEST_FAILED); + + test_apic[4] = sizeof(test_apic); + // Out-of-bounds subtable + test_apic[sizeof(test_apic) - 5]++; + FOREACH_SUBTEST(CHECK_SUBTEST_FAILED); + + // all pass + test_apic[sizeof(test_apic) - 5]--; + uacpi_table_unref(&tbl); +} + static struct { const char *name; void (*func)(void); } test_cases[] = { { "basic-operation", test_basic_operation }, { "table-installation", test_table_installation }, + { "foreach-subtable", test_foreach_subtable }, }; static arg_spec_t TEST_CASE_ARG = ARG_POS("test-case", "name of the test case"); diff --git a/kernel/hal/x86_64/uACPI/tests/runner/helpers.h b/kernel/hal/x86_64/uACPI/tests/runner/helpers.h index c4a4ad2..2ae80a1 100644 --- a/kernel/hal/x86_64/uACPI/tests/runner/helpers.h +++ b/kernel/hal/x86_64/uACPI/tests/runner/helpers.h @@ -20,6 +20,8 @@ NORETURN static inline void error(const char *format, ...) { va_list args; + fflush(stdout); + fprintf(stderr, "unexpected error: "); va_start(args, format); vfprintf(stderr, format, args); diff --git a/kernel/kmain.c b/kernel/kmain.c index 8623486..59a9fc3 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -69,7 +69,7 @@ void kmain(void) { kprintf(BANNER_TEXT "\n"); - *((int *)0xdeadbeef) = 123; + /* *((int *)0xdeadbeef) = 123; */ hal_hang(); } diff --git a/kernel/util/mmio.h b/kernel/util/mmio.h new file mode 100644 index 0000000..435e781 --- /dev/null +++ b/kernel/util/mmio.h @@ -0,0 +1,49 @@ +#ifndef UTIL_MMIO_H_ +#define UTIL_MMIO_H_ + +#include + +static inline void mmiowrite8(void *p, uint8_t data) { + *(volatile uint8_t *)(p) = data; +} + +static inline uint8_t mmioread8(void *p) { + return *(volatile uint8_t *)(p); +} + +static inline void mmiowrite16(void *p, uint16_t data) { + *(volatile uint16_t *)(p) = data; +} + +static inline uint16_t mmioread16(void *p) { + return *(volatile uint16_t *)(p); +} + +static inline void mmiowrite32(void *p, uint32_t data) { + *(volatile uint32_t *)(p) = data; +} + +static inline uint32_t mmioread32(void *p) { + return *(volatile uint32_t *)(p); +} + +static inline void mmiowrite64(void *p, uint64_t data) { + *(volatile uint64_t *)(p) = data; +} + +static inline uint64_t mmioread64(void *p) { + return *(volatile uint64_t *)(p); +} + +static inline void mmioreadn(void *dst, const volatile void *src, size_t bytes) { + volatile uint8_t *s = (volatile uint8_t *)src; + uint8_t *d = (uint8_t *)dst; + while (bytes > 0) { + *d = *s; + ++s; + ++d; + --bytes; + } +} + +#endif // UTIL_MMIO_H_