summaryrefslogtreecommitdiff
path: root/src/apic.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-31 22:35:04 +0200
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-31 22:35:04 +0200
commit866912eb5f7906da2545f27f7bbef01a7d61c87f (patch)
tree2472110bcf868837d84893bc257edcbafefe5a59 /src/apic.c
parent5e12467c860372dfa10323365fb0df9db79c8f9b (diff)
Oops, commit missing files from last commitHEADmaster
Diffstat (limited to 'src/apic.c')
-rw-r--r--src/apic.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/apic.c b/src/apic.c
new file mode 100644
index 0000000..26adfae
--- /dev/null
+++ b/src/apic.c
@@ -0,0 +1,121 @@
+#include "aplos.h"
+
+enum {
+ APIC_BASE = 0x1B,
+
+ SPURIOUS_INTERRUPT_VECTOR = 0xF0,
+ END_OF_INTERRUPT = 0xB0
+};
+
+static volatile uint32_t *apic_base;
+static volatile uint8_t *ioapic_reg;
+static volatile uint32_t *ioapic_data;
+static uint8_t ioapic_max_entries;
+
+static uint32_t read_apic_reg(uint64_t);
+static void write_apic_reg(uint64_t, uint32_t);
+static uint32_t read_ioapic_reg(uint8_t);
+static void write_ioapic_reg(uint8_t, uint32_t);
+
+void
+setup_apic(struct ioapic_info *ioapic)
+{
+ uint64_t v = get_msr(APIC_BASE);
+ uint64_t addr = v & 0x0000000FFFFFF000;
+
+ apic_base = (uint32_t *)map_page(addr, 1, false);
+ write_apic_reg(SPURIOUS_INTERRUPT_VECTOR, read_apic_reg(SPURIOUS_INTERRUPT_VECTOR) | 0x1FF);
+
+ uint8_t *ioapic_base = (uint8_t*)map_page(ioapic->base, 1, false);
+ ioapic_reg = ioapic_base;
+ ioapic_data = (uint32_t*)(ioapic_base+16);
+
+ ioapic_max_entries = (read_ioapic_reg(1) >> 16)&0xFF;
+}
+
+void
+apic_end_of_interrupt(void)
+{
+ write_apic_reg(END_OF_INTERRUPT, 0);
+}
+
+struct ioapic_redirection
+read_redirection(uint8_t n)
+{
+ assert(n <= ioapic_max_entries);
+ struct ioapic_redirection r;
+
+ uint32_t low = read_ioapic_reg(0x10+2*n);
+ uint32_t high = read_ioapic_reg(0x11+2*n);
+
+ r.vector = low & 0xFF;
+ r.delivery_mode = (low >> 8) & 0x7;
+ r.destination_mode = (low >> 11) & 0x1;
+ r.delivery_status = (low >> 12) & 0x1;
+ r.pin_polarity = (low >> 13) & 0x1;
+ r.remote_irr = (low >> 14) & 0x1;
+ r.trigger_mode = (low >> 15) & 0x1;
+ r.mask = (low >> 16) & 0x1;
+ r.reserved = (low >> 17) & 0xFF;
+ r.reserved |= high & 0xFFFFFF;
+ if(r.destination_mode)
+ r.destination = (high >> 24) & 0xF;
+ else
+ r.destination = (high >> 24) & 0xFF;
+ return r;
+}
+
+void
+write_redirection(uint8_t n, struct ioapic_redirection r)
+{
+ uint32_t high, low;
+ high = low = 0;
+ assert(n <= ioapic_max_entries);
+ assert(r.vector >= 0x10 && r.vector <= 0xFE);
+
+ low |= r.vector & 0xFF;
+ low |= (r.delivery_mode & 0x7) << 8;
+ low |= (r.destination_mode & 0x1) << 11;
+ low |= (r.delivery_status & 0x1) << 12;
+ low |= (r.pin_polarity & 0x1) << 13;
+ low |= (r.remote_irr & 0x1) << 14;
+ low |= (r.trigger_mode & 0x1) << 15;
+ low |= (r.mask & 0x1) << 16;
+ low |= (r.reserved & 0xF) << 17;
+ high |= (r.reserved & 0xFFFFFF00) >> 8;
+ if(r.destination_mode)
+ high |= (r.destination & 0xF) << 24;
+ else
+ high |= (r.destination & 0xFF) << 24;
+
+ write_ioapic_reg(0x10+2*n, low);
+ write_ioapic_reg(0x11+2*n, high);
+}
+
+static uint32_t
+read_apic_reg(uint64_t r)
+{
+ r /= 4;
+ return apic_base[r];
+}
+
+static void
+write_apic_reg(uint64_t r, uint32_t v)
+{
+ r /= 4;
+ apic_base[r] = v;
+}
+
+static uint32_t
+read_ioapic_reg(uint8_t r)
+{
+ *ioapic_reg = r;
+ return *ioapic_data;
+}
+
+static void
+write_ioapic_reg(uint8_t r, uint32_t v)
+{
+ *ioapic_reg = r;
+ *ioapic_data = v;
+}