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;
                }

Reply via email to