aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/pmap.c58
-rw-r--r--sys/include/arch/amd64/cpu.h3
-rw-r--r--sys/include/arch/amd64/sysvec.h1
3 files changed, 62 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index 8af6d39..468cca4 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -31,7 +31,12 @@
#include <vm/vm.h>
#include <vm/physseg.h>
#include <sys/cdefs.h>
+#include <sys/cpu.h>
+#include <sys/intr.h>
#include <machine/tlb.h>
+#include <machine/lapic.h>
+#include <machine/sysvec.h>
+#include <machine/idt.h>
#include <assert.h>
#include <string.h>
@@ -52,6 +57,45 @@
#define PTE_GLOBAL __BIT(8)
#define PTE_NX __BIT(63) /* Execute-disable */
+__attr(interrupt) static void
+tlb_shootdown_isr(void *sf)
+{
+ struct cpu_info *ci = this_cpu();
+ struct intr_info *intr_info = ci->tlb_shootdown;
+
+ /* Setup interrupt information if needed */
+ if (ci->tlb_shootdown == NULL) {
+ intr_info = intr_info_alloc("TLB-Shootdown", "LAPIC-IPI");
+ intr_info->affinity = ci->id;
+
+ ci->tlb_shootdown = intr_info;
+ intr_register(intr_info);
+ }
+
+ ++intr_info->count;
+ tlb_flush(ci->tlb_flush_ptr);
+
+ ci->tlb_flush_ptr = 0;
+ lapic_send_eoi();
+}
+
+static void
+tlb_shootdown(vaddr_t flush_va)
+{
+ struct cpu_info *curcpu, *ci = NULL;
+ size_t idx = 0;
+
+ curcpu = this_cpu();
+ while ((ci = cpu_get(idx++)) != NULL) {
+ if (ci->id == curcpu->id)
+ continue;
+
+ ci->tlb_flush_ptr = flush_va;
+ }
+
+ lapic_send_ipi(0, IPI_SHORTHAND_OTHERS, SYSVEC_TLB);
+}
+
/*
* Convert pmap prot flags to PTE flags.
*/
@@ -160,6 +204,17 @@ pmap_modify_tbl(struct vm_ctx *ctx, struct vas vas, vaddr_t va, size_t val)
/* Map our page */
tbl[pmap_get_level_index(1, va)] = val;
+
+ /*
+ * Do TLB shootdown if CPUs are listed.
+ *
+ * XXX: Some might not be listed during early
+ * startup.
+ */
+ if (cpu_get(0) != NULL) {
+ tlb_shootdown(va);
+ }
+
tlb_flush(va);
done:
return status;
@@ -261,5 +316,8 @@ pmap_read_vas(void)
int
pmap_init(struct vm_ctx *ctx)
{
+ idt_set_desc(SYSVEC_TLB, IDT_INT_GATE_FLAGS,
+ (uintptr_t)tlb_shootdown_isr, 0);
+
return 0;
}
diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h
index ee9bad7..3febf5a 100644
--- a/sys/include/arch/amd64/cpu.h
+++ b/sys/include/arch/amd64/cpu.h
@@ -35,6 +35,7 @@
#include <sys/spinlock.h>
#include <sys/sched_state.h>
#include <sys/queue.h>
+#include <sys/intr.h>
#include <machine/tss.h>
#include <machine/msr.h>
/*
@@ -72,6 +73,8 @@ struct cpu_info {
volatile void *lapic_base;
volatile bool has_x2apic;
volatile struct tss_entry *tss;
+ volatile uintptr_t tlb_flush_ptr; /* Address to flush */
+ struct intr_info *tlb_shootdown; /* Shootdown interrupt info */
};
/*
diff --git a/sys/include/arch/amd64/sysvec.h b/sys/include/arch/amd64/sysvec.h
index a6ff1bd..99a84c0 100644
--- a/sys/include/arch/amd64/sysvec.h
+++ b/sys/include/arch/amd64/sysvec.h
@@ -43,6 +43,7 @@ typedef enum {
SYSVEC_IPI, /* IPI vector */
SYSVEC_HLT, /* Halt vector */
SYSVEC_PCKBD, /* Keyboard vector */
+ SYSVEC_TLB, /* TLB shootdown */
/* -- XXX: New vectors go above -- */
NSYSVEC_BASE, /* Non-system vector base */