SME2 support adds the following state for HVF guests:
- Vector registers Z0, ... , Z31 (introduced by FEAT_SVE but HVF does
not support it)
- Predicate registers P0, .., P15 (also FEAT_SVE)
- ZA register
- ZT0 register
- PSTATE.{SM,ZA} bits (SVCR pseudo-register)
- SMPRI_EL1 which handles the PE's priority in the SMCU
- TPIDR2_EL0 the thread local ID register for SME
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
target/arm/hvf/hvf.c | 294 ++++++++++++++++++++++++++++++++++++++++-
target/arm/hvf/hvf_sme_stubs.h | 158 ++++++++++++++++++++++
target/arm/hvf/sysreg.c.inc | 8 ++
target/arm/hvf_arm.h | 41 ++++++
target/arm/machine.c | 2 +-
5 files changed, 500 insertions(+), 3 deletions(-)
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index d79469ca27f794139b8073e25fc16d470b1942d5..3d194680cc87e78835098df2e0e7987ed544c553 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -395,6 +395,60 @@ static const struct hvf_reg_match hvf_fpreg_match[] = {
{ HV_SIMD_FP_REG_Q31, offsetof(CPUARMState, vfp.zregs[31]) },
};
+static const struct hvf_reg_match hvf_sme2_zreg_match[] = {
+ { HV_SME_Z_REG_0, offsetof(CPUARMState, vfp.zregs[0]) },
+ { HV_SME_Z_REG_1, offsetof(CPUARMState, vfp.zregs[1]) },
+ { HV_SME_Z_REG_2, offsetof(CPUARMState, vfp.zregs[2]) },
+ { HV_SME_Z_REG_3, offsetof(CPUARMState, vfp.zregs[3]) },
+ { HV_SME_Z_REG_4, offsetof(CPUARMState, vfp.zregs[4]) },
+ { HV_SME_Z_REG_5, offsetof(CPUARMState, vfp.zregs[5]) },
+ { HV_SME_Z_REG_6, offsetof(CPUARMState, vfp.zregs[6]) },
+ { HV_SME_Z_REG_7, offsetof(CPUARMState, vfp.zregs[7]) },
+ { HV_SME_Z_REG_8, offsetof(CPUARMState, vfp.zregs[8]) },
+ { HV_SME_Z_REG_9, offsetof(CPUARMState, vfp.zregs[9]) },
+ { HV_SME_Z_REG_10, offsetof(CPUARMState, vfp.zregs[10]) },
+ { HV_SME_Z_REG_11, offsetof(CPUARMState, vfp.zregs[11]) },
+ { HV_SME_Z_REG_12, offsetof(CPUARMState, vfp.zregs[12]) },
+ { HV_SME_Z_REG_13, offsetof(CPUARMState, vfp.zregs[13]) },
+ { HV_SME_Z_REG_14, offsetof(CPUARMState, vfp.zregs[14]) },
+ { HV_SME_Z_REG_15, offsetof(CPUARMState, vfp.zregs[15]) },
+ { HV_SME_Z_REG_16, offsetof(CPUARMState, vfp.zregs[16]) },
+ { HV_SME_Z_REG_17, offsetof(CPUARMState, vfp.zregs[17]) },
+ { HV_SME_Z_REG_18, offsetof(CPUARMState, vfp.zregs[18]) },
+ { HV_SME_Z_REG_19, offsetof(CPUARMState, vfp.zregs[19]) },
+ { HV_SME_Z_REG_20, offsetof(CPUARMState, vfp.zregs[20]) },
+ { HV_SME_Z_REG_21, offsetof(CPUARMState, vfp.zregs[21]) },
+ { HV_SME_Z_REG_22, offsetof(CPUARMState, vfp.zregs[22]) },
+ { HV_SME_Z_REG_23, offsetof(CPUARMState, vfp.zregs[23]) },
+ { HV_SME_Z_REG_24, offsetof(CPUARMState, vfp.zregs[24]) },
+ { HV_SME_Z_REG_25, offsetof(CPUARMState, vfp.zregs[25]) },
+ { HV_SME_Z_REG_26, offsetof(CPUARMState, vfp.zregs[26]) },
+ { HV_SME_Z_REG_27, offsetof(CPUARMState, vfp.zregs[27]) },
+ { HV_SME_Z_REG_28, offsetof(CPUARMState, vfp.zregs[28]) },
+ { HV_SME_Z_REG_29, offsetof(CPUARMState, vfp.zregs[29]) },
+ { HV_SME_Z_REG_30, offsetof(CPUARMState, vfp.zregs[30]) },
+ { HV_SME_Z_REG_31, offsetof(CPUARMState, vfp.zregs[31]) },
+};
+
+static const struct hvf_reg_match hvf_sme2_preg_match[] = {
+ { HV_SME_P_REG_0, offsetof(CPUARMState, vfp.pregs[0]) },
+ { HV_SME_P_REG_1, offsetof(CPUARMState, vfp.pregs[1]) },
+ { HV_SME_P_REG_2, offsetof(CPUARMState, vfp.pregs[2]) },
+ { HV_SME_P_REG_3, offsetof(CPUARMState, vfp.pregs[3]) },
+ { HV_SME_P_REG_4, offsetof(CPUARMState, vfp.pregs[4]) },
+ { HV_SME_P_REG_5, offsetof(CPUARMState, vfp.pregs[5]) },
+ { HV_SME_P_REG_6, offsetof(CPUARMState, vfp.pregs[6]) },
+ { HV_SME_P_REG_7, offsetof(CPUARMState, vfp.pregs[7]) },
+ { HV_SME_P_REG_8, offsetof(CPUARMState, vfp.pregs[8]) },
+ { HV_SME_P_REG_9, offsetof(CPUARMState, vfp.pregs[9]) },
+ { HV_SME_P_REG_10, offsetof(CPUARMState, vfp.pregs[10]) },
+ { HV_SME_P_REG_11, offsetof(CPUARMState, vfp.pregs[11]) },
+ { HV_SME_P_REG_12, offsetof(CPUARMState, vfp.pregs[12]) },
+ { HV_SME_P_REG_13, offsetof(CPUARMState, vfp.pregs[13]) },
+ { HV_SME_P_REG_14, offsetof(CPUARMState, vfp.pregs[14]) },
+ { HV_SME_P_REG_15, offsetof(CPUARMState, vfp.pregs[15]) },
+};
+
/*
* QEMU uses KVM system register ids in the migration format.
* Conveniently, HVF uses the same encoding of the op* and cr* parameters
@@ -406,22 +460,201 @@ static const struct hvf_reg_match hvf_fpreg_match[] = {
#define HVF_TO_KVMID(HVF) \
(CP_REG_ARM64 | CP_REG_SIZE_U64 | CP_REG_ARM64_SYSREG | (HVF))
-/* Verify this at compile-time. */
+/*
+ * Verify this at compile-time.
+ *
+ * SME2 registers are guarded by a runtime availability attribute instead of a
+ * compile-time def, so verify those at runtime in hvf_arch_init_vcpu() below.
+ */
#define DEF_SYSREG(HVF_ID, ...) \
QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
+#define DEF_SYSREG_15_02(...)
#include "sysreg.c.inc"
#undef DEF_SYSREG
+#undef DEF_SYSREG_15_02
#define DEF_SYSREG(HVF_ID, op0, op1, crn, crm, op2) HVF_ID,
+#define DEF_SYSREG_15_02(...)
static const hv_sys_reg_t hvf_sreg_list[] = {
#include "sysreg.c.inc"
};
#undef DEF_SYSREG
+#undef DEF_SYSREG_15_02
+
+#define DEF_SYSREG(...)
+#define DEF_SYSREG_15_02(HVF_ID, op0, op1, crn, crm, op2) HVF_ID,
+
+API_AVAILABLE(macos(15.2))
+static const hv_sys_reg_t hvf_sreg_list_sme2[] = {
+#include "sysreg.c.inc"
+};
+
+#undef DEF_SYSREG
+#undef DEF_SYSREG_15_02
+
+/*
+ * For FEAT_SME2 migration, we need to store PSTATE.{SM,ZA} bits which are
+ * accessible with the SVCR pseudo-register. However, in the HVF API this is
+ * not exposed as a system-register (i.e. HVF_SYS_REG_SVCR) but a custom
+ * struct, hv_vcpu_sme_state_t. So we need to define our own KVMID in order to
+ * store it in cpreg_values and make it migrateable.
+ */
+#define SVCR KVMID_AA64_SYS_REG64(3, 3, 4, 2, 2)
+
+API_AVAILABLE(macos(15.2))
+static void hvf_arch_put_sme(CPUState *cpu)
+{
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ const size_t svl_bytes = hvf_arm_sme2_get_svl();
+ const size_t z_size = svl_bytes;
+ const size_t preg_size = DIV_ROUND_UP(z_size, 8);
+ const size_t za_size = svl_bytes * svl_bytes;
+ hv_vcpu_sme_state_t sme_state = { 0 };
+ hv_return_t ret;
+ uint64_t svcr;
+ int n;
+
+ /*
+ * Set PSTATE.{SM,ZA} bits
+ */
+ svcr = arm_cpu->cpreg_values[arm_cpu->cpreg_array_len - 1];
+ env->svcr = svcr;
+
+ /*
+ * Construct SVCR (PSTATE.{SM,ZA}) state to pass to HVF:
+ */
+ sme_state.streaming_sve_mode_enabled = FIELD_EX64(env->svcr, SVCR, SM) > 0;
+ sme_state.za_storage_enabled = FIELD_EX64(env->svcr, SVCR, ZA) > 0;
+ ret = hv_vcpu_set_sme_state(cpu->accel->fd, &sme_state);
+ assert_hvf_ok(ret);
+
+ /*
+ * We only care about Z/P registers if we're in streaming SVE mode, i.e.
+ * PSTATE.SM is set, because only then can instructions that access them be
+ * used. We don't care about the register values otherwise. This is because
+ * when the processing unit exits/enters this mode, it zeroes out those
+ * registers.
+ */
+ if (sme_state.streaming_sve_mode_enabled) {
+ for (n = 0; n < ARRAY_SIZE(hvf_sme2_zreg_match); ++n) {
+ ret = hv_vcpu_set_sme_z_reg(cpu->accel->fd,
+ hvf_sme2_zreg_match[n].reg,
+ (uint8_t *)&env->vfp.zregs[n].d[0],
+ z_size);
+ assert_hvf_ok(ret);
+ }
+
+ for (n = 0; n < ARRAY_SIZE(hvf_sme2_preg_match); ++n) {
+ ret = hv_vcpu_set_sme_p_reg(cpu->accel->fd,
+ hvf_sme2_preg_match[n].reg,
+ (uint8_t *)&env->vfp.pregs[n].p[0],
+ preg_size);
+ assert_hvf_ok(ret);
+ }
+ }
+
+ /*
+ * If PSTATE.ZA bit is set then ZA and ZT0 are valid, otherwise they are
+ * zeroed out.
+ */
+ if (sme_state.za_storage_enabled) {
+ hv_sme_zt0_uchar64_t tmp = { 0 };
+
+ memcpy(&tmp, &env->za_state.zt0, 64);
+ ret = hv_vcpu_set_sme_zt0_reg(cpu->accel->fd, &tmp);
+ assert_hvf_ok(ret);
+
+ ret = hv_vcpu_set_sme_za_reg(cpu->accel->fd,
+ (uint8_t *)&env->za_state.za,
+ za_size);
+ assert_hvf_ok(ret);
+ }
+
+ return;
+}
+
+API_AVAILABLE(macos(15.2))
+static void hvf_arch_get_sme(CPUState *cpu)
+{
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ const size_t svl_bytes = hvf_arm_sme2_get_svl();
+ const size_t z_size = svl_bytes;
+ const size_t preg_size = DIV_ROUND_UP(z_size, 8);
+ const size_t za_size = svl_bytes * svl_bytes;
+ hv_vcpu_sme_state_t sme_state = { 0 };
+ hv_return_t ret;
+ uint64_t svcr;
+ int n;
+
+ /*
+ * Get SVCR (PSTATE.{SM,ZA}) state from HVF:
+ */
+ ret = hv_vcpu_get_sme_state(cpu->accel->fd, &sme_state);
+ assert_hvf_ok(ret);
+
+ /*
+ * Set SVCR first because changing it will zero out Z/P regs
+ */
+ svcr =
+ (sme_state.za_storage_enabled ? R_SVCR_ZA_MASK : 0)
+ | (sme_state.streaming_sve_mode_enabled ? R_SVCR_SM_MASK : 0);
+
+ aarch64_set_svcr(env, svcr, R_SVCR_ZA_MASK | R_SVCR_SM_MASK);
+ arm_cpu->cpreg_values[arm_cpu->cpreg_array_len - 1] = svcr;
+
+ /*
+ * We only care about Z/P registers if we're in streaming SVE mode, i.e.
+ * PSTATE.SM is set, because only then can instructions that access them be
+ * used. We don't care about the register values otherwise. This is because
+ * when the processing unit exits/enters this mode, it zeroes out those
+ * registers.
+ */
+ if (sme_state.streaming_sve_mode_enabled) {
+ for (n = 0; n < ARRAY_SIZE(hvf_sme2_zreg_match); ++n) {
+ ret = hv_vcpu_get_sme_z_reg(cpu->accel->fd,
+ hvf_sme2_zreg_match[n].reg,
+ (uint8_t *)&env->vfp.zregs[n].d[0],
+ z_size);
+ assert_hvf_ok(ret);
+ }
+
+ for (n = 0; n < ARRAY_SIZE(hvf_sme2_preg_match); ++n) {
+ ret = hv_vcpu_get_sme_p_reg(cpu->accel->fd,
+ hvf_sme2_preg_match[n].reg,
+ (uint8_t *)&env->vfp.pregs[n].p[0],
+ preg_size);
+ assert_hvf_ok(ret);
+ }
+ }
+
+ /*
+ * If PSTATE.ZA bit is set then ZA and ZT0 are valid, otherwise they are
+ * zeroed out.
+ */
+ if (sme_state.za_storage_enabled) {
+ hv_sme_zt0_uchar64_t tmp = { 0 };
+
+ /* Get ZT0 in a tmp vector, and then copy it to env.za_state.zt0 */
+ ret = hv_vcpu_get_sme_zt0_reg(cpu->accel->fd, &tmp);
+ assert_hvf_ok(ret);
+
+ memcpy(&env->za_state.zt0, &tmp, 64);
+ ret = hv_vcpu_get_sme_za_reg(cpu->accel->fd,
+ (uint8_t *)&env->za_state.za,
+ za_size);
+ assert_hvf_ok(ret);
+
+ }
+
+ return;
+}
static uint32_t hvf_reg2cp_reg(uint32_t reg)
{
@@ -534,6 +767,10 @@ int hvf_arch_get_registers(CPUState *cpu)
uint64_t kvm_id = arm_cpu->cpreg_indexes[i];
int hvf_id = KVMID_TO_HVF(kvm_id);
+ if (kvm_id == HVF_TO_KVMID(SVCR)) {
+ continue;
+ }
+
if (cpu->accel->guest_debug_enabled) {
/* Handle debug registers */
switch (hvf_id) {
@@ -627,6 +864,13 @@ int hvf_arch_get_registers(CPUState *cpu)
arm_cpu->cpreg_values[i] = val;
}
+ if (cpu_isar_feature(aa64_sme, arm_cpu)) {
+ if (__builtin_available(macOS 15.2, *)) {
+ hvf_arch_get_sme(cpu);
+ } else {
+ g_assert_not_reached();
+ }
+ }
assert(write_list_to_cpustate(arm_cpu));
aarch64_restore_sp(env, arm_current_el(env));
@@ -643,6 +887,18 @@ int hvf_arch_put_registers(CPUState *cpu)
hv_simd_fp_uchar16_t fpval;
int i, n;
+ /*
+ * Set SVCR first because changing it will zero out Z/P (including NEON)
+ * regs
+ */
+ if (cpu_isar_feature(aa64_sme, arm_cpu)) {
+ if (__builtin_available(macOS 15.2, *)) {
+ hvf_arch_put_sme(cpu);
+ } else {
+ g_assert_not_reached();
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) {
val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset);
ret = hv_vcpu_set_reg(cpu->accel->fd, hvf_reg_match[i].reg, val);
@@ -672,6 +928,10 @@ int hvf_arch_put_registers(CPUState *cpu)
uint64_t kvm_id = arm_cpu->cpreg_indexes[i];
int hvf_id = KVMID_TO_HVF(kvm_id);
+ if (kvm_id == HVF_TO_KVMID(SVCR)) {
+ continue;
+ }
+
if (cpu->accel->guest_debug_enabled) {
/* Handle debug registers */
switch (hvf_id) {
@@ -985,6 +1245,18 @@ int hvf_arch_init_vcpu(CPUState *cpu)
hv_return_t ret;
int i;
+ if (__builtin_available(macOS 15.2, *)) {
+ sregs_match_len += ARRAY_SIZE(hvf_sreg_list_sme2) + 1;
+
+#define DEF_SYSREG_15_02(HVF_ID, ...) \
+ g_assert(HVF_ID == KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
+#define DEF_SYSREG(...)
+
+#include "sysreg.c.inc"
+
+#undef DEF_SYSREG
+#undef DEF_SYSREG_15_02
+ }
env->aarch64 = true;
/* system count frequency sanity check */
@@ -1005,7 +1277,7 @@ int hvf_arch_init_vcpu(CPUState *cpu)
memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t));
/* Populate cp list for all known sysregs */
- for (i = 0; i < sregs_match_len; i++) {
+ for (i = 0; i < ARRAY_SIZE(hvf_sreg_list); i++) {
hv_sys_reg_t hvf_id = hvf_sreg_list[i];
uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
uint32_t key = kvm_to_cpreg_id(kvm_id);
@@ -1016,6 +1288,24 @@ int hvf_arch_init_vcpu(CPUState *cpu)
arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
}
}
+ if (__builtin_available(macOS 15.2, *)) {
+ for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
+ hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i];
+ uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
+ uint32_t key = kvm_to_cpreg_id(kvm_id);
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
+
+ if (ri) {
+ assert(!(ri->type & ARM_CP_NO_RAW));
+ arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
+ }
+ }
+ /*
+ * Add SVCR last. It is elsewhere assumed its index is after
+ * hvf_sreg_list and hvf_sreg_list_sme2.
+ */
+ arm_cpu->cpreg_indexes[sregs_cnt++] = HVF_TO_KVMID(SVCR);
+ }
arm_cpu->cpreg_array_len = sregs_cnt;
arm_cpu->cpreg_vmstate_array_len = sregs_cnt;
diff --git a/target/arm/hvf/hvf_sme_stubs.h b/target/arm/hvf/hvf_sme_stubs.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c679b711017448681e532b88ce10a07ebfd5122
--- /dev/null
+++ b/target/arm/hvf/hvf_sme_stubs.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+typedef int32_t hv_return_t;
+typedef uint64_t hv_vcpu_t;
+
+static inline bool hvf_arm_sme2_supported(void)
+{
+ return false;
+}
+
+static inline uint32_t hvf_arm_sme2_get_svl(void)
+{
+ g_assert_not_reached();
+}
+
+typedef enum hv_sme_p_reg_t {
+ HV_SME_P_REG_0,
+ HV_SME_P_REG_1,
+ HV_SME_P_REG_2,
+ HV_SME_P_REG_3,
+ HV_SME_P_REG_4,
+ HV_SME_P_REG_5,
+ HV_SME_P_REG_6,
+ HV_SME_P_REG_7,
+ HV_SME_P_REG_8,
+ HV_SME_P_REG_9,
+ HV_SME_P_REG_10,
+ HV_SME_P_REG_11,
+ HV_SME_P_REG_12,
+ HV_SME_P_REG_13,
+ HV_SME_P_REG_14,
+ HV_SME_P_REG_15,
+} hv_sme_p_reg_t;
+
+typedef __attribute__((ext_vector_type(64))) uint8_t hv_sme_zt0_uchar64_t;
+
+typedef enum hv_sme_z_reg_t {
+ HV_SME_Z_REG_0,
+ HV_SME_Z_REG_1,
+ HV_SME_Z_REG_2,
+ HV_SME_Z_REG_3,
+ HV_SME_Z_REG_4,
+ HV_SME_Z_REG_5,
+ HV_SME_Z_REG_6,
+ HV_SME_Z_REG_7,
+ HV_SME_Z_REG_8,
+ HV_SME_Z_REG_9,
+ HV_SME_Z_REG_10,
+ HV_SME_Z_REG_11,
+ HV_SME_Z_REG_12,
+ HV_SME_Z_REG_13,
+ HV_SME_Z_REG_14,
+ HV_SME_Z_REG_15,
+ HV_SME_Z_REG_16,
+ HV_SME_Z_REG_17,
+ HV_SME_Z_REG_18,
+ HV_SME_Z_REG_19,
+ HV_SME_Z_REG_20,
+ HV_SME_Z_REG_21,
+ HV_SME_Z_REG_22,
+ HV_SME_Z_REG_23,
+ HV_SME_Z_REG_24,
+ HV_SME_Z_REG_25,
+ HV_SME_Z_REG_26,
+ HV_SME_Z_REG_27,
+ HV_SME_Z_REG_28,
+ HV_SME_Z_REG_29,
+ HV_SME_Z_REG_30,
+ HV_SME_Z_REG_31,
+} hv_sme_z_reg_t;
+
+enum {
+ HV_SYS_REG_SMCR_EL1,
+ HV_SYS_REG_SMPRI_EL1,
+ HV_SYS_REG_TPIDR2_EL0,
+ HV_SYS_REG_ID_AA64ZFR0_EL1,
+ HV_SYS_REG_ID_AA64SMFR0_EL1,
+};
+
+typedef struct {
+ bool streaming_sve_mode_enabled;
+ bool za_storage_enabled;
+} hv_vcpu_sme_state_t;
+
+static inline hv_return_t hv_sme_config_get_max_svl_bytes(size_t *value)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_get_sme_state(hv_vcpu_t vcpu,
+ hv_vcpu_sme_state_t *sme_state)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_set_sme_state(hv_vcpu_t vcpu,
+ const hv_vcpu_sme_state_t *sme_state)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_get_sme_z_reg(hv_vcpu_t vcpu,
+ hv_sme_z_reg_t reg,
+ uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_set_sme_z_reg(hv_vcpu_t vcpu,
+ hv_sme_z_reg_t reg,
+ const uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_get_sme_p_reg(hv_vcpu_t vcpu,
+ hv_sme_p_reg_t reg,
+ uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_set_sme_p_reg(hv_vcpu_t vcpu,
+ hv_sme_p_reg_t reg,
+ const uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_get_sme_za_reg(hv_vcpu_t vcpu,
+ uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_set_sme_za_reg(hv_vcpu_t vcpu,
+ const uint8_t *value,
+ size_t length)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_get_sme_zt0_reg(hv_vcpu_t vcpu,
+ hv_sme_zt0_uchar64_t *value)
+{
+ g_assert_not_reached();
+}
+
+static inline hv_return_t hv_vcpu_set_sme_zt0_reg(hv_vcpu_t vcpu,
+ const hv_sme_zt0_uchar64_t *value)
+{
+ g_assert_not_reached();
+}
diff --git a/target/arm/hvf/sysreg.c.inc b/target/arm/hvf/sysreg.c.inc
index 067a8603fa785593ed0879cea26d036b0ec2823e..7a2f880f784b7610b14a6eb91fec1817e98bfd2e 100644
--- a/target/arm/hvf/sysreg.c.inc
+++ b/target/arm/hvf/sysreg.c.inc
@@ -145,3 +145,11 @@ DEF_SYSREG(HV_SYS_REG_TPIDRRO_EL0, 3, 3, 13, 0, 3)
DEF_SYSREG(HV_SYS_REG_CNTV_CTL_EL0, 3, 3, 14, 3, 1)
DEF_SYSREG(HV_SYS_REG_CNTV_CVAL_EL0, 3, 3, 14, 3, 2)
DEF_SYSREG(HV_SYS_REG_SP_EL1, 3, 4, 4, 1, 0)
+
+DEF_SYSREG_15_02(HV_SYS_REG_SMCR_EL1, 3, 0, 1, 2, 6)
+DEF_SYSREG_15_02(HV_SYS_REG_SMPRI_EL1, 3, 0, 1, 2, 4)
+DEF_SYSREG_15_02(HV_SYS_REG_TPIDR2_EL0, 3, 3, 13, 0, 5)
+DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
+DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5)
+DEF_SYSREG_15_02(HV_SYS_REG_SMPRI_EL1, 3, 0, 1, 2, 4)
+DEF_SYSREG_15_02(HV_SYS_REG_SMCR_EL1, 3, 0, 1, 2, 6)
diff --git a/target/arm/hvf_arm.h b/target/arm/hvf_arm.h
index 5d19d82e5ded66bc02da10523c0f7138840ecff3..6b1c3b9792dfd7d81ef747d8a6676a23fd212d84 100644
--- a/target/arm/hvf_arm.h
+++ b/target/arm/hvf_arm.h
@@ -22,4 +22,45 @@ void hvf_arm_init_debug(void);
void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu);
+/*
+ * We need access to types from macOS SDK >=15.2, so expose stubs if the
+ * headers are not available until we raise our minimum macOS version.
+ */
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
+ #if (__MAC_OS_X_VERSION_MAX_ALLOWED >= 150200)
+ #include "system/hvf_int.h"
+
+ static inline bool hvf_arm_sme2_supported(void)
+ {
+ if (__builtin_available(macOS 15.2, *)) {
+ size_t svl_bytes;
+ hv_return_t result = hv_sme_config_get_max_svl_bytes(&svl_bytes);
+ if (result == HV_UNSUPPORTED) {
+ return false;
+ }
+ assert_hvf_ok(result);
+ return svl_bytes > 0;
+ } else {
+ return false;
+ }
+ }
+
+ static inline uint32_t hvf_arm_sme2_get_svl(void)
+ {
+ if (__builtin_available(macOS 15.2, *)) {
+ size_t svl_bytes;
+ hv_return_t result = hv_sme_config_get_max_svl_bytes(&svl_bytes);
+ assert_hvf_ok(result);
+ return svl_bytes;
+ } else {
+ abort();
+ }
+ }
+ #else /* (__MAC_OS_X_VERSION_MAX_ALLOWED >= 150200) */
+ #include "hvf/hvf_sme_stubs.h"
+ #endif /* (__MAC_OS_X_VERSION_MAX_ALLOWED >= 150200) */
+#else /* ifdef __MAC_OS_X_VERSION_MAX_ALLOWED */
+ #include "hvf/hvf_sme_stubs.h"
+#endif /* ifdef __MAC_OS_X_VERSION_MAX_ALLOWED */
+
#endif
diff --git a/target/arm/machine.c b/target/arm/machine.c
index bbaae3444928985813b7dcc91888784d06cfe305..81a506ce4cc09493dd7faed88652d8d246e23187 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -231,7 +231,7 @@ static bool sve_needed(void *opaque)
{
ARMCPU *cpu = opaque;
- return cpu_isar_feature(aa64_sve, cpu);
+ return cpu_isar_feature(aa64_sve, cpu) || cpu_isar_feature(aa64_sme, cpu);
}
/* The first two words of each Zreg is stored in VFP state. */
--
2.47.3
On Tue, 3 Mar 2026 at 07:42, Manos Pitsidianakis
<manos.pitsidianakis@linaro.org> wrote:
>
> SME2 support adds the following state for HVF guests:
>
> - Vector registers Z0, ... , Z31 (introduced by FEAT_SVE but HVF does
> not support it)
> - Predicate registers P0, .., P15 (also FEAT_SVE)
> - ZA register
> - ZT0 register
> - PSTATE.{SM,ZA} bits (SVCR pseudo-register)
> - SMPRI_EL1 which handles the PE's priority in the SMCU
> - TPIDR2_EL0 the thread local ID register for SME
Mohamed points out that this breaks the build when compiling
with GCC (which I hadn't noticed because I happen to do my testing
of target-arm with clang on Linux these days):
> --- /dev/null
> +++ b/target/arm/hvf/hvf_sme_stubs.h
> @@ -0,0 +1,158 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +typedef int32_t hv_return_t;
> +typedef uint64_t hv_vcpu_t;
> +typedef __attribute__((ext_vector_type(64))) uint8_t hv_sme_zt0_uchar64_t;
The "ext_vector_type()" attribute is clang specific and gcc
doesn't recognize it.
Since we're defining all these types specifically because the system
headers are not providing them and only for the prototypes, my
preference would be to simply drop the attribute from this
declaration:
typedef uint8_t hv_sme_zt0_uchar64_t;
Could somebody confirm that that works OK on the relevant macos
configurations ?
thanks
-- PMM
On Fri, Mar 6, 2026 at 11:19 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Tue, 3 Mar 2026 at 07:42, Manos Pitsidianakis
> <manos.pitsidianakis@linaro.org> wrote:
> >
> > SME2 support adds the following state for HVF guests:
> >
> > - Vector registers Z0, ... , Z31 (introduced by FEAT_SVE but HVF does
> > not support it)
> > - Predicate registers P0, .., P15 (also FEAT_SVE)
> > - ZA register
> > - ZT0 register
> > - PSTATE.{SM,ZA} bits (SVCR pseudo-register)
> > - SMPRI_EL1 which handles the PE's priority in the SMCU
> > - TPIDR2_EL0 the thread local ID register for SME
>
> Mohamed points out that this breaks the build when compiling
> with GCC (which I hadn't noticed because I happen to do my testing
> of target-arm with clang on Linux these days):
Oops. same here, I was using clang.
>
> > --- /dev/null
> > +++ b/target/arm/hvf/hvf_sme_stubs.h
> > @@ -0,0 +1,158 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +
> > +typedef int32_t hv_return_t;
> > +typedef uint64_t hv_vcpu_t;
>
>
> > +typedef __attribute__((ext_vector_type(64))) uint8_t hv_sme_zt0_uchar64_t;
>
> The "ext_vector_type()" attribute is clang specific and gcc
> doesn't recognize it.
>
> Since we're defining all these types specifically because the system
> headers are not providing them and only for the prototypes, my
> preference would be to simply drop the attribute from this
> declaration:
>
> typedef uint8_t hv_sme_zt0_uchar64_t;
>
> Could somebody confirm that that works OK on the relevant macos
> configurations ?
I think this works. Do you want me to send a new revision?
>
> thanks
> -- PMM
--
Manos Pitsidianakis
Emulation and Virtualization Engineer at Linaro Ltd
On Fri, 6 Mar 2026 at 09:31, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote: > > On Fri, Mar 6, 2026 at 11:19 AM Peter Maydell <peter.maydell@linaro.org> wrote: > > Mohamed points out that this breaks the build when compiling > > with GCC (which I hadn't noticed because I happen to do my testing > > of target-arm with clang on Linux these days): > > Oops. same here, I was using clang. > > typedef uint8_t hv_sme_zt0_uchar64_t; > > > > Could somebody confirm that that works OK on the relevant macos > > configurations ? > > I think this works. Do you want me to send a new revision? If you can test it for the macos configs I can just make the change locally. I have: +/* + * The system version of this type declares it with + * __attribute__((ext_vector_type(64))) + * However, that is clang specific and not supported by GCC. + * Since these headers are only here for the case where the system + * headers do not provide these types (including both older macos + * and non-macos hosts), we don't need to make the type match + * exactly, so we declare it as a plain uint8_t. + */ +typedef uint8_t hv_sme_zt0_uchar64_t; While you're retesting, could you also look at / test patches 17 and 18 in Mohamed's series https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d ? They look to me like bugfixes that we should be squashing/including in the "enable SME2 for hvf" handling. thanks -- PMM
On Fri, Mar 6, 2026 at 11:48 AM Peter Maydell <peter.maydell@linaro.org> wrote: > > On Fri, 6 Mar 2026 at 09:31, Manos Pitsidianakis > <manos.pitsidianakis@linaro.org> wrote: > > > > On Fri, Mar 6, 2026 at 11:19 AM Peter Maydell <peter.maydell@linaro.org> wrote: > > > Mohamed points out that this breaks the build when compiling > > > with GCC (which I hadn't noticed because I happen to do my testing > > > of target-arm with clang on Linux these days): > > > > Oops. same here, I was using clang. > > > > typedef uint8_t hv_sme_zt0_uchar64_t; > > > > > > Could somebody confirm that that works OK on the relevant macos > > > configurations ? > > > > I think this works. Do you want me to send a new revision? > > If you can test it for the macos configs I can just make the change > locally. I have: Tested it with gcc on linux and on macos, thanks. > +/* > + * The system version of this type declares it with > + * __attribute__((ext_vector_type(64))) > + * However, that is clang specific and not supported by GCC. > + * Since these headers are only here for the case where the system > + * headers do not provide these types (including both older macos > + * and non-macos hosts), we don't need to make the type match > + * exactly, so we declare it as a plain uint8_t. > + */ > +typedef uint8_t hv_sme_zt0_uchar64_t; > > While you're retesting, could you also look at / test patches > 17 and 18 in Mohamed's series > https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d > > ? > > They look to me like bugfixes that we should be squashing/including > in the "enable SME2 for hvf" handling. Had a quick look, 17 seems to be nested-virt specific so not a bugfix if nested-virt was not already supported in the first place, right? As for 18: I'm not sure why this is needed (I'm not that familiar with HVF API) and there's no commit message to explain. @Mohamed Mediouni can you help? > > thanks > -- PMM -- Manos Pitsidianakis Emulation and Virtualization Engineer at Linaro Ltd
> On 6. Mar 2026, at 11:05, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote:
>
> On Fri, Mar 6, 2026 at 11:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>> On Fri, 6 Mar 2026 at 09:31, Manos Pitsidianakis
>> <manos.pitsidianakis@linaro.org> wrote:
>>>
>>> On Fri, Mar 6, 2026 at 11:19 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>>>> Mohamed points out that this breaks the build when compiling
>>>> with GCC (which I hadn't noticed because I happen to do my testing
>>>> of target-arm with clang on Linux these days):
>>>
>>> Oops. same here, I was using clang.
>>
>>>> typedef uint8_t hv_sme_zt0_uchar64_t;
>>>>
>>>> Could somebody confirm that that works OK on the relevant macos
>>>> configurations ?
>>>
>>> I think this works. Do you want me to send a new revision?
>>
>> If you can test it for the macos configs I can just make the change
>> locally. I have:
>
> Tested it with gcc on linux and on macos, thanks.
>
>> +/*
>> + * The system version of this type declares it with
>> + * __attribute__((ext_vector_type(64)))
>> + * However, that is clang specific and not supported by GCC.
>> + * Since these headers are only here for the case where the system
>> + * headers do not provide these types (including both older macos
>> + * and non-macos hosts), we don't need to make the type match
>> + * exactly, so we declare it as a plain uint8_t.
>> + */
>> +typedef uint8_t hv_sme_zt0_uchar64_t;
>
>
>>
>> While you're retesting, could you also look at / test patches
>> 17 and 18 in Mohamed's series
>> https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d
>>
>> ?
>>
>> They look to me like bugfixes that we should be squashing/including
>> in the "enable SME2 for hvf" handling.
>
> Had a quick look, 17 seems to be nested-virt specific so not a bugfix
> if nested-virt was not already supported in the first place, right?
Hello,
This part isn’t:
@@ -1370,16 +1373,22 @@ int hvf_arch_init_vcpu(CPUState *cpu)
arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
}
}
- if (__builtin_available(macOS 15.2, *)) {
- for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
- hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
- uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
- uint32_t key = kvm_to_cpreg_id(kvm_id);
- const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
-
- if (ri) {
- assert(!(ri->type & ARM_CP_NO_RAW));
- arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
+ if (hvf_arm_sme2_supported()) {
+ /*
+ * Clang doesn't allow us to combine the two checks together.
+ * -Wunsupported-availability-guard
+ */
+ if (__builtin_available(macOS 15.2, *)) {
+ for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
+ hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
+ uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
+ uint32_t key = kvm_to_cpreg_id(kvm_id);
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
+
+ if (ri) {
+ assert(!(ri->type & ARM_CP_NO_RAW));
+ arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
+ }
}
}
/*
For CPUs that don’t have SME
But the remainder of the patch is. Probably worth it to just merge it all as part of the nested virt stuff though...
>
> As for 18: I'm not sure why this is needed (I'm not that familiar with
> HVF API) and there's no commit message to explain. @Mohamed Mediouni
> can you help?
We have this in sysreg.c.inc:
DEF_SYSREG_15_02(HV_SYS_REG_SMCR_EL1, 3, 0, 1, 2, 6)
DEF_SYSREG_15_02(HV_SYS_REG_SMPRI_EL1, 3, 0, 1, 2, 4)
DEF_SYSREG_15_02(HV_SYS_REG_TPIDR2_EL0, 3, 3, 13, 0, 5)
DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5)
DEF_SYSREG_15_02(HV_SYS_REG_SMPRI_EL1, 3, 0, 1, 2, 4)
DEF_SYSREG_15_02(HV_SYS_REG_SMCR_EL1, 3, 0, 1, 2, 6)
which means that actual sysreg state gets synced from the QEMU view including for the ID_AA64SMFR0_EL1 and ID_AA64ZFR0_EL1 feature registers.
See /proc/cpuinfo from a Linux guest with and without the patch,
without it the QEMU view of those ID regs is empty… and that empty view
gets synced in to the vCPU state.
Thank you,
-Mohamed
>>
>> thanks
>> -- PMM
>
> --
> Manos Pitsidianakis
> Emulation and Virtualization Engineer at Linaro Ltd
>
On Fri, 6 Mar 2026 at 10:19, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
> > On 6. Mar 2026, at 11:05, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote:
> >
> > On Fri, Mar 6, 2026 at 11:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> >> While you're retesting, could you also look at / test patches
> >> 17 and 18 in Mohamed's series
> >> https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d
> >>
> >> ?
> >>
> >> They look to me like bugfixes that we should be squashing/including
> >> in the "enable SME2 for hvf" handling.
> >
> > Had a quick look, 17 seems to be nested-virt specific so not a bugfix
> > if nested-virt was not already supported in the first place, right?
>
> Hello,
>
> This part isn’t:
>
> @@ -1370,16 +1373,22 @@ int hvf_arch_init_vcpu(CPUState *cpu)
> arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> }
> }
> - if (__builtin_available(macOS 15.2, *)) {
> - for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
> - hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
> - uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
> - uint32_t key = kvm_to_cpreg_id(kvm_id);
> - const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
> -
> - if (ri) {
> - assert(!(ri->type & ARM_CP_NO_RAW));
> - arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> + if (hvf_arm_sme2_supported()) {
> + /*
> + * Clang doesn't allow us to combine the two checks together.
> + * -Wunsupported-availability-guard
> + */
> + if (__builtin_available(macOS 15.2, *)) {
> + for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
> + hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
> + uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
> + uint32_t key = kvm_to_cpreg_id(kvm_id);
> + const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
> +
> + if (ri) {
> + assert(!(ri->type & ARM_CP_NO_RAW));
> + arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> + }
> }
Yes; the patch is doing two things and really ought to be two patches,
so we can put the bit that we need for "make SME2 hvf work correctly"
before the "enable SME2 HVF" patch, and the bit that is nested-virt
specific in the nested-virt patches.
thanks
-- PMM
On Fri, Mar 6, 2026 at 1:14 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Fri, 6 Mar 2026 at 10:19, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
> > > On 6. Mar 2026, at 11:05, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote:
> > >
> > > On Fri, Mar 6, 2026 at 11:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > >> While you're retesting, could you also look at / test patches
> > >> 17 and 18 in Mohamed's series
> > >> https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d
> > >>
> > >> ?
> > >>
> > >> They look to me like bugfixes that we should be squashing/including
> > >> in the "enable SME2 for hvf" handling.
> > >
> > > Had a quick look, 17 seems to be nested-virt specific so not a bugfix
> > > if nested-virt was not already supported in the first place, right?
> >
> > Hello,
> >
> > This part isn’t:
> >
> > @@ -1370,16 +1373,22 @@ int hvf_arch_init_vcpu(CPUState *cpu)
> > arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> > }
> > }
> > - if (__builtin_available(macOS 15.2, *)) {
> > - for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
> > - hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
> > - uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
> > - uint32_t key = kvm_to_cpreg_id(kvm_id);
> > - const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
> > -
> > - if (ri) {
> > - assert(!(ri->type & ARM_CP_NO_RAW));
> > - arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> > + if (hvf_arm_sme2_supported()) {
> > + /*
> > + * Clang doesn't allow us to combine the two checks together.
> > + * -Wunsupported-availability-guard
> > + */
> > + if (__builtin_available(macOS 15.2, *)) {
> > + for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
> > + hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
> > + uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
> > + uint32_t key = kvm_to_cpreg_id(kvm_id);
> > + const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
> > +
> > + if (ri) {
> > + assert(!(ri->type & ARM_CP_NO_RAW));
> > + arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
> > + }
> > }
>
> Yes; the patch is doing two things and really ought to be two patches,
> so we can put the bit that we need for "make SME2 hvf work correctly"
> before the "enable SME2 HVF" patch, and the bit that is nested-virt
> specific in the nested-virt patches.
>
Patch v18 needs an adjustment, because clang prints warnings about the
`static const struct sme_isar_regs` array.
../target/arm/hvf/hvf.c:1098:11: warning:
'HV_FEATURE_REG_ID_AA64SMFR0_EL1' is only available on macOS 15.2 or
newer [-Wunguarded-availability-new]
Peter,
Maybe I should send a new revision since you haven't merged these
patches anyway?
> thanks
> -- PMM
--
Manos Pitsidianakis
Emulation and Virtualization Engineer at Linaro Ltd
On Fri, 6 Mar 2026 at 11:49, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote: > Patch v18 needs an adjustment, because clang prints warnings about the > `static const struct sme_isar_regs` array. > > > ../target/arm/hvf/hvf.c:1098:11: warning: > 'HV_FEATURE_REG_ID_AA64SMFR0_EL1' is only available on macOS 15.2 or > newer [-Wunguarded-availability-new] > > Peter, > > Maybe I should send a new revision since you haven't merged these > patches anyway? Yes please, if you could do that that would be really helpful. -- PMM
> On 6. Mar 2026, at 12:49, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote:
>
> On Fri, Mar 6, 2026 at 1:14 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>> On Fri, 6 Mar 2026 at 10:19, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
>>>> On 6. Mar 2026, at 11:05, Manos Pitsidianakis <manos.pitsidianakis@linaro.org> wrote:
>>>>
>>>> On Fri, Mar 6, 2026 at 11:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>>>>> While you're retesting, could you also look at / test patches
>>>>> 17 and 18 in Mohamed's series
>>>>> https://lore.kernel.org/qemu-devel/20260306083113.74177-18-mohamed@unpredictable.fr/T/#m2d1e3dfbfa5aecd41af6c0aa9e3b574a72c6f04d
>>>>>
>>>>> ?
>>>>>
>>>>> They look to me like bugfixes that we should be squashing/including
>>>>> in the "enable SME2 for hvf" handling.
>>>>
>>>> Had a quick look, 17 seems to be nested-virt specific so not a bugfix
>>>> if nested-virt was not already supported in the first place, right?
>>>
>>> Hello,
>>>
>>> This part isn’t:
>>>
>>> @@ -1370,16 +1373,22 @@ int hvf_arch_init_vcpu(CPUState *cpu)
>>> arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
>>> }
>>> }
>>> - if (__builtin_available(macOS 15.2, *)) {
>>> - for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
>>> - hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
>>> - uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
>>> - uint32_t key = kvm_to_cpreg_id(kvm_id);
>>> - const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
>>> -
>>> - if (ri) {
>>> - assert(!(ri->type & ARM_CP_NO_RAW));
>>> - arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
>>> + if (hvf_arm_sme2_supported()) {
>>> + /*
>>> + * Clang doesn't allow us to combine the two checks together.
>>> + * -Wunsupported-availability-guard
>>> + */
>>> + if (__builtin_available(macOS 15.2, *)) {
>>> + for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
>>> + hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
>>> + uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
>>> + uint32_t key = kvm_to_cpreg_id(kvm_id);
>>> + const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
>>> +
>>> + if (ri) {
>>> + assert(!(ri->type & ARM_CP_NO_RAW));
>>> + arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
>>> + }
>>> }
>>
>> Yes; the patch is doing two things and really ought to be two patches,
>> so we can put the bit that we need for "make SME2 hvf work correctly"
>> before the "enable SME2 HVF" patch, and the bit that is nested-virt
>> specific in the nested-virt patches.
>>
>
> Patch v18 needs an adjustment, because clang prints warnings about the
> `static const struct sme_isar_regs` array.
>
Hello,
Put an updated version of my branch to https://github.com/mediouni-m/qemu/commits/hvf-irqchip-and-nested/
Feel free to pick the needed patches from it/squash as needed :)
>
> ../target/arm/hvf/hvf.c:1098:11: warning:
> 'HV_FEATURE_REG_ID_AA64SMFR0_EL1' is only available on macOS 15.2 or
> newer [-Wunguarded-availability-new]
>
> Peter,
>
> Maybe I should send a new revision since you haven't merged these
> patches anyway?
>
>> thanks
>> -- PMM
>
> --
> Manos Pitsidianakis
> Emulation and Virtualization Engineer at Linaro Ltd
© 2016 - 2026 Red Hat, Inc.