diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/Makefile | 2 | ||||
| -rw-r--r-- | kernel/include/apic.h | 13 | ||||
| -rw-r--r-- | kernel/include/atomic.h | 3 | ||||
| -rw-r--r-- | kernel/include/ioapic.h | 12 | ||||
| -rw-r--r-- | kernel/src/apic/apic.c | 79 | ||||
| -rw-r--r-- | kernel/src/apic/ioapic.c | 67 | ||||
| -rw-r--r-- | kernel/src/apic/madt.c | 141 | ||||
| -rw-r--r-- | kernel/src/boot/multiboot2.c | 2 | ||||
| -rw-r--r-- | kernel/src/cpu/irq.c | 4 | ||||
| -rw-r--r-- | kernel/src/main.c | 4 | ||||
| -rw-r--r-- | kernel/src/scheduler/ap_startup.c | 1 |
11 files changed, 185 insertions, 143 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 8e9e158..33a5d4d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,6 +1,8 @@ CFLAGS += -I include OBJS = \ + src/apic/apic.o \ + src/apic/ioapic.o \ src/apic/madt.o \ src/apic/rsdp.o \ src/boot/boot64.o \ diff --git a/kernel/include/apic.h b/kernel/include/apic.h index f795a49..700d6d1 100644 --- a/kernel/include/apic.h +++ b/kernel/include/apic.h @@ -1,6 +1,17 @@ #ifndef APIC_H #define APIC_H -void apic_eoi(void); +#include <types.h> +#include <atomic.h> + +uint8_t curr_cpu_apic_id(void); +void init_ap_cpus(void); + +extern mutex_t cnt_lock; +extern uint32_t cnt; +extern uint32_t ioapic_addr; +extern uint64_t lapic_addr; +extern uint32_t numcores; +extern uint8_t cpu_apic_ids[256]; #endif diff --git a/kernel/include/atomic.h b/kernel/include/atomic.h index 99f83fb..5ddc620 100644 --- a/kernel/include/atomic.h +++ b/kernel/include/atomic.h @@ -14,7 +14,4 @@ bool test_and_set(mutex_t mutex, bool value); void lock(mutex_t mutex); void unlock(mutex_t mutex); -extern mutex_t cnt_lock; -extern uint64_t cnt; - #endif diff --git a/kernel/include/ioapic.h b/kernel/include/ioapic.h new file mode 100644 index 0000000..1b2307a --- /dev/null +++ b/kernel/include/ioapic.h @@ -0,0 +1,12 @@ +#ifndef IOAPIC_H +#define IOAPIC_H + +#include <types.h> + +void ioapic_eoi(void); +uint32_t ioapic_read(const uint8_t offset); +void ioapic_write(const uint8_t offset, const uint32_t val); +void ioapic_set_irq(uint8_t irq, uint64_t apic_id, uint8_t vector); +void apic_remap_interrupts(void); + +#endif diff --git a/kernel/src/apic/apic.c b/kernel/src/apic/apic.c index e69de29..b947317 100644 --- a/kernel/src/apic/apic.c +++ b/kernel/src/apic/apic.c @@ -0,0 +1,79 @@ +#include <atomic.h> +#include <paging.h> +#include <libk/stdio.h> +#include <apic.h> +#include <ioapic.h> +#include <madt.h> +#include <timer.h> + +mutex_t cnt_lock; +uint32_t cnt = 0; +uint32_t ioapic_addr = 0; +uint64_t lapic_addr = 0; +uint32_t numcores = 0; +uint8_t cpu_apic_ids[256]; + +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; +} + +void init_ap_cpus() +{ + uint8_t bspid = curr_cpu_apic_id(); + uint8_t* bspdone = (uint8_t*)0x3000100; + uint8_t* aprunning = (uint8_t*)0x3000200; + *bspdone = 0; + *aprunning = 0; + + init_mutex(&cnt_lock); + map_addr(lapic_addr, lapic_addr, FLAG_PRESENT); + + 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; + + printf("initializing cpu with apic id 0x%x\n", cpu_apic_ids[i]); + // send INIT IPI + + // clear APIC errors + *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; + // select AP + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); + // trigger INIT IPI + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x00C500; + // wait for delivery + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); + // select AP + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); + // deassert + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x008500; + // wait for delivery + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); + // wait 10 msec + wait(10); + + // send STARTUP IPI (twice) + + for(size_t j = 0; j < 2; j++) { + // clear APIC errors + *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; + // select AP + *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); + // trigger STARTUP IPI for 0800:0000 + *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff0f800) | 0x000608; + // wait 200 usec + wait(1); + // wait for delivery + do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); + } + } + + *bspdone = 1; + wait(100); + printf("aprunning: %d\n", *aprunning); + printf("cnt: %d\n", cnt); +} diff --git a/kernel/src/apic/ioapic.c b/kernel/src/apic/ioapic.c new file mode 100644 index 0000000..a8c3452 --- /dev/null +++ b/kernel/src/apic/ioapic.c @@ -0,0 +1,67 @@ +#include <ioapic.h> +#include <apic.h> +#include <paging.h> +#include <libk/stdio.h> + +void ioapic_eoi() +{ + *((volatile uint32_t*)((uint64_t)lapic_addr + 0xB0)) = 0; +} + +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) +{ + /* 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 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 apic_remap_interrupts() +{ + uint8_t bspid = curr_cpu_apic_id(); + + map_addr(ioapic_addr, ioapic_addr, FLAG_PRESENT); + map_addr(lapic_addr, lapic_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/madt.c b/kernel/src/apic/madt.c index 3929cd8..f69887d 100644 --- a/kernel/src/apic/madt.c +++ b/kernel/src/apic/madt.c @@ -1,80 +1,8 @@ #include <madt.h> +#include <apic.h> #include <heap.h> -#include <paging.h> #include <libk/string.h> #include <libk/stdio.h> -#include <apic.h> -#include <timer.h> -#include <atomic.h> - -mutex_t cnt_lock; -uint64_t cnt; - -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; -uint64_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() { @@ -101,8 +29,10 @@ 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++; + if (cpu->flags & 0x1) { + 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); @@ -149,65 +79,4 @@ void parse_madt() curr_size += len; } kfree(madt); - - init_mutex(&cnt_lock); - - uint8_t bspid = curr_cpu_apic_id(); - uint8_t* bspdone = (uint8_t*)0x3000100; - uint8_t* aprunning = (uint8_t*)0x3000200; - *bspdone = 0; - *aprunning = 0; - - - 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;"); - - 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; - - printf("initializing cpu with apic id 0x%x\n", cpu_apic_ids[i]); - // send INIT IPI - - // clear APIC errors - *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; - // select AP - *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); - // trigger INIT IPI - *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x00C500; - // wait for delivery - do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); - // select AP - *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); - // deassert - *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x008500; - // wait for delivery - do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); - // wait 10 msec - wait(10); - - // send STARTUP IPI (twice) - - for(size_t j = 0; j < 2; j++) { - // clear APIC errors - *((volatile uint32_t*)(lapic_addr + 0x280)) = 0; - // select AP - *((volatile uint32_t*)(lapic_addr + 0x310)) = (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | ((uint32_t)cpu_apic_ids[i] << 24); - // trigger STARTUP IPI for 0800:0000 - *((volatile uint32_t*)(lapic_addr + 0x300)) = (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff0f800) | 0x000608; - // wait 200 usec - wait(1); - // wait for delivery - do { __asm__ __volatile__ ("pause" : : : "memory"); }while(*((volatile uint32_t*)(uint64_t)(lapic_addr + 0x300)) & (1 << 12)); - } - } - *bspdone = 1; - wait(100); - printf("aprunning: %d\n", *aprunning); - printf("cnt: %d\n", cnt); } diff --git a/kernel/src/boot/multiboot2.c b/kernel/src/boot/multiboot2.c index 3e6c6d4..1e38cd7 100644 --- a/kernel/src/boot/multiboot2.c +++ b/kernel/src/boot/multiboot2.c @@ -4,7 +4,7 @@ #include <graphics.h> #include <paging.h> -#include <libk/stdio.h> +#include <libk/serial_stdio.h> #include <libk/string.h> #include <libk/list.h> #include <heap.h> diff --git a/kernel/src/cpu/irq.c b/kernel/src/cpu/irq.c index 79498ba..6975fec 100644 --- a/kernel/src/cpu/irq.c +++ b/kernel/src/cpu/irq.c @@ -9,7 +9,7 @@ #include <libk/serial_stdio.h> #include <libk/stdio.h> #include <panic.h> -#include <apic.h> +#include <ioapic.h> #define PIT 0 @@ -70,7 +70,7 @@ void eoi(uint64_t number) outb(PIC2_COMMAND, PIC_EOI); } } else { - apic_eoi(); + ioapic_eoi(); } } diff --git a/kernel/src/main.c b/kernel/src/main.c index 5061515..f70bbee 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -19,6 +19,8 @@ #include <serial.h> #include <containter_of.h> #include <madt.h> +#include <apic.h> +#include <ioapic.h> #include <atomic.h> #include <pmm.h> @@ -43,6 +45,8 @@ int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) init_tss(); list_sys_tables(); parse_madt(); + apic_remap_interrupts(); + init_ap_cpus(); jump_userspace(); for(;;) { diff --git a/kernel/src/scheduler/ap_startup.c b/kernel/src/scheduler/ap_startup.c index 3bb4ab2..cbde44e 100644 --- a/kernel/src/scheduler/ap_startup.c +++ b/kernel/src/scheduler/ap_startup.c @@ -1,4 +1,5 @@ #include <atomic.h> +#include <apic.h> void ap_startup(void) { lock(cnt_lock); |
