Hi Manos,

Mostly nitpicking comments :)

On 15/1/26 12:20, Manos Pitsidianakis 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

Signed-off-by: Manos Pitsidianakis <[email protected]>
---
  target/arm/hvf/hvf.c           | 285 ++++++++++++++++++++++++++++++++++++++++-
  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, 491 insertions(+), 3 deletions(-)


  int hvf_arch_get_registers(CPUState *cpu)
  {
@@ -465,6 +698,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) {
@@ -558,6 +795,11 @@ int hvf_arch_get_registers(CPUState *cpu)
arm_cpu->cpreg_values[i] = val;
      }
+    if (__builtin_available(macOS 15.2, *)) {
+        if (cpu_isar_feature(aa64_sme, arm_cpu)) {
+            hvf_arch_get_sme(cpu);
+        }
+    }

What about:

       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));
@@ -603,6 +845,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) {
@@ -687,6 +933,11 @@ int hvf_arch_put_registers(CPUState *cpu)
      ret = hv_vcpu_set_vtimer_offset(cpu->accel->fd, hvf_state->vtimer_offset);
      assert_hvf_ok(ret);
+ if (__builtin_available(macOS 15.2, *)) {
+        if (cpu_isar_feature(aa64_sme, arm_cpu)) {
+            hvf_arch_put_sme(cpu);
+        }
+    }
      return 0;
  }
@@ -909,6 +1160,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;
      asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
@@ -927,7 +1190,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);
@@ -938,6 +1201,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);
+    }

Could we add as a hvf_arch_init_sme() helper instead?

      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;

We certainly already have these.

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

Hmm do we need those? Could we just define the typedef?

  typedef uint32_t hv_sme_p_reg_t;
  typedef uint32_t hv_sme_z_reg_t;
  typedef void *hv_sme_zt0_uchar64_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();
+}

Reply via email to