The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=6227d0f81a5e5e2473ceb8b185098ee9a53c82ff
commit 6227d0f81a5e5e2473ceb8b185098ee9a53c82ff Author: Andrew Turner <and...@freebsd.org> AuthorDate: 2025-08-07 11:12:39 +0000 Commit: Andrew Turner <and...@freebsd.org> CommitDate: 2025-08-07 11:30:59 +0000 bhyve/arm64: Stop assuming the CPU index is MPIDR We need the MPIDR value in a few places in userspace. Rather than calculate it ask the kernel to give it to us. This allows us to change how it is calculated without having to change userspace. Reviewed by: markj Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D51763 --- usr.sbin/bhyve/aarch64/bhyve_machdep.h | 1 + usr.sbin/bhyve/aarch64/bhyverun_machdep.c | 21 +++++++++++++++++++++ usr.sbin/bhyve/aarch64/fdt.c | 3 ++- usr.sbin/bhyve/aarch64/vmexit.c | 23 +++++++++++------------ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/usr.sbin/bhyve/aarch64/bhyve_machdep.h b/usr.sbin/bhyve/aarch64/bhyve_machdep.h index e487bb5a0f44..2dde231091fc 100644 --- a/usr.sbin/bhyve/aarch64/bhyve_machdep.h +++ b/usr.sbin/bhyve/aarch64/bhyve_machdep.h @@ -7,6 +7,7 @@ #ifndef _BHYVE_MACHDEP_H_ #define _BHYVE_MACHDEP_H_ +extern uint64_t *cpu_to_mpidr; extern cpuset_t running_cpumask; #endif /* _BHYVE_MACHDEP_H_ */ diff --git a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c index 098454169272..06fe85f96e0a 100644 --- a/usr.sbin/bhyve/aarch64/bhyverun_machdep.c +++ b/usr.sbin/bhyve/aarch64/bhyverun_machdep.c @@ -30,6 +30,8 @@ #include <sys/mman.h> #include <sys/stat.h> +#include <machine/armreg.h> + #include <assert.h> #include <err.h> #include <errno.h> @@ -74,6 +76,8 @@ #define PCIE_INTC 36 #define PCIE_INTD 37 +uint64_t *cpu_to_mpidr; + void bhyve_init_config(void) { @@ -364,6 +368,23 @@ bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp) int error; int pcie_intrs[4] = {PCIE_INTA, PCIE_INTB, PCIE_INTC, PCIE_INTD}; + cpu_to_mpidr = calloc(guest_ncpus, sizeof(*cpu_to_mpidr)); + if (cpu_to_mpidr == NULL) { + warnx("unable to allocate space for mpidr list"); + return (ENOMEM); + } + + for (uint64_t cpu = 0; cpu < (uint64_t)guest_ncpus; cpu++) { + uint64_t mpidr; + + error = vm_get_register(fbsdrun_vcpu(cpu), VM_REG_GUEST_MPIDR_EL1, + &mpidr); + assert(error == 0); +#define MPIDR_AFF_MASK (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | MPIDR_AFF2_MASK | MPIDR_AFF3_MASK) + cpu_to_mpidr[cpu] = mpidr & MPIDR_AFF_MASK; +#undef MPIDR_AFF_MASK + } + bootrom = get_config_value("bootrom"); if (bootrom == NULL) { warnx("no bootrom specified"); diff --git a/usr.sbin/bhyve/aarch64/fdt.c b/usr.sbin/bhyve/aarch64/fdt.c index 3fb97a40c241..8832a99a6cf1 100644 --- a/usr.sbin/bhyve/aarch64/fdt.c +++ b/usr.sbin/bhyve/aarch64/fdt.c @@ -39,6 +39,7 @@ #include <vmmapi.h> #include "config.h" +#include "bhyve_machdep.h" #include "bhyverun.h" #include "fdt.h" @@ -92,7 +93,7 @@ add_cpu(void *fdt, int cpuid) fdt_begin_node(fdt, node_name); fdt_property_string(fdt, "device_type", "cpu"); fdt_property_string(fdt, "compatible", "arm,armv8"); - fdt_property_u64(fdt, "reg", cpuid); + fdt_property_u64(fdt, "reg", cpu_to_mpidr[cpuid]); fdt_property_string(fdt, "enable-method", "psci"); fdt_end_node(fdt); } diff --git a/usr.sbin/bhyve/aarch64/vmexit.c b/usr.sbin/bhyve/aarch64/vmexit.c index 6b7f80e67a92..e6dd4b074d39 100644 --- a/usr.sbin/bhyve/aarch64/vmexit.c +++ b/usr.sbin/bhyve/aarch64/vmexit.c @@ -152,7 +152,7 @@ vmexit_bogus(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, static uint64_t smccc_affinity_info(uint64_t target_affinity, uint32_t lowest_affinity_level) { - uint64_t cpu_aff, mask = 0; + uint64_t mask = 0; switch (lowest_affinity_level) { case 0: @@ -172,13 +172,7 @@ smccc_affinity_info(uint64_t target_affinity, uint32_t lowest_affinity_level) } for (int vcpu = 0; vcpu < guest_ncpus; vcpu++) { - /* TODO: We should get this from the kernel */ - cpu_aff = (vcpu & 0xf) << MPIDR_AFF0_SHIFT | - ((vcpu >> 4) & 0xff) << MPIDR_AFF1_SHIFT | - ((vcpu >> 12) & 0xff) << MPIDR_AFF2_SHIFT | - (uint64_t)((vcpu >> 20) & 0xff) << MPIDR_AFF3_SHIFT; - - if ((cpu_aff & mask) == (target_affinity & mask) && + if ((cpu_to_mpidr[vcpu] & mask) == (target_affinity & mask) && CPU_ISSET(vcpu, &running_cpumask)) { /* Return ON if any CPUs are on */ return (PSCI_AFFINITY_INFO_ON); @@ -194,9 +188,9 @@ vmexit_smccc(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) { struct vcpu *newvcpu; struct vm_exit *vme; - uint64_t newcpu, smccc_rv; + uint64_t mpidr, smccc_rv; enum vm_suspend_how how; - int error; + int error, newcpu; /* Return the Unknown Function Identifier by default */ smccc_rv = SMCCC_RET_NOT_SUPPORTED; @@ -211,8 +205,13 @@ vmexit_smccc(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) case PSCI_FNID_CPU_OFF: break; case PSCI_FNID_CPU_ON: - newcpu = vme->u.smccc_call.args[0]; - if (newcpu > (uint64_t)guest_ncpus) { + mpidr = vme->u.smccc_call.args[0]; + for (newcpu = 0; newcpu < guest_ncpus; newcpu++) { + if (cpu_to_mpidr[newcpu] == mpidr) + break; + } + + if (newcpu == guest_ncpus) { smccc_rv = PSCI_RETVAL_INVALID_PARAMS; break; }