[PATCH v16 16/45] KVM: arm64: CCA: Allow passing the machine type in KVM creation
Gavin Shan
gshan at redhat.com
Mon Aug 31 21:45:35 PDT 2026
Hi Steve,
On 8/3/26 11:43 PM, Steven Price wrote:
> Previously machine type was used purely for specifying the physical
> address size of the guest. Reserve the higher bits to specify an ARM
> specific machine type and declare a new type 'KVM_VM_TYPE_ARM_REALM'
> used to create a realm guest.
>
> Signed-off-by: Steven Price <steven.price at arm.com>
> ---
> Changes since v15:
> * Specify the encoding for each VM type in the documentation.
> Changes since v13:
> * Rework to use the two top bits for the machine type now that pKVM has
> merged and used the top bit for KVM_VM_TYPE_ARM_PROTECTED.
> * Update the documentation to include KVM_VM_TYPE_ARM_PROTECTED as
> well.
> Changes since v9:
> * Explictly set realm.state to REALM_STATE_NONE rather than rely on the
> zeroing of the structure.
> Changes since v7:
> * Add some documentation explaining the new machine type.
> Changes since v6:
> * Make the check for kvm_rme_is_available more visible and report an
> error code of -EPERM (instead of -EINVAL) to make it explicit that
> the kernel supports RME, but the platform doesn't.
> ---
> Documentation/virt/kvm/api.rst | 21 +++++++++++++++++++--
> arch/arm64/kvm/arm.c | 11 +++++++++++
> include/uapi/linux/kvm.h | 7 ++++++-
> 3 files changed, 36 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index ce588c05b26a..802601eaf560 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -181,8 +181,25 @@ flag KVM_VM_MIPS_VZ.
> ARM64:
> ^^^^^^
>
> -On arm64, the physical address size for a VM (IPA Size limit) is limited
> -to 40bits by default. The limit can be configured if the host supports the
> +On arm64, the machine type identifier is used to encode a type and the
> +physical address size for the VM. The lower byte (bits[7:0]) encodes the
> +address size and the upper bits[31:30] encode a machine type. The machine
> +types that might be available are:
> +
> + ========================= ======= ========================================
> + Type [31:30] Description
> + ========================= ======= ========================================
> + KVM_VM_TYPE_ARM_NORMAL 0b00 A standard VM
> + KVM_VM_TYPE_ARM_REALM 0b01 A "realm" VM using the Arm Confidential
> + Compute extensions, the VM's memory is
> + protected from the host.
> + KVM_VM_TYPE_ARM_PROTECTED 0b10 A "protected" VM using pKVM to
> + isolate the VM from the host.
> + Reserved 0b11 Reserved for future use
> + ========================= ======= ========================================
> +
> +The physical address size for a VM (IPA Size limit) is limited to 40bits
> +by default. The limit can be configured if the host supports the
> extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
> KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
> identifier, where IPA_Bits is the maximum width of any physical
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 6f39831dcf5d..9881fd6c511c 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -249,6 +249,17 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> mutex_unlock(&kvm->lock);
> #endif
>
> + if ((type & KVM_VM_TYPE_ARM_PROTECTED) &&
> + (type & KVM_VM_TYPE_ARM_REALM))
> + return -EINVAL;
> +
> + if (type & KVM_VM_TYPE_ARM_REALM) {
> + if (!static_branch_unlikely(&kvm_rmi_is_available))
> + return -EINVAL;
> + kvm_set_realm_state(kvm, REALM_STATE_NONE);
> + kvm->arch.is_realm = true;
> + }
> +
Shall we use kvm_arm_rmi_supported() here? In that way, the check is consistent
to what has been done for KVM_CAP_ARM_RMI. You know that a misbehaving VMM can
issue KVM_CREATE_VM to create a realm VM without checking if KVM_CAP_ARM_RMI
is supported by the host.
if (type & KVM_VM_TYPE_ARM_REALM) {
if (!kvm_arm_rmi_supported())
return -EINVAL;
kvm_set_realm_state(kvm, REALM_STATE_NONE);
WRITE_ONCE(kvm->arch.is_realm, true);
}
> kvm_init_nested(kvm);
>
> ret = kvm_share_hyp(kvm, kvm + 1);
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 0231ff174a50..adee3936d6ae 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -700,14 +700,19 @@ struct kvm_enable_cap {
> * address size for the VM. Bits[7-0] are reserved for the guest
> * PA size shift (i.e, log2(PA_Size)). For backward compatibility,
> * value 0 implies the default IPA size, 40bits.
> + *
> + * Bits[30-31] are reserved for the VM type
> */
> #define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
> #define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
> ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
>
> +#define KVM_VM_TYPE_ARM_NORMAL 0
> +#define KVM_VM_TYPE_ARM_REALM (1UL << 30)
> #define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31)
> #define KVM_VM_TYPE_ARM_MASK (KVM_VM_TYPE_ARM_IPA_SIZE_MASK | \
> - KVM_VM_TYPE_ARM_PROTECTED)
> + KVM_VM_TYPE_ARM_PROTECTED | \
> + KVM_VM_TYPE_ARM_REALM)
>
> /*
> * ioctls for /dev/kvm fds:
Thanks,
Gavin
More information about the linux-arm-kernel
mailing list