Re: [PATCH v22 23/23] KVM: arm64: CCA: Control user register access for Realms

From: Suzuki K Poulose

Date: Tue Oct 06 2026 - 08:37:43 EST


On 06/10/2026 07:16, Gavin Shan wrote:
On 10/6/26 4:01 PM, Suzuki K Poulose wrote:
On 06/10/2026 06:47, Gavin Shan wrote:
On 10/5/26 7:07 PM, Suzuki K Poulose wrote:
From: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx>

The RMM restricts the access to the register states that the host can
read/modify for a given Realm.

e.g., At VCPU creation, can modify GPRS (x0-x30) and PC.
       While servicing SMCCC calls via RSI_HOST_CALL or servicing PSCI
       requests.
       MMIO emulation in the unprotected space.

Additionally we use the sysreg configuration to advertise/configure the
following Realm parameters, which are required before the Realm Descriptor
is created:
  - SVE Vector Length
  - Number of HW Breakpoints/Watchpoints
  - PMU Counters.

Thus KVM also additionally allows access to ID_AA64DFR0_EL1 and SVE_VLS for
the configuration of Realm creation parameters. We don't support PMUs for
the Realm VMs yet, so PMCR is not exposed.

The RMM makes similar restrictions for reading of the guest's registers
(this is *confidential* compute after all), however we don't impose the
restriction here. This allows the VMM to read (stale) values from the
registers which might be useful to read back the initial values even if
the RMM doesn't provide the latest version. For migration of a realm VM,
a new interface will be needed so that the VMM can receive an
(encrypted) blob of the VM's state.

Reflect the above in KVM_GET_REG_LIST, KVM_SET_ONE_REG calls.

  static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off)
  {
      int size;
@@ -553,6 +572,9 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
          u64 reg = KVM_REG_ARM64 | KVM_REG_ARM_CORE | i;
          int size = core_reg_size_from_offset(vcpu, i);
+        if (vcpu_is_rec(vcpu) && !kvm_realm_validate_core_reg(i))
+            continue;
+
          if (size < 0)
              continue;
@@ -598,6 +620,9 @@ static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
      if (!vcpu_has_sve(vcpu))
          return 0;
+    if (kvm_vm_is_realm(vcpu->kvm))
+        return 1; /* KVM_REG_ARM64_SVE_VLS */
+

This could be vcpu_is_rec().
      if (!kvm_arm_vcpu_sve_finalized(vcpu))
          return 1; /* KVM_REG_ARM64_SVE_VLS */


Aren't above two checks conflicting to each other?

Do they? We allow SVE_VLS only for the Realms and we allow that
before the vCPUs are finalized. For normal VMs, depending on
whether the vcpus are finalized, we either send 1 or the full list.


num_sve_regs() can be called for 3 cases: (a) non-finalized RECs; (b) finalized
RECs; (c) Other finalized vCPUs, correct? "if (kvm_vm_is_realm(vcpu- >kvm))", which
would be "if (vcpu_is_rec(vcpu))", covers (a) and (b). We needn't the excessive
check "if (!kvm_arm_vcpu_sve_finalized(vcpu))". So the check would be something
as below after this series is applied:

    /*
     * KVM_REG_ARM64_SVE_VLS is visible on realm vCPU no matter if it
     * has been finalized.
     */
    if (vcpu_is_rec(vcpu))
        return 1;

This check "if (vcpu_is_rec(vcpu))" belongs to PATCH[22]. Hope I make myself
clear this time :)

Sure, these two patches are closely related and may be even could be
folded in. I split it out to make it easier to review.

22: Allow exposing SVE_VLS for unfinalized VCPU RECs
23: Control register accesses includingthe SVE_VLS, but prevent
everything else

Does it help ?

Cheers
Suzuki




@@ -625,6 +650,10 @@ static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu,
          return -EFAULT;
      ++num_regs;
+    /* For Realms only support SVE_VLS */
+    if (kvm_vm_is_realm(vcpu->kvm))
+        return num_regs;
+
      if (!kvm_arm_vcpu_sve_finalized(vcpu))
          return num_regs;

Same question here.

As above.

Suzuki

Thanks,
Gavin