summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/intr.c63
-rw-r--r--sys/arch/amd64/amd64/lapic.c2
-rw-r--r--sys/include/arch/amd64/asm.h14
-rw-r--r--sys/include/arch/amd64/cpu.h1
-rw-r--r--sys/include/arch/amd64/intr.h19
5 files changed, 93 insertions, 6 deletions
diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c
index b841da7..3e3f309 100644
--- a/sys/arch/amd64/amd64/intr.c
+++ b/sys/arch/amd64/amd64/intr.c
@@ -28,16 +28,71 @@
*/
#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/panic.h>
#include <machine/intr.h>
+#include <machine/cpu.h>
+#include <machine/asm.h>
+#include <vm/dynalloc.h>
+
+static struct intr_entry *intrs[256] = {0};
+
+void
+splraise(uint8_t s)
+{
+ struct cpu_info *ci = this_cpu();
+
+ if (s < ci->ipl) {
+ panic("splraise IPL less than current IPL\n");
+ }
+
+ amd64_write_cr8(s);
+ ci->ipl = s;
+}
+
+void
+splx(uint8_t s)
+{
+ struct cpu_info *ci = this_cpu();
+
+ if (s > ci->ipl) {
+ panic("splx IPL greater than current IPL\n");
+ }
+
+ amd64_write_cr8(s);
+ ci->ipl = s;
+}
int
-intr_alloc_vector(void)
+intr_alloc_vector(const char *name, uint8_t priority)
{
- static size_t vec = 0x21;
+ size_t vec = MAX(priority << IPL_SHIFT, 0x20);
+ struct intr_entry *intr;
- if (vec >= 0xFF) {
+ /* Sanity check */
+ if (vec > NELEM(intrs)) {
return -1;
}
- return vec++;
+ /*
+ * Try to allocate an interrupt vector. An IPL is made up
+ * of 4 bits so there can be 16 vectors per IPL.
+ */
+ for (int i = vec; i < vec + 16; ++i) {
+ if (intrs[i] != NULL) {
+ continue;
+ }
+
+ intr = dynalloc(sizeof(*intr));
+ if (intr == NULL) {
+ return -ENOMEM;
+ }
+
+ intr->priority = priority;
+ intrs[i] = intr;
+ return i;
+ }
+
+ return -1;
}
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
index b7cefd4..896c2bd 100644
--- a/sys/arch/amd64/amd64/lapic.c
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -317,7 +317,7 @@ lapic_init(void)
/* Allocate a vector if needed */
if (lapic_timer_vec == 0) {
- lapic_timer_vec = intr_alloc_vector();
+ lapic_timer_vec = intr_alloc_vector("lapictmr", IPL_CLOCK);
idt_set_desc(lapic_timer_vec, IDT_INT_GATE, ISR(lapic_tmr_isr),
IST_SCHED);
}
diff --git a/sys/include/arch/amd64/asm.h b/sys/include/arch/amd64/asm.h
index d7334fe..e85dd87 100644
--- a/sys/include/arch/amd64/asm.h
+++ b/sys/include/arch/amd64/asm.h
@@ -85,6 +85,20 @@ amd64_write_cr0(uint64_t val)
}
static inline uint64_t
+amd64_read_cr8(void)
+{
+ uint64_t cr8;
+ __ASMV("mov %%cr8, %0" : "=r" (cr8) :: "memory");
+ return cr8;
+}
+
+static inline void
+amd64_write_cr8(uint64_t val)
+{
+ __ASMV("mov %0, %%cr8" :: "r" (val) : "memory");
+}
+
+static inline uint64_t
amd64_read_cr4(void)
{
uint64_t cr4;
diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h
index b5420a6..16936e9 100644
--- a/sys/include/arch/amd64/cpu.h
+++ b/sys/include/arch/amd64/cpu.h
@@ -38,6 +38,7 @@
struct cpu_info {
uint32_t apicid;
uint8_t has_x2apic : 1;
+ uint8_t ipl;
size_t lapic_tmr_freq;
struct tss_entry *tss;
struct proc *curtd;
diff --git a/sys/include/arch/amd64/intr.h b/sys/include/arch/amd64/intr.h
index 3f0da77..af5edf2 100644
--- a/sys/include/arch/amd64/intr.h
+++ b/sys/include/arch/amd64/intr.h
@@ -36,6 +36,23 @@
#define IST_HW_IRQ 2U
#define IST_SW_INT 3U
-int intr_alloc_vector(void);
+/* Upper 4 bits of interrupt vector */
+#define IPL_SHIFT 4
+
+/*
+ * Interrupt priority levels
+ */
+#define IPL_NONE 0 /* Don't defer anything */
+#define IPL_BIO 1 /* Block I/O */
+#define IPL_CLOCK 2 /* Clock */
+#define IPL_HIGH 3 /* Defer everything */
+
+struct intr_entry {
+ int priority;
+};
+
+int intr_alloc_vector(const char *name, uint8_t priority);
+void splraise(uint8_t s);
+void splx(uint8_t s);
#endif