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
This commit is contained in:
kib 2018-08-14 16:37:14 +00:00
parent 21f5deb5e6
commit bf861eb196
3 changed files with 25 additions and 5 deletions

View File

@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <x86/apicreg.h>
@ -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();
}

View File

@ -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)
{

View File

@ -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);