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 ++++++++++++++++ 3 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 kernel/src/apic/apic.c (limited to 'kernel/src/apic') 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(); -- cgit v1.2.3