From c53c696286821ad13ab9ec61ed011cfe90e193c0 Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Sat, 28 Jan 2023 04:11:57 +0100 Subject: PIC -> APIC, removing boilerplate irq_handlers --- kernel/src/apic/apic.c | 0 kernel/src/apic/madt.c | 116 ++++++++++++++++++- kernel/src/apic/rsdp.c | 38 ++++++ kernel/src/cpu/idt.c | 19 +-- kernel/src/cpu/irq.c | 290 +++++++--------------------------------------- kernel/src/cpu/irq_stub.S | 56 ++++----- kernel/src/cpu/pic.c | 12 +- kernel/src/main.c | 1 + kernel/src/mem/paging.c | 2 +- 9 files changed, 224 insertions(+), 310 deletions(-) create mode 100644 kernel/src/apic/apic.c (limited to 'kernel/src') diff --git a/kernel/src/apic/apic.c b/kernel/src/apic/apic.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/apic/madt.c b/kernel/src/apic/madt.c index b88b788..fff0db5 100644 --- a/kernel/src/apic/madt.c +++ b/kernel/src/apic/madt.c @@ -1,7 +1,75 @@ #include #include +#include #include #include +#include + +uint8_t curr_cpu_apic_id(void); +uint8_t curr_cpu_apic_id() +{ + uint8_t apic_id = 0; + __asm__ __volatile__ ("movl $1, %%eax; cpuid; shrl $24, %%ebx;": "=b"(apic_id)); + return apic_id; +} + +uint32_t ioapic_addr = 0; +uint32_t lapic_addr = 0; +uint32_t numcores = 0; +uint8_t cpu_apic_ids[256]; + +uint32_t ioapic_read(const uint8_t offset); +uint32_t ioapic_read(const uint8_t offset) +{ + /* tell IOREGSEL where we want to read from */ + *(volatile uint32_t*)(uint64_t)ioapic_addr = offset; + /* return the data from IOWIN */ + return *(volatile uint32_t*)((uint64_t)ioapic_addr + 0x10); +} + +void ioapic_write(const uint8_t offset, const uint32_t val); +void ioapic_write(const uint8_t offset, const uint32_t val) +{ + /* tell IOREGSEL where we want to write to */ + *(volatile uint32_t*)(uint64_t)ioapic_addr = offset; + /* write the value to IOWIN */ + *(volatile uint32_t*)((uint64_t)ioapic_addr + 0x10) = val; +} + +void apic_eoi() +{ + *((volatile uint32_t*)((uint64_t)0xFEE00000 + 0xB0)) = 0; +} + +void ioapic_set_irq(uint8_t irq, uint64_t apic_id, uint8_t vector); +void ioapic_set_irq(uint8_t irq, uint64_t apic_id, uint8_t vector) +{ + const uint32_t low_index = (uint32_t)0x10 + irq*2; + const uint32_t high_index = (uint32_t)0x10 + irq*2 + 1; + + uint32_t high = ioapic_read((uint8_t)high_index); + // set APIC ID + high &= (uint32_t)~0xff000000; + high |= (uint32_t)apic_id << 24; + ioapic_write((uint8_t)high_index, high); + + uint32_t low = ioapic_read((uint8_t)low_index); + + // unmask the IRQ + low &= (uint32_t)~(1<<16); + + // set to physical delivery mode + low &= (uint32_t)~(1<<11); + + // set to fixed delivery mode + low &= (uint32_t)~0x700; + + // set delivery vector + low &= (uint32_t)~0xff; + low |= vector; + + ioapic_write((uint8_t)low_index, low); +} void parse_madt() { @@ -14,6 +82,7 @@ void parse_madt() struct MADT* madt = (struct MADT*)kalloc(sizeof(struct MADT)); memcpy(madt, madt_addr, sizeof(struct MADT)); + lapic_addr = madt->lapic_addr; for (size_t curr_size = sizeof(struct MADT); curr_size < madt->h.Length;) { struct MADT_type_header* m = (struct MADT_type_header*)kalloc(sizeof(struct MADT_type_header)); @@ -27,6 +96,9 @@ void parse_madt() struct MADT_cpu_local_apic* cpu = (struct MADT_cpu_local_apic*)kalloc(sizeof(struct MADT_cpu_local_apic)); memcpy(cpu, (uint64_t*)((uint64_t)madt_addr + (uint64_t)curr_size), sizeof(struct MADT_cpu_local_apic)); + cpu_apic_ids[numcores] = cpu->apic_id; + numcores++; + printf("found cpu: acpi_id: 0x%x, apic_id: 0x%x, flags: 0x%x\n", cpu->acpi_id, cpu->apic_id, cpu->flags); kfree(cpu); } else if (type == 1) { @@ -34,6 +106,8 @@ void parse_madt() struct MADT_io_apic* io = (struct MADT_io_apic*)kalloc(sizeof(struct MADT_io_apic)); memcpy(io, (uint64_t*)((uint64_t)madt_addr + (uint64_t)curr_size), sizeof(struct MADT_io_apic)); + ioapic_addr = io->io_apic_addr; + printf("found io: apic_id: 0x%x, addr: 0x%x, int_base: 0x%x\n", io->apic_id, io->io_apic_addr, io->int_base); kfree(io); } else if (type == 2) { @@ -55,11 +129,11 @@ void parse_madt() kfree(lapic_nmi); } else if (type == 5) { // Local APIC Address Override - struct MADT_lapic_addr* lapic_addr = (struct MADT_lapic_addr*)kalloc(sizeof(struct MADT_lapic_addr)); - memcpy(lapic_addr, (uint64_t*)((uint64_t)madt_addr + (uint64_t)curr_size), sizeof(struct MADT_lapic_addr)); + struct MADT_lapic_addr* lapic_addr_ovr = (struct MADT_lapic_addr*)kalloc(sizeof(struct MADT_lapic_addr)); + memcpy(lapic_addr_ovr, (uint64_t*)((uint64_t)madt_addr + (uint64_t)curr_size), sizeof(struct MADT_lapic_addr)); - printf("found lapic: addr: 0x%x\n", lapic_addr->phys_addr); - kfree(lapic_addr); + printf("found lapic: addr: 0x%x\n", lapic_addr_ovr->phys_addr); + kfree(lapic_addr_ovr); } else if (type == 9) { // Processor Local x2APIC printf("MADT entry of type %d\n", type); @@ -69,4 +143,38 @@ void parse_madt() } curr_size += len; } + kfree(madt); + + /* + for(size_t i = 0; i < numcores; i++) { + // do not start BSP, that's already running this code + if(cpu_apic_ids[i] == bspid) continue; + // send INIT IPI + *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x00C500; // trigger INIT IPI + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12)); // wait for delivery + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x008500; // deassert + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12)); // wait for delivery + mdelay(10); // wait 10 msec + // send STARTUP IPI (twice) + for(size_t j = 0; j < 2; j++) { + *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; // clear APIC errors + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff0f800) | 0x000608; // trigger STARTUP IPI for 0800:0000 + udelay(200); // wait 200 usec + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12)); // wait for delivery + } + } + */ + + uint8_t bspid = curr_cpu_apic_id(); + + map_addr(lapic_addr, lapic_addr, FLAG_PRESENT); + map_addr(ioapic_addr, ioapic_addr, FLAG_PRESENT); + // irq is 2 because of gsi remap + ioapic_set_irq(0x2, bspid, 0x20); // timer + ioapic_set_irq(0x1, bspid, 0x21); // keyboard + __asm__ volatile ("sti;"); } diff --git a/kernel/src/apic/rsdp.c b/kernel/src/apic/rsdp.c index ebecd66..983ab5f 100644 --- a/kernel/src/apic/rsdp.c +++ b/kernel/src/apic/rsdp.c @@ -24,6 +24,44 @@ uint64_t* find_rsdp() return NULL; } +void list_sys_tables(void) +{ + uint64_t* rsdp = find_rsdp(); + + if (rsdp == NULL) { + printf("RSDP NOT FOUND\n"); + return; + } + + struct RSDP_descriptor* rsdp_desc = (struct RSDP_descriptor*)rsdp; + map_addr(rsdp_desc->RsdtAddress, rsdp_desc->RsdtAddress, FLAG_PRESENT); + + struct ACPI_header* rsdt = (struct ACPI_header*)kalloc(sizeof(struct ACPI_header)); + memcpy(rsdt, (uint64_t*)(uint64_t)rsdp_desc->RsdtAddress, sizeof(struct ACPI_header)); + + uint32_t entries = (rsdt->Length - (uint32_t)sizeof(struct ACPI_header)) / 4; + + for (size_t i = 0; i < entries; i++) { + uint32_t na_addr = (uint32_t)rsdp_desc->RsdtAddress + (uint32_t)sizeof(struct ACPI_header) + (uint32_t)i * 4; + uint32_t addr; + memcpy(&addr, (uint64_t*)(uint64_t)na_addr, 4); + + struct ACPI_header* t = (struct ACPI_header*)kalloc(sizeof(struct ACPI_header)); + memcpy(t, (uint64_t*)(uint64_t)addr, sizeof(struct ACPI_header)); + + for (size_t j = 0; j < 4; j++) { + printf("%c", t->Signature[j]); + } + printf(", "); + + kfree(t); + } + printf("\n"); + + kfree(rsdt); + +} + uint64_t* find_sys_table_addr(const char* signature) { uint64_t* rsdp = find_rsdp(); diff --git a/kernel/src/cpu/idt.c b/kernel/src/cpu/idt.c index e900c77..3578f53 100644 --- a/kernel/src/cpu/idt.c +++ b/kernel/src/cpu/idt.c @@ -8,7 +8,7 @@ idtp idt_pointer; void load_idt(idtp* pointer) { - __asm__ volatile ("lidt (%0); sti;" : : "r"(pointer) : ); + __asm__ volatile ("lidt (%0);" : : "r"(pointer) : ); } void add_to_idt(uint16_t num, uint64_t offset, uint16_t selector, uint8_t type) @@ -61,20 +61,9 @@ void init_idt_table(void) // interrupts add_to_idt(32, (uint64_t)irq0, GDT_CODE_SEG, INTERRUPT_GATE); add_to_idt(33, (uint64_t)irq1, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(34, (uint64_t)irq2, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(35, (uint64_t)irq3, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(36, (uint64_t)irq4, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(37, (uint64_t)irq5, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(38, (uint64_t)irq6, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(39, (uint64_t)irq7, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(40, (uint64_t)irq8, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(41, (uint64_t)irq9, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(42, (uint64_t)irq10, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(43, (uint64_t)irq11, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(44, (uint64_t)irq12, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(45, (uint64_t)irq13, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(46, (uint64_t)irq14, GDT_CODE_SEG, INTERRUPT_GATE); - add_to_idt(47, (uint64_t)irq15, GDT_CODE_SEG, INTERRUPT_GATE); + for (size_t i = 34; i < 256; i++) { + add_to_idt((uint16_t)i, (uint64_t)irq2, GDT_CODE_SEG, INTERRUPT_GATE); + } } void init_idt() diff --git a/kernel/src/cpu/irq.c b/kernel/src/cpu/irq.c index 4670da5..79498ba 100644 --- a/kernel/src/cpu/irq.c +++ b/kernel/src/cpu/irq.c @@ -9,6 +9,9 @@ #include #include #include +#include + +#define PIT 0 const char* const exception_name[] = { "Divide-by-zero Error", @@ -45,253 +48,42 @@ const char* const exception_name[] = { "Reserved", }; -void isr0_handler(void) -{ - panic("%s\n", exception_name[0]); -} - -void isr1_handler(void) -{ - panic("%s\n", exception_name[1]); -} - -void isr2_handler(void) -{ - panic("%s\n", exception_name[2]); -} - -void isr3_handler(void) -{ - panic("%s\n", exception_name[3]); -} - -void isr4_handler(void) -{ - panic("%s\n", exception_name[4]); -} - -void isr5_handler(void) -{ - panic("%s\n", exception_name[5]); -} - -void isr6_handler(void) -{ - panic("%s\n", exception_name[6]); -} - -void isr7_handler(void) -{ - panic("%s\n", exception_name[7]); -} - -void isr8_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[8], error); -} - -void isr9_handler(void) -{ - panic("%s\n", exception_name[9]); -} - -void isr10_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[10], error); -} - -void isr11_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[11], error); -} - -void isr12_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[12], error); -} - -void isr13_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[13], error); -} - -void isr14_handler(uint64_t error) -{ - printf("%s, error: %d\n", exception_name[14], error); - page_fault(error); -} - -void isr15_handler(void) -{ - panic("%s\n", exception_name[15]); -} - -void isr16_handler(void) -{ - panic("%s\n", exception_name[16]); -} - -void isr17_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[17], error); -} - -void isr18_handler(void) -{ - panic("%s\n", exception_name[18]); -} - -void isr19_handler(void) -{ - panic("%s\n", exception_name[19]); -} - -void isr20_handler(void) -{ - panic("%s\n", exception_name[20]); -} - -void isr21_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[21], error); -} - -void isr22_handler(void) -{ - panic("%s\n", exception_name[22]); -} - -void isr23_handler(void) -{ - panic("%s\n", exception_name[23]); -} - -void isr24_handler(void) -{ - panic("%s\n", exception_name[24]); -} - -void isr25_handler(void) -{ - panic("%s\n", exception_name[25]); -} - -void isr26_handler(void) -{ - panic("%s\n", exception_name[26]); -} - -void isr27_handler(void) -{ - panic("%s\n", exception_name[27]); -} - -void isr28_handler(void) -{ - panic("%s\n", exception_name[28]); -} - -void isr29_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[29], error); -} - -void isr30_handler(uint64_t error) -{ - panic("%s, error: %d\n", exception_name[30], error); -} - -void isr31_handler(void) -{ - panic("%s\n", exception_name[31]); -} - -void irq0_handler(void) -{ - timer_handler(); - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq1_handler(void) -{ - keyboard_handler(); - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq2_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq3_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq4_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq5_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq6_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq7_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); -} - -void irq8_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq9_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq10_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq11_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq12_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq13_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq14_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); -} - -void irq15_handler(void) -{ - outb(PIC1_COMMAND, PIC_EOI); - outb(PIC2_COMMAND, PIC_EOI); +void isr_def_handler(uint64_t number, uint64_t error) +{ + switch(number) { + case 14: + printf("%s, error: 0x%x\n", exception_name[14], error); + page_fault(error); + break; + default: + panic("%s, error: 0x%x\n", exception_name[number], error); + } +} + +void eoi(uint64_t number) +{ + if (PIT) { + if (number < 8) { + outb(PIC1_COMMAND, PIC_EOI); + } else if (number < 16) { + outb(PIC1_COMMAND, PIC_EOI); + outb(PIC2_COMMAND, PIC_EOI); + } + } else { + apic_eoi(); + } +} + +void irq_def_handler(uint64_t number) +{ + switch(number) + { + case 0: + timer_handler(); + break; + case 1: + keyboard_handler(); + break; + } + eoi(number); } diff --git a/kernel/src/cpu/irq_stub.S b/kernel/src/cpu/irq_stub.S index ee02d3e..3ba4360 100644 --- a/kernel/src/cpu/irq_stub.S +++ b/kernel/src/cpu/irq_stub.S @@ -49,27 +49,41 @@ pop %rax .endm -.macro isr_no_error number -.global isr\number -isr\number: +.macro isrstub pushall - cld + mov 0x88(%rsp), %rsi mov %rsp, panic_rsp - call isr\number\()_handler + cld + call isr_def_handler popall + add $8, %rsp iretq .endm +.macro isr_no_error number +.global isr\number +isr\number: + push $0 + mov $\number, %rdi + isrstub +.endm + .macro isr_error number .global isr\number isr\number: + mov $\number, %rdi + isrstub +.endm + +.macro irq number +.global irq\number +irq\number: pushall - mov 0x88(%rsp), %rdi - cld + mov $\number, %rdi mov %rsp, panic_rsp - call isr\number\()_handler + cld + call irq_def_handler popall - add $8, %rsp iretq .endm @@ -106,30 +120,6 @@ isr_error 29 isr_error 30 isr_no_error 31 -.macro irq number -.global irq\number -irq\number: - pushall - cld - mov %rsp, panic_rsp - call irq\number\()_handler - popall - iretq -.endm - irq 0 irq 1 irq 2 -irq 3 -irq 4 -irq 5 -irq 6 -irq 7 -irq 8 -irq 9 -irq 10 -irq 11 -irq 12 -irq 13 -irq 14 -irq 15 diff --git a/kernel/src/cpu/pic.c b/kernel/src/cpu/pic.c index ceb6e11..83bb524 100644 --- a/kernel/src/cpu/pic.c +++ b/kernel/src/cpu/pic.c @@ -3,22 +3,18 @@ void remap_pic(void) { - // save masks -// uint8_t a1 = inb(PIC1_DATA); -// uint8_t a2 = inb(PIC2_DATA); - // starts the initialization sequence (in cascade mode) outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); - outb(PIC1_DATA, 0x20); // ICW2: Master PIC vector offset - outb(PIC2_DATA, 0x28); // ICW2: Slave PIC vector offset + outb(PIC1_DATA, 0xe0); // ICW2: Master PIC vector offset + outb(PIC2_DATA, 0xe8); // ICW2: Slave PIC vector offset outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) outb(PIC1_DATA, ICW4_8086); outb(PIC2_DATA, ICW4_8086); - // mask interrupts - outb(PIC1_DATA, 0xfc); + // mask all interrupts + outb(PIC1_DATA, 0xff); outb(PIC2_DATA, 0xff); } diff --git a/kernel/src/main.c b/kernel/src/main.c index 31f8117..a14d5ad 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -46,6 +46,7 @@ int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) //print_inode(path_to_inode("/")); init_tss(); + list_sys_tables(); parse_madt(); jump_userspace(); diff --git a/kernel/src/mem/paging.c b/kernel/src/mem/paging.c index 5e248cf..1445410 100644 --- a/kernel/src/mem/paging.c +++ b/kernel/src/mem/paging.c @@ -63,7 +63,7 @@ void page_fault(uint64_t error) uint64_t addr; __asm__ volatile ("mov %%cr2, %0;" : "=r"(addr) : : "memory"); - printf("address: 0x%x, error code: %d\n", addr, error); + printf("address: 0x%x, error code: 0x%x\n", addr, error); if (error == 7) { panic("Accessing privileged page in usermode\n"); -- cgit v1.2.3