summaryrefslogtreecommitdiff
path: root/kernel/src
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksa@vuckovic.cc>2023-02-16 21:46:25 +0100
committerAleksa Vuckovic <aleksa@vuckovic.cc>2023-02-16 23:49:29 +0100
commit2bb4e7fb4c0f5895148bb32da64381b985c8dcef (patch)
tree1e1fa9a38dba75d0ca0b5fea85b63c8ca0b05a8f /kernel/src
parentbf20ce47a9d5dcad841e4549a68f4ec3db3c57de (diff)
code refactoring
Diffstat (limited to 'kernel/src')
-rw-r--r--kernel/src/apic/apic.c79
-rw-r--r--kernel/src/apic/ioapic.c67
-rw-r--r--kernel/src/apic/madt.c141
-rw-r--r--kernel/src/boot/multiboot2.c2
-rw-r--r--kernel/src/cpu/irq.c4
-rw-r--r--kernel/src/main.c4
-rw-r--r--kernel/src/scheduler/ap_startup.c1
7 files changed, 159 insertions, 139 deletions
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);