diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 58 | ||||
-rw-r--r-- | sys/include/arch/amd64/cpu.h | 3 | ||||
-rw-r--r-- | sys/include/arch/amd64/sysvec.h | 1 |
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 */ |