From caaddb88e80c9b9033436e74a5176a8a32001d8e Mon Sep 17 00:00:00 2001 From: Mitchell Horne Date: Thu, 5 Nov 2020 00:52:52 +0000 Subject: [PATCH] riscv: set kernel_pmap hart mask more precisely In pmap_bootstrap(), we fill kernel_pmap->pm_active since it is invariably active on all harts. However, this marks it as active even for harts that don't exist in the system, which can cause issue when the mask is passed to the SBI firmware via sbi_remote_sfence_vma(). Specifically, the SBI spec allows SBI_ERR_INVALID_PARAM to be returned when an invalid hart is set in the mask. The latest version of OpenSBI does not have this issue, but v0.6 does, and this is triggering a recently added KASSERT in CI. Switch to only setting bits in pm_active for harts that enter the system. Reported by: Jenkins Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D27080 --- sys/riscv/riscv/mp_machdep.c | 4 ++++ sys/riscv/riscv/pmap.c | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/riscv/riscv/mp_machdep.c b/sys/riscv/riscv/mp_machdep.c index b453ef844c2f..cdcc86e715dd 100644 --- a/sys/riscv/riscv/mp_machdep.c +++ b/sys/riscv/riscv/mp_machdep.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -266,6 +267,9 @@ init_secondary(uint64_t hart) /* Enable external (PLIC) interrupts */ csr_set(sie, SIE_SEIE); + /* Activate this hart in the kernel pmap. */ + CPU_SET_ATOMIC(hart, &kernel_pmap->pm_active); + /* Activate process 0's pmap. */ pmap_activate_boot(vmspace_pmap(proc0.p_vmspace)); diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 1d37bcb0bd20..6cad0f68740c 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -573,7 +573,12 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) rw_init(&pvh_global_lock, "pmap pv global"); - CPU_FILL(&kernel_pmap->pm_active); + /* + * Set the current CPU as active in the kernel pmap. Secondary cores + * will add themselves later in init_secondary(). The SBI firmware + * may rely on this mask being precise, so CPU_FILL() is not used. + */ + CPU_SET(PCPU_GET(hart), &kernel_pmap->pm_active); /* Assume the address we were loaded to is a valid physical address. */ min_pa = max_pa = kernstart;