aboutsummaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-03-17 20:59:31 -0400
committerIan Moffett <ian@osmora.org>2024-03-17 20:59:31 -0400
commit0776264c266e7c1619b8b8b84d2da5384979bb3c (patch)
tree80b6ded012336e24c72cc2c16e4c3ce952b7b739 /sys/arch/amd64
parent7895aaff402a021a1b04645ca8d251f760e5662e (diff)
parent2896f4126de2ee0fd1bab4b960bfb2213c359f18 (diff)
Merge branch 'user' into dev
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/machdep.c82
-rw-r--r--sys/arch/amd64/amd64/pmap.c13
-rw-r--r--sys/arch/amd64/amd64/spectre.c7
-rw-r--r--sys/arch/amd64/amd64/syscall.S43
-rw-r--r--sys/arch/amd64/amd64/syscall.c49
-rw-r--r--sys/arch/amd64/amd64/trap.S10
-rw-r--r--sys/arch/amd64/amd64/trap.c12
7 files changed, 211 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 6342aab..47d6dd0 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -40,6 +40,7 @@
#include <machine/spectre.h>
#include <machine/cpu.h>
#include <machine/uart.h>
+#include <machine/cpuid.h>
#include <vm/vm.h>
#include <vm/dynalloc.h>
#include <vm/physseg.h>
@@ -56,6 +57,8 @@ __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, "
#define INIT_FLAG_IOAPIC 0x00000001U
#define INIT_FLAG_ACPI 0x00000002U
+void syscall_isr(void);
+
static inline void
init_tss(struct cpu_info *cur_cpu)
{
@@ -78,18 +81,28 @@ interrupts_init(void)
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(0xC, IDT_TRAP_GATE_FLAGS, ISR(ss_fault), 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_set_desc(0x80, IDT_INT_GATE_USER, ISR(syscall_isr), 0);
idt_load();
}
+static bool
+is_sse_supported(void)
+{
+ uint32_t edx, unused;
+
+ __CPUID(0x00000001, unused, unused, unused, edx);
+ return __TEST(edx, __BIT(25)) && __TEST(edx, __BIT(26));
+}
+
void
processor_halt(void)
{
__ASMV("cli; hlt");
}
-
/*
* Send char to serial for debugging purposes.
*/
@@ -144,11 +157,63 @@ intr_unmask(void)
__ASMV("sti");
}
+int
+processor_init_pcb(struct proc *proc)
+{
+ struct pcb *pcb = &proc->pcb;
+ const uint16_t FPU_FCW = 0x33F;
+ const uint32_t SSE_MXCSR = 0x1F80;
+
+ /* Allocate FPU save area, aligned on a 16 byte boundary */
+ pcb->fpu_state = PHYS_TO_VIRT(vm_alloc_pageframe(1));
+ if (pcb->fpu_state == NULL) {
+ return -1;
+ }
+
+ /*
+ * Setup x87 FPU control word and SSE MXCSR bits
+ * as per the sysv ABI
+ */
+ __ASMV("fldcw %0\n"
+ "ldmxcsr %1"
+ :: "m" (FPU_FCW),
+ "m" (SSE_MXCSR) : "memory");
+
+ amd64_fxsave(pcb->fpu_state);
+ return 0;
+}
+
+int
+processor_free_pcb(struct proc *proc)
+{
+ struct pcb *pcb = &proc->pcb;
+
+ if (pcb->fpu_state == NULL) {
+ return -1;
+ }
+
+ vm_free_pageframe(VIRT_TO_PHYS(pcb->fpu_state), 1);
+ return 0;
+}
+
+void
+processor_switch_to(struct proc *old_td, struct proc *new_td)
+{
+ struct pcb *old_pcb = (old_td != NULL) ? &old_td->pcb : NULL;
+ struct pcb *new_pcb = &new_td->pcb;
+
+ if (old_pcb != NULL) {
+ amd64_fxsave(old_pcb->fpu_state);
+ }
+ amd64_fxrstor(new_pcb->fpu_state);
+}
+
void
processor_init(void)
{
/* Indicates what doesn't need to be init anymore */
static uint8_t init_flags = 0;
+ static uint64_t reg_tmp;
struct cpu_info *cur_cpu;
/* Create our cpu_info structure */
@@ -159,6 +224,21 @@ processor_init(void)
/* Set %GS to cpu_info */
amd64_write_gs_base((uintptr_t)cur_cpu);
+ if (is_sse_supported()) {
+ /* Enable SSE/SSE2 */
+ reg_tmp = amd64_read_cr0();
+ reg_tmp &= ~(__BIT(2));
+ reg_tmp |= __BIT(1);
+ amd64_write_cr0(reg_tmp);
+
+ /* Enable FXSAVE/FXRSTOR */
+ reg_tmp = amd64_read_cr4();
+ reg_tmp |= 3 << 9;
+ amd64_write_cr4(reg_tmp);
+ } else {
+ panic("SSE/SSE2 not supported!\n");
+ }
+
CPU_INFO_LOCK(cur_cpu);
init_tss(cur_cpu);
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index 2760532..54d4ca3 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -228,6 +228,19 @@ pmap_switch_vas(struct vm_ctx *ctx, struct vas vas)
: "memory");
}
+/*
+ * TODO: During the mapping of a virtual address, a level
+ * may be allocated. This function does not handle the
+ * freeing of allocated levels. We should keep track
+ * of levels allocated and free them here.
+ */
+int
+pmap_free_vas(struct vm_ctx *ctx, struct vas vas)
+{
+ vm_free_pageframe(vas.top_level, 1);
+ return 0;
+}
+
struct vas
pmap_read_vas(void)
{
diff --git a/sys/arch/amd64/amd64/spectre.c b/sys/arch/amd64/amd64/spectre.c
index 1247607..05aa557 100644
--- a/sys/arch/amd64/amd64/spectre.c
+++ b/sys/arch/amd64/amd64/spectre.c
@@ -62,13 +62,18 @@ __weak int
try_spectre_mitigate(void)
{
uint64_t tmp;
+ static bool should_log = true;
if (!__can_mitigate_spectre()) {
KINFO("IBRS not supported; spectre mitigation NOT enabled\n");
return EXIT_FAILURE;
}
- KINFO("IBRS supported; spectre mitigation enabled\n");
+ /* This is called per processor, only log once */
+ if (should_log) {
+ KINFO("IBRS supported; spectre mitigation enabled\n");
+ should_log = false;
+ }
tmp = rdmsr(IA32_SPEC_CTL);
tmp |= __BIT(0); /* IBRS */
diff --git a/sys/arch/amd64/amd64/syscall.S b/sys/arch/amd64/amd64/syscall.S
new file mode 100644
index 0000000..fe70523
--- /dev/null
+++ b/sys/arch/amd64/amd64/syscall.S
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023-2024 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>
+ #include <machine/frameasm.h>
+
+__KERNEL_META "$Hyra$: syscall.S, Ian Marco Moffett, \
+ Syscall ISR code"
+
+.text
+.globl syscall_isr
+syscall_isr:
+ push_trapframe $0
+ mov %rsp, %rdi
+ call __syscall
+ pop_trapframe
+ iretq
diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c
new file mode 100644
index 0000000..68235d5
--- /dev/null
+++ b/sys/arch/amd64/amd64/syscall.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023-2024 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/syscall.h>
+
+void
+__syscall(struct trapframe *tf)
+{
+ struct syscall_args args = {
+ .code = tf->rax,
+ .arg0 = tf->rdi,
+ .arg1 = tf->rsi,
+ .arg2 = tf->rcx,
+ .arg3 = tf->r8,
+ .arg4 = tf->r9,
+ .sp = tf->rsp
+ };
+
+ if (args.code < __MAX_SYSCALLS && args.code > 0) {
+ args.code -= 1;
+ tf->rax = g_syscall_table[args.code](&args);
+ }
+}
diff --git a/sys/arch/amd64/amd64/trap.S b/sys/arch/amd64/amd64/trap.S
index 5a77955..66dd2a9 100644
--- a/sys/arch/amd64/amd64/trap.S
+++ b/sys/arch/amd64/amd64/trap.S
@@ -144,3 +144,13 @@ nmi:
/* TODO */
cli
hlt
+
+.globl ss_fault
+ss_fault:
+ push_trapframe_ec $TRAP_SS
+
+ handle_trap
+
+ /* TODO */
+ cli
+ hlt
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
index b73048d..f1e58f1 100644
--- a/sys/arch/amd64/amd64/trap.c
+++ b/sys/arch/amd64/amd64/trap.c
@@ -44,7 +44,8 @@ static const char *trap_type[] = {
[TRAP_SEGNP] = "segment not present",
[TRAP_PROTFLT] = "general protection",
[TRAP_PAGEFLT] = "page fault",
- [TRAP_NMI] = "non-maskable interrupt"
+ [TRAP_NMI] = "non-maskable interrupt",
+ [TRAP_SS] = "stack-segment fault"
};
static const int TRAP_COUNT = __ARRAY_COUNT(trap_type);
@@ -54,12 +55,17 @@ dbg_errcode(struct trapframe *tf)
{
uint64_t ec = tf->error_code;
- if (tf->trapno == TRAP_PAGEFLT) {
+ switch (tf->trapno) {
+ case TRAP_PAGEFLT:
kprintf("bits (pwui): %c%c%c%c\n",
__TEST(ec, __BIT(0)) ? 'p' : '-',
__TEST(ec, __BIT(1)) ? 'w' : '-',
__TEST(ec, __BIT(2)) ? 'u' : '-',
__TEST(ec, __BIT(4)) ? 'i' : '-');
+ break;
+ case TRAP_SS:
+ kprintf("ss: 0x%x\n", ec);
+ break;
}
}
@@ -115,5 +121,5 @@ trap_handler(struct trapframe *tf)
}
regdump(tf);
- panic("Caught pre-sched exception\n");
+ panic("Halted\n");
}