From 8fba5348fc5fec93d56b5d540962f94b4685e7c0 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 14 Aug 2018 16:37:14 +0000 Subject: [PATCH] amd64: ensure that curproc->p_vmspace pmap always matches PCPU curpmap. When performing context switch on a machine without PCID, if current %cr3 equals to the new pmap %cr3, which is typical for kernel_pmap vs. kernel process, I overlooked to update PCPU curpmap value. Remove check for %cr3 not equal to pm_cr3 for doing the update. It is believed that this case cannot happen at all, due to other changes in this revision. Also, do not set the very first curpmap to kernel_pmap, it should be vmspace0 pmap instead to match curproc. Move the common code to activate the initial pmap both on BSP and APs into pmap_activate_boot() helper. Reported by: eadler, ambrisko Discussed with: kevans Reviewed by: alc, markj (previous version) Tested by: ambrisko (previous version) Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D16618 --- sys/amd64/amd64/mp_machdep.c | 3 ++- sys/amd64/amd64/pmap.c | 26 ++++++++++++++++++++++---- sys/amd64/include/pmap.h | 1 + 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index c3fc2109568d..314c46e8dd31 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -297,7 +298,6 @@ init_secondary(void) pc->pc_gs32p = &gdt[NGDT * cpu + GUGS32_SEL]; pc->pc_ldt = (struct system_segment_descriptor *)&gdt[NGDT * cpu + GUSERLDT_SEL]; - pc->pc_curpmap = kernel_pmap; pc->pc_pcid_gen = 1; pc->pc_pcid_next = PMAP_PCID_KERN + 1; common_tss[cpu].tss_rsp0 = 0; @@ -342,6 +342,7 @@ init_secondary(void) while (atomic_load_acq_int(&aps_ready) == 0) ia32_pause(); + pmap_activate_boot(vmspace_pmap(proc0.p_vmspace)); init_secondary_tail(); } diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index e447963ff394..e707b9ec4e57 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -2655,9 +2655,7 @@ pmap_pinit0(pmap_t pmap) __pcpu[i].pc_ucr3 = PMAP_NO_CR3; } } - PCPU_SET(curpmap, kernel_pmap); - pmap_activate(curthread); - CPU_FILL(&kernel_pmap->pm_active); + pmap_activate_boot(pmap); } void @@ -7529,7 +7527,7 @@ pmap_activate_sw(struct thread *td) intr_restore(rflags); if (cached) PCPU_INC(pm_save_cnt); - } else if (cr3 != pmap->pm_cr3) { + } else { load_cr3(pmap->pm_cr3); PCPU_SET(curpmap, pmap); if (pti) { @@ -7559,6 +7557,26 @@ pmap_activate(struct thread *td) critical_exit(); } +void +pmap_activate_boot(pmap_t pmap) +{ + u_int cpuid; + + /* + * kernel_pmap must be never deactivated, and we ensure that + * by never activating it at all. + */ + MPASS(pmap != kernel_pmap); + + cpuid = PCPU_GET(cpuid); +#ifdef SMP + CPU_SET_ATOMIC(cpuid, &pmap->pm_active); +#else + CPU_SET(cpuid, &pmap->pm_active); +#endif + PCPU_SET(curpmap, pmap); +} + void pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) { diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 47a970e7a9a0..34c3fb868ce3 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -407,6 +407,7 @@ extern int invpcid_works; struct thread; +void pmap_activate_boot(pmap_t pmap); void pmap_activate_sw(struct thread *); void pmap_bootstrap(vm_paddr_t *); int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde);