aboutsummaryrefslogtreecommitdiff
path: root/sys/arch/amd64/amd64
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2023-12-19 01:00:18 -0500
committerIan Moffett <ian@osmora.org>2023-12-19 01:03:46 -0500
commitf67c2579af54201fd3522996f18109fe9ceaa31f (patch)
tree3dffda9861803cd7c53824457cc3bb3e16decfc5 /sys/arch/amd64/amd64
parent979fca86b84c641cc1c763d8881266f6ab4ba700 (diff)
kernel/amd64: Re-organize AMD64 files
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/arch/amd64/amd64')
-rw-r--r--sys/arch/amd64/amd64/cpu.c52
-rw-r--r--sys/arch/amd64/amd64/gdt.c85
-rw-r--r--sys/arch/amd64/amd64/idt.c66
-rw-r--r--sys/arch/amd64/amd64/ioapic.c188
-rw-r--r--sys/arch/amd64/amd64/lapic.c292
-rw-r--r--sys/arch/amd64/amd64/machdep.c109
-rw-r--r--sys/arch/amd64/amd64/pmap.c50
-rw-r--r--sys/arch/amd64/amd64/spectre.S54
-rw-r--r--sys/arch/amd64/amd64/spectre.c78
-rw-r--r--sys/arch/amd64/amd64/trap.S146
-rw-r--r--sys/arch/amd64/amd64/trap.c97
-rw-r--r--sys/arch/amd64/amd64/tss.S41
-rw-r--r--sys/arch/amd64/amd64/tss.c158
13 files changed, 1416 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
new file mode 100644
index 0000000..81118e1
--- /dev/null
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/cpu.h>
+#include <sys/cdefs.h>
+
+__KERNEL_META("$Hyra$: cpu.c, Ian Marco Moffett, "
+ "AMD64 CPU abstraction module");
+
+static struct cpu_info bsp_info;
+
+struct cpu_info *
+amd64_get_bsp(void)
+{
+ return &bsp_info;
+}
+
+/*
+ * TODO: Update this when adding SMP
+ * support.
+ */
+struct cpu_info *
+amd64_this_cpu(void)
+{
+ return amd64_get_bsp();
+}
diff --git a/sys/arch/amd64/amd64/gdt.c b/sys/arch/amd64/amd64/gdt.c
new file mode 100644
index 0000000..667170a
--- /dev/null
+++ b/sys/arch/amd64/amd64/gdt.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/gdt.h>
+
+struct gdt_entry g_gdt[256] = {
+ /* Null */
+ {0},
+
+ /* Kernel code (0x8) */
+ {
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .access = 0x9A,
+ .granularity = 0x20,
+ .base_hi = 0x00
+ },
+
+ /* Kernel data (0x10) */
+ {
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .access = 0x92,
+ .granularity = 0x00,
+ .base_hi = 0x00
+ },
+
+ /* User code (0x18) */
+ {
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .access = 0xFA,
+ .granularity = 0xAF,
+ .base_hi = 0x00
+ },
+
+ /* User data (0x20) */
+ {
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .access = 0xF2,
+ .granularity = 0x00,
+ .base_hi = 0x00
+ },
+
+ /* TSS segment (0x28) */
+ {0}
+};
+
+struct gdt_entry *g_gdt_tss = &g_gdt[GDT_TSS];
+
+struct gdtr g_gdtr = {
+ .limit = sizeof(struct gdt_entry) * 256 - 1,
+ .offset = (uintptr_t)&g_gdt[0]
+};
diff --git a/sys/arch/amd64/amd64/idt.c b/sys/arch/amd64/amd64/idt.c
new file mode 100644
index 0000000..9f177e0
--- /dev/null
+++ b/sys/arch/amd64/amd64/idt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/idt.h>
+
+static struct idt_entry idt[256];
+static struct idtr idtr = {
+ .limit = sizeof(struct idt_entry) * 256 - 1,
+ .offset = (uintptr_t)&idt[0]
+};
+
+void
+idt_load(void)
+{
+ LIDT(idtr);
+}
+
+void
+idt_set_desc(uint8_t vec, uint8_t type, uintptr_t isr, uint8_t ist)
+{
+ struct idt_entry *desc;
+
+ if (vec >= 255) {
+ /* Invalid vector */
+ return;
+ }
+
+ desc = &idt[vec];
+ desc->off_lo = __SHIFTOUT(isr, __MASK(16));
+ desc->off_mid = __SHIFTOUT(isr, __MASK(16) << 16);
+ desc->off_hi = __SHIFTOUT(isr, __MASK(32) << 32);
+ desc->segsel = 0x8; /* Kernel CS */
+ desc->type = type;
+ desc->dpl = 3;
+ desc->p = 1;
+ desc->zero = 0;
+ desc->zero1 = 0;
+ desc->reserved = 0;
+ desc->ist = ist;
+}
diff --git a/sys/arch/amd64/amd64/ioapic.c b/sys/arch/amd64/amd64/ioapic.c
new file mode 100644
index 0000000..443142c
--- /dev/null
+++ b/sys/arch/amd64/amd64/ioapic.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/ioapic.h>
+#include <machine/ioapicvar.h>
+#include <firmware/acpi/acpi.h>
+#include <sys/panic.h>
+#include <sys/mmio.h>
+#include <sys/cdefs.h>
+#include <sys/syslog.h>
+
+__MODULE_NAME("ioapic");
+__KERNEL_META("$Hyra$: ioapic.c, Ian Marco Moffett, "
+ "I/O APIC driver");
+
+#define IOAPIC_BASE_OFF(off) ((void *)((uintptr_t)ioapic_base + off))
+
+static void *ioapic_base = NULL;
+
+/*
+ * Reads a 32 bit value from the IOAPIC
+ * register space.
+ *
+ * @reg: Register to read from.
+ */
+static uint32_t
+ioapic_readl(uint16_t reg)
+{
+ mmio_write32(IOAPIC_BASE_OFF(IOREGSEL), reg);
+ return mmio_read32(IOAPIC_BASE_OFF(IOWIN));
+}
+
+/*
+ * Writes a 32 bit value to the IOAPIC
+ * register space.
+ *
+ * @reg: Register to write to.
+ * @val: Value to write.
+ */
+static void
+ioapic_writel(uint16_t reg, uint32_t val)
+{
+ mmio_write32(IOAPIC_BASE_OFF(IOREGSEL), reg);
+ mmio_write32(IOAPIC_BASE_OFF(IOWIN), val);
+}
+
+/*
+ * Reads an I/O APIC redirection entry.
+ *
+ * @entry: Entry variable to read into.
+ * @index: Index to read.
+ */
+static void
+ioapic_read_redentry(union ioapic_redentry *entry, uint8_t index)
+{
+ uint32_t lo, hi;
+
+ lo = ioapic_readl(IOREDTBL + index * 2);
+ hi = ioapic_readl(IOREDTBL + index * 2 + 1);
+
+ entry->value = ((uint64_t)hi << 32) | lo;
+}
+
+/*
+ * Writes an I/O APIC redirection entry.
+ *
+ * @entry: Entry variable to write.
+ * @index: Index to write to.
+ */
+static void
+ioapic_write_redentry(const union ioapic_redentry *entry, uint8_t index)
+{
+ ioapic_writel(IOREDTBL + index * 2, (uint32_t)entry->value);
+ ioapic_writel(IOREDTBL + index * 2 + 1, (uint32_t)(entry->value >> 32));
+}
+
+/*
+ * Mask I/O APIC pin with "raw" pin number
+ * (Global System Interrupt)
+ *
+ * @gsi: Global System Interrupt number
+ */
+void
+ioapic_gsi_mask(uint8_t gsi)
+{
+ union ioapic_redentry redentry;
+
+ ioapic_read_redentry(&redentry, gsi);
+ redentry.interrupt_mask = 1;
+ ioapic_write_redentry(&redentry, gsi);
+}
+
+/*
+ * Unmask I/O APIC pin with "raw" pin number
+ * (Global System Interrupt)
+ *
+ * @gsi: Global System Interrupt number
+ */
+void
+ioapic_gsi_unmask(uint8_t gsi)
+{
+ union ioapic_redentry redentry;
+
+ ioapic_read_redentry(&redentry, gsi);
+ redentry.interrupt_mask = 0;
+ ioapic_write_redentry(&redentry, gsi);
+}
+
+/*
+ * Masks I/O APIC pin via IRQ number
+ *
+ * @irq: Interrupt Request number
+ */
+void
+ioapic_irq_mask(uint8_t irq)
+{
+ uint8_t gsi;
+
+ gsi = irq_to_gsi(irq);
+ ioapic_gsi_mask(gsi);
+}
+
+/*
+ * Unmasks I/O APIC pin via IRQ number
+ *
+ * @irq: Interrupt Request number
+ */
+void
+ioapic_irq_unmask(uint8_t irq)
+{
+ uint8_t gsi;
+
+ gsi = irq_to_gsi(irq);
+ ioapic_gsi_unmask(gsi);
+}
+
+void
+ioapic_set_base(void *mmio_base)
+{
+ if (ioapic_base == NULL)
+ ioapic_base = mmio_base;
+}
+
+void
+ioapic_init(void)
+{
+ size_t tmp;
+ uint8_t redir_entry_cnt;
+
+ /* Sanity check */
+ if (ioapic_base == NULL)
+ panic("ioapic base not set!\n");
+
+ tmp = ioapic_readl(IOAPICVER);
+ redir_entry_cnt = __SHIFTOUT(tmp, 0xFF << 16) + 1;
+
+ KINFO("Masking %d GSIs...\n", redir_entry_cnt);
+
+ for (uint8_t i = 0; i < redir_entry_cnt; ++i) {
+ ioapic_gsi_mask(i);
+ }
+}
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
new file mode 100644
index 0000000..8058e3f
--- /dev/null
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/lapic.h>
+#include <machine/lapicvar.h>
+#include <machine/cpuid.h>
+#include <machine/msr.h>
+#include <machine/cpu.h>
+#include <sys/cdefs.h>
+#include <sys/timer.h>
+#include <sys/syslog.h>
+#include <sys/panic.h>
+#include <sys/mmio.h>
+#include <dev/timer/hpet.h>
+
+__MODULE_NAME("lapic");
+__KERNEL_META("$Hyra$: lapic.c, Ian Marco Moffett, "
+ "Local APIC driver");
+
+/*
+ * Only calls KINFO if we are the BSP.
+ */
+#define BSP_KINFO(...) do { \
+ uint64_t msr_val; \
+ \
+ msr_val = rdmsr(IA32_APIC_BASE_MSR); \
+ if (__TEST(msr_val, 1 << 8)) { \
+ KINFO(__VA_ARGS__); \
+ } \
+ } while (0);
+
+static void *lapic_base = NULL;
+static struct timer lapic_timer = { 0 };
+static bool has_x2apic = false;
+
+/*
+ * Returns true if LAPIC is supported.
+ *
+ * LAPIC is supported if CPUID.(EAX=1H):EDX[9] == 1
+ */
+static inline bool
+lapic_check_support(void)
+{
+ uint32_t eax, edx, tmp;
+
+ __CPUID(0x00000001, eax, tmp, tmp, edx);
+ return __TEST(edx, 1 << 9);
+}
+
+/*
+ * Reads a 32 bit value from Local APIC
+ * register space.
+ *
+ * @reg: Register to read from.
+ */
+static inline uint32_t
+lapic_readl(uint32_t reg)
+{
+ void *addr;
+
+ if (!has_x2apic) {
+ addr = (void *)((uintptr_t)lapic_base + reg);
+ return mmio_read32(addr);
+ } else {
+ reg >>= 4;
+ return rdmsr(x2APIC_MSR_BASE + reg);
+ }
+}
+
+/*
+ * Writes a 32 bit value to Local APIC
+ * register space.
+ *
+ * @reg: Register to write to.
+ */
+static inline void
+lapic_writel(uint32_t reg, uint32_t val)
+{
+ void *addr;
+
+ if (!has_x2apic) {
+ addr = (void *)((uintptr_t)lapic_base + reg);
+ mmio_write32(addr, val);
+ } else {
+ reg >>= 4;
+ wrmsr(x2APIC_MSR_BASE + reg, val);
+ }
+}
+
+/*
+ * Calibrates the Local APIC timer - Timer abstraction
+ */
+static size_t
+lapic_timer_calibrate(void)
+{
+ size_t freq;
+
+ lapic_timer_init(&freq);
+ return freq;
+}
+
+/*
+ * Stops the Local APIC timer - Timer abstraction
+ */
+static void
+lapic_timer_stop(void)
+{
+ lapic_writel(LAPIC_INIT_CNT, 0);
+ lapic_writel(LAPIC_LVT_TMR, LAPIC_LVT_MASK);
+}
+
+/*
+ * Set bits within a LAPIC register
+ * without overwriting the whole thing.
+ *
+ * @reg: Reg with bits to be set.
+ * @value: Value in reg will be ORd with this.
+ */
+static inline void
+lapic_reg_set(uint32_t reg, uint32_t value)
+{
+ uint32_t old;
+
+ old = lapic_readl(reg);
+ lapic_writel(reg, old | value);
+}
+
+/*
+ * Clear bits within a LAPIC register
+ * without overwriting the whole thing.
+ *
+ * @reg: Reg with bits to be cleared.
+ * @value: Value in reg will be cleared by this value.
+ */
+static inline void
+lapic_reg_clear(uint32_t reg, uint32_t value)
+{
+ uint32_t old;
+
+ old = lapic_readl(reg);
+ lapic_writel(reg, old & ~(value));
+}
+
+/*
+ * Reads the Local APIC ID of the
+ * current processor.
+ */
+static inline uint32_t
+lapic_get_id(void)
+{
+ if (!has_x2apic) {
+ return (lapic_readl(LAPIC_ID) >> 24) & 0xF;
+ } else {
+ return lapic_readl(LAPIC_ID);
+ }
+}
+
+/*
+ * Checks if the processor supports x2APIC
+ * mode. Returns true if so.
+ */
+static inline bool
+lapic_has_x2apic(void)
+{
+ uint32_t ecx, tmp;
+
+ __CPUID(0x00000001, tmp, tmp, ecx, tmp);
+ return __TEST(ecx, 1 << 21);
+}
+
+/*
+ * Updates LDR to LAPIC_STARTUP_LID.
+ *
+ * XXX: This does *not* happen with x2APIC
+ * as the LDR register in x2APIC mode
+ * is readonly.
+ */
+static inline void
+lapic_set_ldr(void)
+{
+ if (!has_x2apic)
+ lapic_writel(LAPIC_LDR, LAPIC_STARTUP_LID);
+}
+
+void
+lapic_timer_init(size_t *freq_out)
+{
+ uint32_t ticks_per_10ms;
+ const uint32_t MAX_SAMPLES = 0xFFFFFFFF;
+
+ lapic_writel(LAPIC_DCR, 3); /* Use divider 16 */
+ lapic_writel(LAPIC_INIT_CNT, MAX_SAMPLES); /* Set the initial count */
+
+ hpet_msleep(10); /* Wait 10ms (10000 usec) */
+ lapic_writel(LAPIC_LVT_TMR, LAPIC_LVT_MASK); /* Stop the timer w/ LVT mask bit */
+
+ /* Sanity check */
+ if (freq_out == NULL)
+ panic("lapic_timer_init() freq_out NULL\n");
+
+ ticks_per_10ms = MAX_SAMPLES - lapic_readl(LAPIC_CUR_CNT);
+ *freq_out = ticks_per_10ms;
+}
+
+void
+lapic_set_base(void *mmio_base)
+{
+ if (lapic_base == NULL)
+ lapic_base = mmio_base;
+}
+
+void
+lapic_init(void)
+{
+ struct cpu_info *cur_cpu;
+ uint64_t tmp;
+ size_t tmr_freq;
+
+ /* Sanity check */
+ if (lapic_base == NULL) {
+ panic("LAPIC base not set!\n");
+ }
+
+ if (!lapic_check_support()) {
+ /*
+ * Hyra currently depends on the existance
+ * of a Local APIC.
+ */
+ panic("This machine does not support LAPIC!\n");
+ }
+
+ has_x2apic = lapic_has_x2apic();
+
+ /* Hardware enable the Local APIC */
+ tmp = rdmsr(IA32_APIC_BASE_MSR);
+ tmp |= has_x2apic << x2APIC_ENABLE_SHIFT;
+ wrmsr(IA32_APIC_BASE_MSR, tmp | LAPIC_HW_ENABLE);
+
+ /* Software enable the Local APIC via SVR */
+ lapic_reg_set(LAPIC_SVR, LAPIC_SW_ENABLE);
+
+ BSP_KINFO("Enabled Local APIC for BSP\n");
+ lapic_set_ldr();
+
+ /* Setup the timer descriptor */
+ lapic_timer.name = "LAPIC_INTEGRATED_TIMER";
+ lapic_timer.calibrate = lapic_timer_calibrate;
+ lapic_timer.stop = lapic_timer_stop;
+
+ /* Register the timer for scheduler usage */
+ register_timer(TIMER_SCHED, &lapic_timer);
+
+ /* Get the current processor, and lock its structure */
+ cur_cpu = this_cpu();
+ CPU_INFO_LOCK(cur_cpu);
+
+ /* Calibrate timer */
+ lapic_timer_init(&tmr_freq);
+ cur_cpu->lapic_tmr_freq = tmr_freq;
+
+ /* Set the Local APIC ID */
+ cur_cpu->id = lapic_get_id();
+
+ BSP_KINFO("BSP Local APIC ID: %d\n", cur_cpu->id);
+ CPU_INFO_UNLOCK(cur_cpu);
+}
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
new file mode 100644
index 0000000..66778a6
--- /dev/null
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/machdep.h>
+#include <sys/cdefs.h>
+#include <machine/trap.h>
+#include <machine/idt.h>
+#include <machine/gdt.h>
+#include <machine/ioapic.h>
+#include <machine/lapic.h>
+#include <machine/tss.h>
+#include <machine/spectre.h>
+#include <machine/cpu.h>
+
+__MODULE_NAME("machdep");
+__KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, "
+ "Core machine dependent code");
+
+#define ISR(func) ((uintptr_t)func)
+#define INIT_FLAG_IOAPIC 0x00000001U
+
+static inline void
+init_tss(struct cpu_info *cur_cpu)
+{
+ struct tss_desc *desc;
+
+ desc = (struct tss_desc *)g_gdt_tss;
+ write_tss(cur_cpu, desc);
+ tss_load();
+}
+
+static void
+interrupts_init(void)
+{
+ idt_set_desc(0x0, IDT_TRAP_GATE_FLAGS, ISR(arith_err), 0);
+ idt_set_desc(0x2, IDT_TRAP_GATE_FLAGS, ISR(nmi), 0);
+ idt_set_desc(0x3, IDT_TRAP_GATE_FLAGS, ISR(breakpoint_handler), 0);
+ idt_set_desc(0x4, IDT_TRAP_GATE_FLAGS, ISR(overflow), 0);
+ idt_set_desc(0x5, IDT_TRAP_GATE_FLAGS, ISR(bound_range), 0);
+ idt_set_desc(0x6, IDT_TRAP_GATE_FLAGS, ISR(invl_op), 0);
+ idt_set_desc(0x8, IDT_TRAP_GATE_FLAGS, ISR(double_fault), 0);
+ idt_set_desc(0xA, IDT_TRAP_GATE_FLAGS, ISR(invl_tss), 0);
+ idt_set_desc(0xB, IDT_TRAP_GATE_FLAGS, ISR(segnp), 0);
+ idt_set_desc(0xD, IDT_TRAP_GATE_FLAGS, ISR(general_prot), 0);
+ idt_set_desc(0xE, IDT_TRAP_GATE_FLAGS, ISR(page_fault), 0);
+ idt_load();
+}
+
+void
+processor_halt(void)
+{
+ __ASMV("cli; hlt");
+}
+
+void
+processor_init(void)
+{
+ /* Indicates what doesn't need to be init anymore */
+ static uint8_t init_flags = 0;
+
+ struct cpu_info *cur_cpu = NULL;
+
+ cur_cpu = this_cpu();
+
+ interrupts_init();
+ gdt_load(&g_gdtr);
+
+ CPU_INFO_LOCK(cur_cpu);
+ init_tss(cur_cpu);
+ CPU_INFO_UNLOCK(cur_cpu);
+
+ if (!__TEST(init_flags, INIT_FLAG_IOAPIC)) {
+ init_flags |= INIT_FLAG_IOAPIC;
+ ioapic_init();
+ }
+
+ lapic_init(); /* Per core */
+
+ /* Use spectre mitigation if enabled */
+ if (try_spectre_mitigate != NULL)
+ try_spectre_mitigate();
+
+}
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
new file mode 100644
index 0000000..2e3e744
--- /dev/null
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <vm/pmap.h>
+#include <sys/cdefs.h>
+
+#define PTE_ADDR_MASK 0x000FFFFFFFFFF000
+
+struct vas
+pmap_read_vas(void)
+{
+ struct vas vas;
+ uintptr_t cr3_raw;
+
+ __ASMV("mov %%cr3, %0"
+ : "=r" (cr3_raw)
+ );
+
+ vas.cr3_flags = cr3_raw & ~PTE_ADDR_MASK;
+ vas.top_level = cr3_raw & PTE_ADDR_MASK;
+ vas.use_l5_paging = false; /* TODO: Check for support */
+ vas.lock.lock = 0;
+ return vas;
+}
diff --git a/sys/arch/amd64/amd64/spectre.S b/sys/arch/amd64/amd64/spectre.S
new file mode 100644
index 0000000..f293ab0
--- /dev/null
+++ b/sys/arch/amd64/amd64/spectre.S
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ #include <sys/cdefs.h>
+
+__KERNEL_META "$Hyra$: spectre.S, Ian Marco Moffett, \
+ Spectre mitigation detection"
+
+.text
+.globl __can_mitigate_spectre
+
+__can_mitigate_spectre:
+ xor %ecx, %ecx // NULL out ECX
+ mov $0x7, %eax // 0x7 (Check IBRS)
+ cpuid
+
+ /* Check if supported (if EDX[26] == 1) */
+ mov $1, %ebx
+ shl $26, %ebx
+ test %ebx, %edx
+ jnz supported
+not_supported:
+ xor %rax, %rax
+ jmp 1f
+supported:
+ mov $1, %rax
+1:
+ ret
diff --git a/sys/arch/amd64/amd64/spectre.c b/sys/arch/amd64/amd64/spectre.c
new file mode 100644
index 0000000..a0be8fc
--- /dev/null
+++ b/sys/arch/amd64/amd64/spectre.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/spectre.h>
+#include <machine/cpuid.h>
+#include <machine/msr.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+
+__MODULE_NAME("spectre");
+__KERNEL_META("$Hyra$: spectre.c, Ian Marco Moffett, "
+ "Spectre mitigation support");
+
+#if __SPECTRE_MITIGATION == 1
+
+/*
+ * Returns true if Indirect Branch Restricted Speculation (IBRS)
+ * is supported.
+ */
+__naked bool
+__can_mitigate_spectre(void);
+
+/*
+ * Returns EXIT_FAILURE if not supported, returns
+ * EXIT_SUCCESS if mitigation is now active.
+ *
+ * This function will be NULL if spectre mitigation isn't enabled;
+ * therefore it is wise to verify to prevent access violations and
+ * undefined behaviour.
+ *
+ * This behaviour is governed by the __SPECTRE_MITIGATION define
+ *
+ * TODO: Try to enable others, not just IBRS
+ */
+__weak int
+try_spectre_mitigate(void)
+{
+ uint64_t tmp;
+
+ if (!__can_mitigate_spectre()) {
+ KINFO("IBRS not supported; spectre mitigation NOT enabled\n");
+ return EXIT_FAILURE;
+ }
+
+ KINFO("IBRS supported; spectre mitigation enabled\n");
+ tmp = rdmsr(IA32_SPEC_CTL);
+ tmp |= __BIT(0); /* IBRS */
+ wrmsr(IA32_SPEC_CTL, tmp);
+ return EXIT_SUCCESS;
+}
+
+#endif /* __SPECTRE_MITIGATION == 1 */
diff --git a/sys/arch/amd64/amd64/trap.S b/sys/arch/amd64/amd64/trap.S
new file mode 100644
index 0000000..9dc1f6a
--- /dev/null
+++ b/sys/arch/amd64/amd64/trap.S
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/frameasm.h>
+#include <machine/trap.h>
+#include <sys/cdefs.h>
+
+__KERNEL_META "$Hyra$: trap.S, Ian Marco Moffett, \
+ Trap handling routines"
+
+.text
+.globl breakpoint_handler
+breakpoint_handler:
+ push_trapframe_ec $TRAP_BREAKPOINT
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl arith_err
+arith_err:
+ push_trapframe_ec $TRAP_ARITH_ERR
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl overflow
+overflow:
+ push_trapframe_ec $TRAP_OVERFLOW
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl bound_range
+bound_range:
+ push_trapframe_ec $TRAP_BOUND_RANGE
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl invl_op
+invl_op:
+ push_trapframe_ec $TRAP_INVLOP
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl double_fault
+double_fault:
+ push_trapframe $TRAP_DOUBLE_FAULT
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl invl_tss
+invl_tss:
+ push_trapframe $TRAP_INVLTSS
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl segnp
+segnp:
+ push_trapframe $TRAP_SEGNP
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl general_prot
+general_prot:
+ push_trapframe $TRAP_PROTFLT
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl page_fault
+page_fault:
+ push_trapframe $TRAP_PAGEFLT
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
+
+.globl nmi
+nmi:
+ push_trapframe_ec $TRAP_NMI
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
new file mode 100644
index 0000000..642c061
--- /dev/null
+++ b/sys/arch/amd64/amd64/trap.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/trap.h>
+#include <sys/cdefs.h>
+#include <sys/spinlock.h>
+#include <sys/syslog.h>
+#include <sys/panic.h>
+
+static const char *trap_type[] = {
+ [TRAP_BREAKPOINT] = "breakpoint",
+ [TRAP_ARITH_ERR] = "arithmetic error",
+ [TRAP_OVERFLOW] = "overflow",
+ [TRAP_BOUND_RANGE] = "bound range exceeded",
+ [TRAP_INVLOP] = "invalid opcode",
+ [TRAP_DOUBLE_FAULT] = "double fault",
+ [TRAP_INVLTSS] = "invalid TSS",
+ [TRAP_SEGNP] = "segment not present",
+ [TRAP_PROTFLT] = "general protection",
+ [TRAP_PAGEFLT] = "page fault",
+ [TRAP_NMI] = "non-maskable interrupt"
+};
+
+static const int TRAP_COUNT = __ARRAY_COUNT(trap_type);
+static ftrap_handler_t ftrap_handler = NULL;
+static struct spinlock ftrap_handler_lock = { 0 };
+
+static void
+trap_print(struct trapframe *tf)
+{
+ const char *mode;
+
+ if (tf->trapno < TRAP_COUNT) {
+ kprintf("** Fatal %s", trap_type[tf->trapno]);
+ } else {
+ kprintf("** Unknown trap %d", tf->trapno);
+ }
+ mode = __TEST(tf->trapno, TRAP_USER) ? "user" : "supervisor";
+ kprintf(" in %s mode **\n", mode);
+}
+
+/*
+ * Registers a handler for *fatal* traps.
+ */
+void
+register_ftrap_handler(ftrap_handler_t handler)
+{
+ spinlock_acquire(&ftrap_handler_lock);
+ ftrap_handler = handler;
+ spinlock_release(&ftrap_handler_lock);
+}
+
+/*
+ * Handles traps.
+ */
+void
+trap_handler(struct trapframe *tf)
+{
+ trap_print(tf);
+
+ /*
+ * XXX: Handle NMIs better. For now we just
+ * panic.
+ */
+ if (tf->trapno == TRAP_NMI) {
+ kprintf("Possible hardware failure?\n");
+ panic("Caught NMI; bailing out\n");
+ }
+
+ panic("Caught pre-sched exception @0x%x\n", tf->rip);
+}
diff --git a/sys/arch/amd64/amd64/tss.S b/sys/arch/amd64/amd64/tss.S
new file mode 100644
index 0000000..be44a04
--- /dev/null
+++ b/sys/arch/amd64/amd64/tss.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_META "$Hyra$: tss.S, Ian Marco Moffett, \
+ Low level TSS code"
+
+.globl tss_load
+tss_load:
+ str %ax /* Store task register value into AX */
+ mov $0x28, %ax /* Store TSS GDT selector into AX */
+ or $3, %ax
+ ltr %ax /* Load the task register */
+ retq
diff --git a/sys/arch/amd64/amd64/tss.c b/sys/arch/amd64/amd64/tss.c
new file mode 100644
index 0000000..b1b5420
--- /dev/null
+++ b/sys/arch/amd64/amd64/tss.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/tss.h>
+#include <machine/cpu.h>
+#include <lib/string.h>
+#include <vm/dynalloc.h>
+#include <sys/panic.h>
+#include <sys/errno.h>
+#include <assert.h>
+
+__MODULE_NAME("TSS");
+__KERNEL_META("$Hyra$: tss.c, Ian Marco Moffett, "
+ "AMD64 Task state segment code");
+
+static void
+alloc_resources(struct cpu_info *cpu)
+{
+ struct tss_entry *tss;
+
+ /*
+ * Allocate TSS entries for this CPU
+ */
+ if (cpu->tss == NULL) {
+ /* Allocate a TSS for this CPU */
+ tss = dynalloc(sizeof(*tss));
+ if (tss == NULL)
+ panic("Failed to alloc %d bytes for TSS\n", sizeof(*tss));
+ memset(tss, 0, sizeof(*tss));
+ cpu->tss = tss;
+ }
+}
+
+/*
+ * Update interrupt stack table entry `istno' with `stack'
+ *
+ * @stack: Interrupt stack.
+ * @istno: IST number, must be 1-based.
+ *
+ * Returns 0 on success.
+ */
+int
+tss_update_ist(struct cpu_info *ci, union tss_stack stack, uint8_t istno)
+{
+ volatile struct tss_entry *tss = ci->tss;
+
+ __assert(tss != NULL);
+
+ switch (istno) {
+ case 1:
+ tss->ist1_lo = stack.top_lo;
+ tss->ist1_hi = stack.top_hi;
+ break;
+ case 2:
+ tss->ist2_lo = stack.top_lo;
+ tss->ist2_hi = stack.top_hi;
+ break;
+ case 3:
+ tss->ist3_lo = stack.top_lo;
+ tss->ist3_hi = stack.top_hi;
+ break;
+ case 4:
+ tss->ist4_lo = stack.top_lo;
+ tss->ist4_hi = stack.top_hi;
+ break;
+ case 5:
+ tss->ist5_lo = stack.top_lo;
+ tss->ist5_hi = stack.top_hi;
+ break;
+ case 6:
+ tss->ist6_lo = stack.top_lo;
+ tss->ist6_hi = stack.top_hi;
+ break;
+ case 7:
+ tss->ist7_lo = stack.top_lo;
+ tss->ist7_hi = stack.top_hi;
+ break;
+ default:
+ return -EXIT_FAILURE;
+ };
+
+ return 0;
+}
+
+/*
+ * Allocates TSS stack.
+ *
+ * Returns 0 on success.
+ *
+ * @entry_out: Pointer to location where allocated entry
+ * will be sent.
+ */
+int
+tss_alloc_stack(union tss_stack *entry_out, size_t size)
+{
+ uintptr_t base = (uintptr_t)dynalloc(size);
+
+ if (base == 0) {
+ return -EXIT_FAILURE;
+ }
+
+ entry_out->top = base + size;
+ return 0;
+}
+
+void
+write_tss(struct cpu_info *cpu, struct tss_desc *desc)
+{
+ uintptr_t tss_base;
+
+ alloc_resources(cpu);
+
+ tss_base = (uintptr_t)cpu->tss;
+
+ /*
+ * XXX: The AVL (Available for use by system software)
+ * bit is ignored by hardware and it is up to us
+ * to decide how to use it... As of now, it is useless
+ * to us and shall remain 0.
+ */
+ desc->seglimit = sizeof(struct tss_entry);
+ desc->p = 1; /* Must be present to be valid! */
+ desc->g = 0; /* Granularity -> 0 */
+ desc->avl = 0; /* Not used */
+ desc->dpl = 0; /* Descriptor Privilege Level -> 0 */
+ desc->type = 0x9; /* For TSS -> 0x9 (0b1001) */
+
+ desc->base_lo16 = __SHIFTOUT(tss_base, __MASK(16));
+ desc->base_mid8 = __SHIFTOUT(tss_base, __MASK(8) << 16);
+ desc->base_hi_mid8 = __SHIFTOUT(tss_base, __MASK(8) << 24);
+ desc->base_hi32 = __SHIFTOUT(tss_base, __MASK(32) << 32);
+}