aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2023-12-13 12:47:10 -0500
committerIan Moffett <ian@osmora.org>2023-12-13 12:47:10 -0500
commite4988a569cdbbbdc70187e80309d496e46225b73 (patch)
treef2d476aa0e1263b722d4f88c34eac32f82fe1385
parent9eb956111bed4f414345f936af83395044f719b0 (diff)
kernel/amd64: tss: Add TSS stack helpers
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/arch/amd64/tss.c74
-rw-r--r--sys/include/arch/amd64/tss.h14
2 files changed, 88 insertions, 0 deletions
diff --git a/sys/arch/amd64/tss.c b/sys/arch/amd64/tss.c
index ba1b0f6..b1b5420 100644
--- a/sys/arch/amd64/tss.c
+++ b/sys/arch/amd64/tss.c
@@ -32,6 +32,8 @@
#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, "
@@ -55,6 +57,78 @@ alloc_resources(struct cpu_info *cpu)
}
}
+/*
+ * 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)
{
diff --git a/sys/include/arch/amd64/tss.h b/sys/include/arch/amd64/tss.h
index 90f6289..bca572e 100644
--- a/sys/include/arch/amd64/tss.h
+++ b/sys/include/arch/amd64/tss.h
@@ -100,6 +100,20 @@ struct __packed tss_desc {
uint32_t reserved;
};
+/*
+ * Holds the address of the address pointing
+ * to the top of an interrupt stack.
+ */
+union tss_stack {
+ struct {
+ uint32_t top_lo;
+ uint32_t top_hi;
+ };
+ uint64_t top;
+};
+
+int tss_alloc_stack(union tss_stack *entry_out, size_t size);
+int tss_update_ist(struct cpu_info *ci, union tss_stack stack, uint8_t istno);
void write_tss(struct cpu_info *cpu, struct tss_desc *desc);
void tss_load(void); /* In tss.S */