Add Realm support to QEMU-VMM
Subsystems (2)
v4 cover Add Realm support to QEMU-VMM
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \
-M confidential-guest-support=rme0,memory-backend=ram0 \
-object rme-guest,id=rme0,convert-in-place=on \
-object memory-backend-guest-memfd,id=ram0,size=1G,share=on \
-cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..
It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES and KVM_CAP_ARM_RMI have been modified to follow QEMU master.
Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
Mathieu
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructions
RFC v3: https://lore.kernel.org/kvm/[email protected]/
RFC v2: https://lore.kernel.org/kvm/[email protected]/
RFC v1: https://lists.gnu.org/archive/html/qemu-devel/2026-07/msg02307.html
Jean-Philippe Brucker (23):
linux-headers: Add RME related definitions
target/arm/kvm: Return immediately on error in kvm_arch_init() target/arm: Add confidential guest support
target/arm/kvm: Split kvm_arch_get/put_registers target/arm/kvm-rme: Initialize vCPU
target/arm/kvm: Create scratch Realm VM when requested target/arm/kvm: Use kvm_vm_check_extension() where necessary hw/core/loader: Add a ROM loader notifier target/arm/kvm-rme: Keep track of images loaded in Realm memory target/arm/kvm-rme: Populate Realm with runtime images target/arm/cpu: Set number of breakpoints and watchpoints in KVM target/arm/cpu: Set number of PMU counters in KVM target/arm/cpu: Don't read Realm registers
hw/arm/virt: Set proper conduit method for Realms hw/arm/virt: Embed Realm VM type with IPA address space hw/arm/virt: Reserve one bit of guest physical address for RME hw/arm/virt: Disable DTB randomness for confidential VMs hw/arm/virt: Move virt_flash_create() to machvirt_init() hw/arm/virt: Use RAM instead of flash for confidential guest firmware target/arm/kvm-rme: Add DMA remapping for the shared memory region docs/interop/firmware.json: Add arm-rme firmware feature hw/arm/boot: Load DTB as is for confidential VMs hw/arm/boot: Skip bootloader for confidential guests
Mathieu Poirier (1):
target/arm/kvm-rme: Add mechanic to initialize realms
docs/interop/firmware.json | 5 +- docs/system/arm/virt.rst | 9 +- docs/system/confidential-guest-support.rst | 1 + hw/arm/boot.c | 70 ++++- hw/arm/virt.c | 142 +++++++-- hw/core/loader.c | 15 + include/hw/arm/boot.h | 9 + include/hw/arm/virt.h | 2 +- include/hw/core/loader.h | 17 ++ linux-headers/asm-arm64/kvm.h | 9 + linux-headers/linux/kvm.h | 10 +- qapi/qom.json | 13 + target/arm/arm-qmp-cmds.c | 1 + target/arm/cpu.c | 5 + target/arm/cpu.h | 10 + target/arm/cpu64.c | 122 ++++++++ target/arm/kvm-rme.c | 336 +++++++++++++++++++++ target/arm/kvm-stub.c | 9 + target/arm/kvm.c | 202 ++++++++++++- target/arm/kvm_arm.h | 20 ++ target/arm/meson.build | 5 +- 21 files changed, 962 insertions(+), 50 deletions(-) create mode 100644 target/arm/kvm-rme.c
Signature · 1 line
2.43.0
RFC v4 1/24 linux-headers: Add RME related definitions
From: Jean-Philippe Brucker <[email protected]>
This is a temporary patch intended for testing purposes only. It provides definitions related to supporting Realms by the QEMU-VMM.
--- linux-headers/asm-arm64/kvm.h | 9 +++++++++ linux-headers/linux/kvm.h | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)
linux-headers/asm-arm64/kvm.h +9 -0
@@ -208,6 +208,15 @@ struct kvm_arm_counter_offset {__u64 reserved; }; +#define KVM_ARM_RMI_POPULATE_FLAGS_MEASURE (1 << 0) +struct kvm_arm_rmi_populate { +__u64 base; +__u64 size; +__u64 source_uaddr; +__u32 flags; +__u32 reserved; +}; +#define KVM_ARM_TAGS_TO_GUEST 0#define KVM_ARM_TAGS_FROM_GUEST 1
linux-headers/linux/kvm.h +9 -1
@@ -689,14 +689,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:
@@ -719,6 +724,8 @@ struct kvm_enable_cap {#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) +#define KVM_ARM_RMI_POPULATE _IOWR(KVMIO, 0xd7, struct kvm_arm_rmi_populate) +/* * Extension capability list. */
@@ -988,6 +995,7 @@ struct kvm_enable_cap {#define KVM_CAP_S390_HPAGE_2G 249#define KVM_CAP_PPC_COMPAT_CAPS 250#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 251 +#define KVM_CAP_ARM_RMI 252struct kvm_irq_routing_irqchip {__u32 irqchip;
Signature · 1 line
2.43.0
Re: [RFC v4 01/24] linux-headers: Add RME related definitions
Hi Mathieu,
Quoted 67 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
This is a temporary patch intended for testing purposes only. It provides definitions related to supporting Realms by the QEMU-VMM.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- linux-headers/asm-arm64/kvm.h | 9 +++++++++ linux-headers/linux/kvm.h | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)linux-headers/asm-arm64/kvm.h +9
-0@@ -208,6 +208,15 @@ struct kvm_arm_counter_offset {__u64 reserved; }; +#define KVM_ARM_RMI_POPULATE_FLAGS_MEASURE (1 << 0) +struct kvm_arm_rmi_populate { +__u64 base; +__u64 size; +__u64 source_uaddr; +__u32 flags; +__u32 reserved; +}; +#define KVM_ARM_TAGS_TO_GUEST 0#define KVM_ARM_TAGS_FROM_GUEST 1linux-headers/linux/kvm.h +8
-1@@ -689,14 +689,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: @@ -719,6 +724,8 @@ struct kvm_enable_cap {#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) +#define KVM_ARM_RMI_POPULATE _IOWR(KVMIO, 0xd7, struct kvm_arm_rmi_populate) +/* * Extension capability list. */
linux-headers/linux/kvm.h struct kvm_enable_cap { · line 999
Quoted 5 lines
linux-headers/linux/kvm.h +1
-0@@ -988,6 +995,7 @@ struct kvm_enable_cap {#define KVM_CAP_S390_HPAGE_2G 249#define KVM_CAP_PPC_COMPAT_CAPS 250#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 251 +#define KVM_CAP_ARM_RMI 252
Both KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES and KVM_CAP_ARM_RMI aren't consistent to the definitions in Steven Price's (v16) host series [1]. They need corrections as below. Otherwise, realm VM can't be started and the following errors are raised by qemu.
[1] https://lore.kernel.org/kvm/[email protected]/
root@host:~# qemu-system-aarch64 -enable-kvm \
-object rme-guest,id=rme0,convert-in-place=on \
-machine virt,gic-version=3,confidential-guest-support=rme0 \
-m 2G -cpu host \
-smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \
-object memory-backend-guest-memfd,id=mem0,size=2G,share=on \
-numa node,nodeid=0,cpus=0-3,memdev=mem0 \
-serial mon:stdio -monitor none -nographic -nodefaults \
-kernel /mnt/linux/arch/arm64/boot/Image \
-initrd /mnt/buildroot/output/images/rootfs.cpio.xz \
-append earlycon=pl011,mmio,0x10009000000
:
qemu-system-aarch64: VM doesn't support Realms
qemu-system-aarch64: failed to initialize kvm: No such device-#define KVM_CAP_PPC_COMPAT_CAPS 250 -#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 251 -#define KVM_CAP_ARM_RMI 252
+#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 250 +#define KVM_CAP_ARM_RMI 251
linux-headers/linux/kvm.h struct kvm_enable_cap { · line 1001
Quoted 2 lines
linux-headers/linux/kvm.h +0
-0struct kvm_irq_routing_irqchip {__u32 irqchip;
Thanks,
Gavin
Re: [RFC v4 01/24] linux-headers: Add RME related definitions
Quoted 66 lines · Gavin Shan
Hi Mathieu,
Quoted 63 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
This is a temporary patch intended for testing purposes only. It provides definitions related to supporting Realms by the QEMU-VMM.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- linux-headers/asm-arm64/kvm.h | 9 +++++++++ linux-headers/linux/kvm.h | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)linux-headers/asm-arm64/kvm.h +9
-0@@ -208,6 +208,15 @@ struct kvm_arm_counter_offset {__u64 reserved; }; +#define KVM_ARM_RMI_POPULATE_FLAGS_MEASURE (1 << 0) +struct kvm_arm_rmi_populate { +__u64 base; +__u64 size; +__u64 source_uaddr; +__u32 flags; +__u32 reserved; +}; +#define KVM_ARM_TAGS_TO_GUEST 0#define KVM_ARM_TAGS_FROM_GUEST 1linux-headers/linux/kvm.h +8
-1@@ -689,14 +689,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: @@ -719,6 +724,8 @@ struct kvm_enable_cap {#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) +#define KVM_ARM_RMI_POPULATE _IOWR(KVMIO, 0xd7, struct kvm_arm_rmi_populate) +/* * Extension capability list. */ @@ -988,6 +995,7 @@ struct kvm_enable_cap {#define KVM_CAP_S390_HPAGE_2G 249
Quoted 8 lines
linux-headers/linux/kvm.h struct kvm_enable_cap { · line 998
Quoted 3 lines
linux-headers/linux/kvm.h +1
-0#define KVM_CAP_PPC_COMPAT_CAPS 250#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 251 +#define KVM_CAP_ARM_RMI 252Both
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIaren't consistent to the definitions in Steven Price's (v16) host series [1]. They need corrections as below. Otherwise, realm VM can't be started and the following errors are raised by qemu.
The changelog is clear - numbers for those defines have been bumped up to keep pace with the definitions in the QEMU master branch. RFC v3 had defines that were similar to Steven's v16 and as such used an older QEMU baseline, but Markus said it wasn't appropriate.
Quoted 31 lines
[1] https://lore.kernel.org/kvm/[email protected]/
root@host:~# qemu-system-aarch64 -enable-kvm \(quoted diff) +0
-10-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 :qemu-system-aarch64: VM doesn't support Realms
qemu-system-aarch64: failed to initialize kvm: No such device(quoted diff) +2
-3-#define KVM_CAP_PPC_COMPAT_CAPS 250 -#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 251 -#define KVM_CAP_ARM_RMI 252 +#define KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTES 250 +#define KVM_CAP_ARM_RMI 251linux-headers/linux/kvm.h struct kvm_enable_cap { · line 1001
Quoted 3 lines
linux-headers/linux/kvm.h +0
-0struct kvm_irq_routing_irqchip {__u32 irqchip;Thanks,
Gavin
RFC v4 2/24 target/arm/kvm: Return immediately on error in kvm_arch_init()
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Returning an error to kvm_init() is fatal anyway, no need to continue the initialization.
Leave the ret variable in the function scope because it will be reused when adding RME support.
--- target/arm/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
target/arm/kvm.c +5 -4
@@ -596,7 +596,7 @@ int kvm_arch_get_default_type(MachineState *ms)int kvm_arch_init (MachineState *ms,KVMState *s) { -int ret =0 ; +int ret;/* For ARM interrupt delivery is always asynchronous, * whether we are using an in-kernel VGIC or not. */
@@ -618,7 +618,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) {error_report ("Using more than 256 vcpus requires a host kernel " "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2" ); - ret = -EINVAL ; +return -EINVAL ; }if (kvm_check_extension (s,KVM_CAP_ARM_NISV_TO_USER )) {
@@ -640,13 +640,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s)warn_report ("Eager Page Split support not available" ); }else if (!(s->kvm_eager_split_size & sizes)) {error_report ("Eager Page Split requested chunk size not valid" ); - ret = -EINVAL ; +return -EINVAL ; }else { ret =kvm_vm_enable_cap (s,KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE ,0 , s->kvm_eager_split_size);if (ret <0 ) {error_report ("Enabling of Eager Page Split failed: %s" ,strerror (-ret)); +return ret; } } }
@@ -659,7 +660,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) hw_breakpoints =g_array_sized_new (true, true,sizeof (HWBreakpoint), max_hw_bps); -return ret; +return 0 ; }unsigned long kvm_arch_vcpu_id (CPUState *cpu)
Signature · 1 line
2.43.0
Re: [RFC v4 02/24] target/arm/kvm: Return immediately on error in kvm_arch_init()
Quoted 29 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Returning an error to
kvm_init()is fatal anyway, no need to continue the initialization.Leave the
retvariable in the function scope because it will be reused when adding RME support.Signed-off-by Jean-Philippe Brucker <[email protected]>Reviewed-by Philippe Mathieu-Daudé <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)target/arm/kvm.c +1
-1@@ -596,7 +596,7 @@ int kvm_arch_get_default_type(MachineState *ms)int kvm_arch_init (MachineState *ms,KVMState *s) { -int ret =0 ; +int ret;/* For ARM interrupt delivery is always asynchronous, * whether we are using an in-kernel VGIC or not. */
target/arm/kvm.c int kvm_arch_init(MachineState *ms, KVMState *s) · line 624
Quoted 8 lines
target/arm/kvm.c +1
-1@@ -618,7 +618,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) {error_report ("Using more than 256 vcpus requires a host kernel " "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2" ); - ret = -EINVAL ; +return -EINVAL ; }if (kvm_check_extension (s,KVM_CAP_ARM_NISV_TO_USER )) {
There's a error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap") under here as well that doesn't have a return -EINVAL after this patch. Is that intentional?
Re: [RFC v4 02/24] target/arm/kvm: Return immediately on error in kvm_arch_init()
Quoted 37 lines · Michael Roth
Quoted 36 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Returning an error to
kvm_init()is fatal anyway, no need to continue the initialization.Leave the
retvariable in the function scope because it will be reused when adding RME support.Signed-off-by Jean-Philippe Brucker <[email protected]>Reviewed-by Philippe Mathieu-Daudé <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)target/arm/kvm.c +2
-2@@ -596,7 +596,7 @@ int kvm_arch_get_default_type(MachineState *ms)int kvm_arch_init (MachineState *ms,KVMState *s) { -int ret =0 ; +int ret;/* For ARM interrupt delivery is always asynchronous, * whether we are using an in-kernel VGIC or not. */ @@ -618,7 +618,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) {error_report ("Using more than 256 vcpus requires a host kernel " "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2" ); - ret = -EINVAL ; +return -EINVAL ; }
Quoted 5 lines
target/arm/kvm.c int kvm_arch_init(MachineState *ms, KVMState *s) · line 624
Quoted 1 line
target/arm/kvm.c +0
-0if (kvm_check_extension (s,KVM_CAP_ARM_NISV_TO_USER )) {There's a
error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap")under here as well that doesn't have a return-EINVALafter this patch. Is that intentional?
This patch did not touch the clause that checks KVM_CAP_ARM_NISV_TO_USER. As far as I can tell, it is mainline code.
RFC v4 3/24 target/arm: Add confidential guest support
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>
This is only the skeleton. Support will be added in following patches.
--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.c
docs/system/confidential-guest-support.rst +1 -0
@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.
qapi/qom.json +13 -0
@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties', + 'data': {} } + ## # @ObjectType: #
@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',
@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',
target/arm/kvm-rme.c new file +42 -0
42 lines not on this page · raw message
target/arm/meson.build +4 -1
@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))
Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 13 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>
[...]
Quoted 5 lines
qapi/qom.json +0
-0
qapi/qom.json line 1296
Quoted 9 lines
qapi/qom.json +6
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1
11.2 now.
Quoted 17 lines
qapi/qom.json +6
-0+## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties', + 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',
qapi/qom.json line 1445
Quoted 7 lines
qapi/qom.json +1
-0@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',
With the Since: fixed
[...]
Re: [RFC v4 03/24] target/arm: Add confidential guest support
In reply to Mathieu PoirierQuoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }
qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',
Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the instance_init function for your rme-guest instance:
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;
rather than exposing it as a cmdline option.
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 57 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
Quoted 8 lines
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Thanks,
Lorenzo
Quoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:
Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with -m is sufficient?
Thanks,
Kohei
Quoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 71 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 9 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?
I'm almost done crafting a new revision that will be based on V20 of the KVM patchset. I will look into your request for the revision after this one.
Quoted 100 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
In reply to Kohei EnjuQuoted 71 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=on
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Thanks,
Mathieu
Quoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 76 lines · Mathieu Poirier
Quoted 75 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of
Quoted 6 lines
Quoted 4 lines
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Are you suggesting that on Arm, we completely get rid of
Nit: obviously on Arm rme-guest configs.
Quoted 1 line
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=on
If that's what we want to make a default, I guess we ought to override create_default_memdev for arm machines + rme-guest configs ?
Pros and cons ? I am not sure how well received is setting implicit defaults for specific machine configs and what that really buys us eventually.
Quoted 4 lines
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Yes please any feedback on this is welcome.
Thanks,
Lorenzo
Quoted 104 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 77 lines · Lorenzo Pieralisi
Quoted 76 lines · Mathieu Poirier
Quoted 75 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Are you suggesting that on Arm, we completely get rid of
Nit: obviously on Arm rme-guest configs.
Indeed.
Quoted 8 lines
Quoted 2 lines
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onIf that's what we want to make a default, I guess we ought to override
create_default_memdevfor arm machines + rme-guest configs ?Pros and cons ? I am not sure how well received is setting implicit defaults for specific machine configs and what that really buys us eventually.
I agree, this entails a fair amount of changes for cosmetic gains only.
Quoted 115 lines
Quoted 5 lines
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Yes please any feedback on this is welcome.
Thanks,
LorenzoQuoted 104 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 92 lines · Mathieu Poirier
Quoted 77 lines · Lorenzo Pieralisi
Quoted 76 lines · Mathieu Poirier
Quoted 75 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent ofQuoted 8 lines
Quoted 6 lines
Quoted 4 lines
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Are you suggesting that on Arm, we completely get rid of
Nit: obviously on Arm rme-guest configs.
Indeed.
Quoted 3 lines
Quoted 2 lines
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=on
Quoted 7 lines
Quoted 5 lines
If that's what we want to make a default, I guess we ought to override
create_default_memdevfor arm machines + rme-guest configs ?Pros and cons ? I am not sure how well received is setting implicit defaults for specific machine configs and what that really buys us eventually.
I agree, this entails a fair amount of changes for cosmetic gains only.
I think it will also add some uneccessary confusion. For instance, based on Paolo's feedback[1], we will likely not expose any sort of option to switch between in-place/out-of-place conversion for SNP/TDX, but instead just use whatever mode the KVM module was actually configured to use.
For in-place conversion, it actually doesn't seem too bad to hook into create_default_memdev to have it default to memory-backend-memfd. However, currently, it used backend-file/backend-ram depending on other options, and those options are applicable to out-of-place conversion as well where e.g. maybe the user wants to use file-backed hugetlb memory for their shared memory. So we wouldn't want to change the behavior for out-of-place.
But then, for in-place, if we default to a different backend then stuff like mem-path=... parameters for out-of-place invocations will then become silently ignored, or we will need to generate an error for those, which works against the idea of having a common cmdline that "just works" for in-place/out-of-place.
If we (users, management/libvirt, etc.) consolidate around specifying the memfd backend for confidential VMs, then we can have a "default" that is more consistent between in-place vs. out-of-place, which i think is more beneficial than trying to consolidate around a syntacticly simpler cmdline that might not behave as expected when switching between older/newer kernels which may or may not have in-place support.
So, a longwinded "I agree" from me as well.
Thanks,
Mike
Quoted 116 lines
Quoted 116 lines
Quoted 6 lines
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Yes please any feedback on this is welcome.
Thanks,
LorenzoQuoted 104 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 96 lines · Michael Roth
Quoted 95 lines · Mathieu Poirier
Quoted 77 lines · Lorenzo Pieralisi
Quoted 76 lines · Mathieu Poirier
Quoted 75 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent ofQuoted 8 lines
Quoted 6 lines
Quoted 4 lines
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Are you suggesting that on Arm, we completely get rid of
Nit: obviously on Arm rme-guest configs.
Indeed.
Quoted 6 lines
Quoted 2 lines
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onIf that's what we want to make a default, I guess we ought to override
create_default_memdevfor arm machines + rme-guest configs ?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Pros and cons ? I am not sure how well received is setting implicit defaults for specific machine configs and what that really buys us eventually.
I agree, this entails a fair amount of changes for cosmetic gains only.
I think it will also add some uneccessary confusion. For instance, based on Paolo's feedback[1], we will likely not expose any sort of option to
I think that [1] is:
https://lore.kernel.org/kvm/[email protected]
for completeness.
Quoted 6 lines
switch between in-place/out-of-place conversion for SNP/TDX, but instead just use whatever mode the KVM module was actually configured to use.
For in-place conversion, it actually doesn't seem too bad to hook into
create_default_memdevto have it default to memory-backend-memfd. However, currently, it used backend-file/backend-ram depending on other
"it used" - can I ask what "it" refers to please ?
Quoted 4 lines
options, and those options are applicable to out-of-place conversion as well where e.g. maybe the user wants to use file-backed hugetlb memory for their shared memory. So we wouldn't want to change the behavior for out-of-place.
So, here you are saying that basically a sensible default for out-of-place might not work for convert-in-place and therefore it does not make much sense to have a default that does/doesn't work depending on how KVM is configured.
Quoted 5 lines
But then, for in-place, if we default to a different backend then stuff like mem-path=... parameters for out-of-place invocations will then become silently ignored, or we will need to generate an error for those, which works against the idea of having a common cmdline that "just works" for in-place/out-of-place.
Yes that makes sense.
Quoted 6 lines
If we (users, management/libvirt, etc.) consolidate around specifying the memfd backend for confidential VMs, then we can have a "default" that is more consistent between in-place vs. out-of-place, which i think is more beneficial than trying to consolidate around a syntacticly simpler cmdline that might not behave as expected when switching between older/newer kernels which may or may not have in-place support.
Can you elaborate on this Michael please ? In particular in relation to a more consistent "default" for in-place/out-of-place, are you referring to defining a -object memfd option that works for both in-place and out-of-place ? Isn't that the case already with your latest v3 (and the VMM detecting the KVM underlying config ie in-place vs out-of-place) ?
Quoted 5 lines
So, a longwinded "I agree" from me as well.
Thanks,
Mike
Thanks,
Lorenzo
Quoted 116 lines
Quoted 116 lines
Quoted 116 lines
Quoted 6 lines
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Yes please any feedback on this is welcome.
Thanks,
LorenzoQuoted 104 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 102 lines · Lorenzo Pieralisi
Quoted 101 lines · Michael Roth
Quoted 99 lines · Mathieu Poirier
Quoted 77 lines · Lorenzo Pieralisi
Quoted 76 lines · Mathieu Poirier
Quoted 75 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent ofQuoted 8 lines
Quoted 6 lines
Quoted 4 lines
-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Are you suggesting that on Arm, we completely get rid of
Nit: obviously on Arm rme-guest configs.
Indeed.
Quoted 8 lines
Quoted 2 lines
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onIf that's what we want to make a default, I guess we ought to override
create_default_memdevfor arm machines + rme-guest configs ?Pros and cons ? I am not sure how well received is setting implicit defaults for specific machine configs and what that really buys us eventually.
I agree, this entails a fair amount of changes for cosmetic gains only.
Quoted 8 lines
Quoted 2 lines
I think it will also add some uneccessary confusion. For instance, based on Paolo's feedback[1], we will likely not expose any sort of option to
I think that [1] is:
https://lore.kernel.org/kvm/[email protected]
for completeness.
Yes, sorry, I should know better by now that adding citations before adding the links is a bad idea.
Quoted 9 lines
Quoted 7 lines
switch between in-place/out-of-place conversion for SNP/TDX, but instead just use whatever mode the KVM module was actually configured to use.
For in-place conversion, it actually doesn't seem too bad to hook into
create_default_memdevto have it default to memory-backend-memfd. However, currently, it used backend-file/backend-ram depending on other"it used" - can I ask what "it" refers to please ?
"it used" -> "QEMU uses" is what I meant.
Quoted 26 lines
Quoted 5 lines
options, and those options are applicable to out-of-place conversion as well where e.g. maybe the user wants to use file-backed hugetlb memory for their shared memory. So we wouldn't want to change the behavior for out-of-place.
So, here you are saying that basically a sensible default for out-of-place might not work for convert-in-place and therefore it does not make much sense to have a default that does/doesn't work depending on how KVM is configured.
Quoted 5 lines
But then, for in-place, if we default to a different backend then stuff like mem-path=... parameters for out-of-place invocations will then become silently ignored, or we will need to generate an error for those, which works against the idea of having a common cmdline that "just works" for in-place/out-of-place.
Yes that makes sense.
Quoted 6 lines
If we (users, management/libvirt, etc.) consolidate around specifying the memfd backend for confidential VMs, then we can have a "default" that is more consistent between in-place vs. out-of-place, which i think is more beneficial than trying to consolidate around a syntacticly simpler cmdline that might not behave as expected when switching between older/newer kernels which may or may not have in-place support.
Quoted 5 lines
Can you elaborate on this Michael please ? In particular in relation to a more consistent "default" for in-place/out-of-place, are you referring to defining a -object memfd option that works for both in-place and out-of-place ? Isn't that the case already with your latest v3 (and the VMM detecting the KVM underlying config ie in-place vs out-of-place) ?
To clarify, what I mean is that if we all CoCo platforms use a similar command-line like:
qemu-system-<arch> -object memory-backend-memfd,...
then that would be consistent not only across all CoCo platforms (for currently implementations anyway...) that support only in-place conversion, but it would also be consistent across CoCo platforms that support both in-place/out-of-place (SNP/TDX). There seems to be a desire for the latter based on Paolo's comments (thanks for fixing the references).
If however we introduce some syntactic sugar to have it handled automatically by -m / create_default_memdev(), then any users who previously ran SNP/TDX for out-of-place conversion with something like:
qemu-system-x86_64 -m <size> -machine ...,mem-path=/path/to/hugetlb
would break/misbehave if we enabled in-place conversion. And that's okay, but it makes clear that using -m comes with a number of restrictions in the case of in-place-conversion (e.g. mem-path not supported), that aren't restrictions for out-of-place-conversion, and that can cause some confusion if we don't document it appropriately.
I don't have any strong objection to that, but it's just trickier to document/explain, whereas if we all just generally agree to use:
qemu-system-<arch> -object memory-backend-memfd,...
a lot of this ambiguity goes away. So I prefer specifying the backend explicitly, especially since guest-memfd is a well-understood commonality for CoCo VMs and we can concentrate our documentation and how we expose that to management/libvirt through this same backend.
That said, there's no reason we can't also have -m "Do the right thing" for in-place conversion, I just don't think we should lean on that too heavily in our documentation/management tooling, and keep it as more of a 'shortcut' for non-production use-cases if we decide it's worth adding.
Thanks,
Mike
Quoted 126 lines
Quoted 6 lines
So, a longwinded "I agree" from me as well.
Thanks,
Mike
Thanks,
LorenzoQuoted 116 lines
Quoted 116 lines
Quoted 116 lines
Quoted 6 lines
or simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
Yes please any feedback on this is welcome.
Thanks,
LorenzoQuoted 104 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
In reply to Mathieu PoirierQuoted 81 lines · Mathieu Poirier
Quoted 71 lines · Kohei Enju
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Michael Roth
Quoted 39 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-)create mode 100644
target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool', '*close-action': 'MonitorQMPCloseAction' } }qapi/qom.json line 1299
Quoted 10 lines
qapi/qom.json +9
-0+## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?
Quoted 9 lines
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onor simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
I don't think that's what Kohei meant. He actually suggested the memory backend shall be pinned to memory-backend-guest-memfd and its in-place conversion shall be enabled when the memory backend isn't explicitly specified by users through "-object memory-backend-xxxx". For this inexplicit case, where the memory backend is determined by '-mem-path', the memory backend is either TYPE_MEMORY_BACKEND_FILE or TYPE_MEMORY_BACKEND_RAM. Please refer to create_default_memdev().
I think Kohei's suggestion makes sense. Besides, I think '-mem-path' should be disallowed for CCA Realms as TYPE_MEMORY_BACKEND_FILE isn't what we want.
Thanks,
Gavin
Quoted 105 lines
Thanks,
MathieuQuoted 101 lines
Thanks,
KoheiQuoted 97 lines
Thanks,
LorenzoQuoted 93 lines
Thanks,
Mike
Quoted 89 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 97 lines · Gavin Shan
Quoted 79 lines · Mathieu Poirier
Quoted 69 lines · Kohei Enju
Quoted 60 lines · Lorenzo Pieralisi
Quoted 59 lines · Michael Roth
Quoted 37 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-)create mode 100644
target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool',qapi/qom.json line 1298
Quoted 10 lines
qapi/qom.json +9
-0'*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Quoted 9 lines
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onor simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
I don't think that's what Kohei meant. He actually suggested the memory backend shall be pinned to memory-backend-guest-memfd and its in-place conversion shall be enabled when the memory backend isn't explicitly specified by users through "-object memory-backend-xxxx". For this inexplicit case, where the memory backend is determined by '-mem-path', the memory backend is either
TYPE_MEMORY_BACKEND_FILEorTYPE_MEMORY_BACKEND_RAM. Please refer tocreate_default_memdev().
Quoted 2 lines
I think Kohei's suggestion makes sense. Besides, I think '-mem-path' should be disallowed for CCA Realms as
TYPE_MEMORY_BACKEND_FILEisn't what we want.
Kohei, what were you suggesting then please ? I think TYPE_MEMORY_BACKEND_FILE would not pass the checks required by Michael's v3 [0] on CCA - I will test this and report back but the only backend allowed, rightly, is memfd,share=on, so it _is_ disallowed.
Lorenzo
[0] https://lore.kernel.org/kvm/[email protected]/
Quoted 108 lines
Thanks,
GavinQuoted 104 lines
Thanks,
MathieuQuoted 100 lines
Thanks,
KoheiQuoted 96 lines
Thanks,
LorenzoQuoted 92 lines
Thanks,
Mike
Quoted 88 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 98 lines · Lorenzo Pieralisi
Quoted 97 lines · Gavin Shan
Quoted 79 lines · Mathieu Poirier
Quoted 69 lines · Kohei Enju
Quoted 60 lines · Lorenzo Pieralisi
Quoted 59 lines · Michael Roth
Quoted 37 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-)create mode 100644
target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool',qapi/qom.json line 1298
Quoted 10 lines
qapi/qom.json +9
-0'*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Quoted 9 lines
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onor simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
I don't think that's what Kohei meant. He actually suggested the memory backend shall be pinned to memory-backend-guest-memfd and its in-place conversion shall be enabled when the memory backend isn't explicitly specified by users through "-object memory-backend-xxxx". For this inexplicit case, where the memory backend is determined by '-mem-path', the memory backend is either
TYPE_MEMORY_BACKEND_FILEorTYPE_MEMORY_BACKEND_RAM. Please refer tocreate_default_memdev().
Quoted 7 lines
Quoted 2 lines
I think Kohei's suggestion makes sense. Besides, I think '-mem-path' should be disallowed for CCA Realms as
TYPE_MEMORY_BACKEND_FILEisn't what we want.Kohei, what were you suggesting then please ? I think
TYPE_MEMORY_BACKEND_FILEwould not pass the checks required by Michael's v3 [0] on CCA - I will test this and report back but the only backend allowed, rightly, is memfd,share=on, so it _is_ disallowed.
Sorry for the late response.
To clarify, I meant the latter: when rme-guest is selected and the user has not explicitly provided a memory backend, QEMU could automatically create the default RAM as a shared guest-memfd backend.
In other words, rather than only rejecting the default file/RAM backend, the Realm configuration could select the equivalent of
-object memory-backend-guest-memfd,id=<default-ram-id>,size=<RAMSIZE>,share=on
by default. Explicitly specified memory backends would still need to be validated against the Realm requirements.
My intention was that, if in-place conversion is the baseline for CCA Realms, -m <size> should be sufficient for the common Realm case, while preserving an explicit memory-backend option for users who need to control it.
That said, I do not have a strong preference for deciding the default -m behavior at this stage. If it is premature to make that decision before the memory-backend and conversion interfaces have settled, I am happy to keep the explicit guest-memfd backend requirement for now and revisit the default behavior later.
Thanks,
Kohei
Quoted 113 lines
Lorenzo
[0] https://lore.kernel.org/kvm/[email protected]/
Quoted 108 lines
Thanks,
GavinQuoted 104 lines
Thanks,
MathieuQuoted 100 lines
Thanks,
KoheiQuoted 96 lines
Thanks,
LorenzoQuoted 92 lines
Thanks,
Mike
Quoted 88 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 118 lines · Kohei Enju
Quoted 98 lines · Lorenzo Pieralisi
Quoted 97 lines · Gavin Shan
Quoted 79 lines · Mathieu Poirier
Quoted 69 lines · Kohei Enju
Quoted 60 lines · Lorenzo Pieralisi
Quoted 59 lines · Michael Roth
Quoted 37 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-)create mode 100644
target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool',qapi/qom.json line 1298
Quoted 10 lines
qapi/qom.json +9
-0'*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Quoted 9 lines
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onor simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
I don't think that's what Kohei meant. He actually suggested the memory backend shall be pinned to memory-backend-guest-memfd and its in-place conversion shall be enabled when the memory backend isn't explicitly specified by users through "-object memory-backend-xxxx". For this inexplicit case, where the memory backend is determined by '-mem-path', the memory backend is either
TYPE_MEMORY_BACKEND_FILEorTYPE_MEMORY_BACKEND_RAM. Please refer tocreate_default_memdev().Quoted 7 lines
Quoted 2 lines
I think Kohei's suggestion makes sense. Besides, I think '-mem-path' should be disallowed for CCA Realms as
TYPE_MEMORY_BACKEND_FILEisn't what we want.Kohei, what were you suggesting then please ? I think
TYPE_MEMORY_BACKEND_FILEwould not pass the checks required by Michael's v3 [0] on CCA - I will test this and report back but the only backend allowed, rightly, is memfd,share=on, so it _is_ disallowed.Sorry for the late response.
To clarify, I meant the latter: when rme-guest is selected and the user has not explicitly provided a memory backend, QEMU could automatically create the default RAM as a shared guest-memfd backend.
In other words, rather than only rejecting the default file/RAM backend, the Realm configuration could select the equivalent of
-object memory-backend-guest-memfd,id=<default-ram-id>,size=<RAMSIZE>,share=on
Quoted 7 lines
by default. Explicitly specified memory backends would still need to be validated against the Realm requirements.
My intention was that, if in-place conversion is the baseline for CCA Realms,
-m <size>should be sufficient for the common Realm case, while preserving an explicit memory-backend option for users who need to control it.
Many thanks for the clarification, it is very helpful. I will look into implementing something along those lines for V6 and we can reconsider how to move forward at that time.
Thanks,
Mathieu
Quoted 123 lines
That said, I do not have a strong preference for deciding the default
-mbehavior at this stage. If it is premature to make that decision before the memory-backend and conversion interfaces have settled, I am happy to keep the explicit guest-memfd backend requirement for now and revisit the default behavior later.Thanks,
KoheiQuoted 113 lines
Lorenzo
[0] https://lore.kernel.org/kvm/[email protected]/
Quoted 108 lines
Thanks,
GavinQuoted 104 lines
Thanks,
MathieuQuoted 100 lines
Thanks,
KoheiQuoted 96 lines
Thanks,
LorenzoQuoted 92 lines
Thanks,
Mike
Quoted 88 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
Re: [RFC v4 03/24] target/arm: Add confidential guest support
Quoted 122 lines · Mathieu Poirier
Quoted 121 lines · Kohei Enju
Quoted 98 lines · Lorenzo Pieralisi
Quoted 97 lines · Gavin Shan
Quoted 79 lines · Mathieu Poirier
Quoted 69 lines · Kohei Enju
Quoted 60 lines · Lorenzo Pieralisi
Quoted 59 lines · Michael Roth
Quoted 37 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line:
-M virt,confidential-guest-support=<id>
-object rme-guest,id=<id>This is only the skeleton. Support will be added in following patches.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- docs/system/confidential-guest-support.rst | 1 + qapi/qom.json | 13 +++++++ target/arm/kvm-rme.c | 42 ++++++++++++++++++++++ target/arm/meson.build | 5 ++- 4 files changed, 60 insertions(+), 1 deletion(-)create mode 100644
target/arm/kvm-rme.cdocs/system/confidential-guest-support.rst +1
-0@@ -42,5 +42,6 @@ Currently supported confidential guest mechanisms are: * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`) * s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`) * AWS Nitro Enclaves (see :doc:`nitro`) +* Arm Realm Management Extension (RME) Other mechanisms may be supported in future.qapi/qom.json +0
-0@@ -1288,6 +1288,17 @@ 'data': { '*pretty': 'bool',qapi/qom.json line 1298
Quoted 10 lines
qapi/qom.json +9
-0'*close-action': 'MonitorQMPCloseAction' } } +## +# @RmeGuestProperties: +# +# Properties for rme-guest objects. +# +# Since: 11.1 +## +{ 'struct': 'RmeGuestProperties', + 'base': 'ConfidentialGuestSupportProperties',Just FYI, based on input from Markus I'm planning to drop this ConfidentialGuestSupportProperties base type from my series since it's probably only SNP/TDX that need to be able to switch it on/off, whereas this series appears to use/require it from the start.
I'm not exactly sure what it will look like for v3 yet, but if you were based on v2 you'd instead probably just do the following in the
instance_initfunction for your rme-guest instance:Quoted 7 lines
Quoted 4 lines
cgs->allow_convert_in_place = true; cgs->convert_in_place = true;rather than exposing it as a cmdline option.
Yep, it won't be an option for CCA Realms anyway since that will be the baseline.
Quoted 8 lines
IIUC, in-place conversion requires RAM backed by a shared/mappable
guest_memfd. If in-place conversion is always enabled for CCA Realms, could QEMU also select the equivalent of-object memory-backend-guest-memfd,id=ram0,size=...,share=on
automatically for the default RAM, so that specifying the RAM size with
-mis sufficient?Quoted 9 lines
Are you suggesting that on Arm, we completely get rid of
-object memory-backend-guest-memfd,id=ram0,size=$(RAMSIZE),share=onor simply to get rid of "size=$(RAMSIZE)" in the above because it is redundant with "-m $(RAMSIZE)"?
Gavin and Michael, what is your take on that suggestion?
I don't think that's what Kohei meant. He actually suggested the memory backend shall be pinned to memory-backend-guest-memfd and its in-place conversion shall be enabled when the memory backend isn't explicitly specified by users through "-object memory-backend-xxxx". For this inexplicit case, where the memory backend is determined by '-mem-path', the memory backend is either
TYPE_MEMORY_BACKEND_FILEorTYPE_MEMORY_BACKEND_RAM. Please refer tocreate_default_memdev().Quoted 7 lines
Quoted 2 lines
I think Kohei's suggestion makes sense. Besides, I think '-mem-path' should be disallowed for CCA Realms as
TYPE_MEMORY_BACKEND_FILEisn't what we want.Kohei, what were you suggesting then please ? I think
TYPE_MEMORY_BACKEND_FILEwould not pass the checks required by Michael's v3 [0] on CCA - I will test this and report back but the only backend allowed, rightly, is memfd,share=on, so it _is_ disallowed.Sorry for the late response.
To clarify, I meant the latter: when rme-guest is selected and the user has not explicitly provided a memory backend, QEMU could automatically create the default RAM as a shared guest-memfd backend.
In other words, rather than only rejecting the default file/RAM backend, the Realm configuration could select the equivalent of
-object memory-backend-guest-memfd,id=<default-ram-id>,size=<RAMSIZE>,share=on
by default. Explicitly specified memory backends would still need to be validated against the Realm requirements.
Quoted 8 lines
Quoted 4 lines
My intention was that, if in-place conversion is the baseline for CCA Realms,
-m <size>should be sufficient for the common Realm case, while preserving an explicit memory-backend option for users who need to control it.Many thanks for the clarification, it is very helpful. I will look into implementing something along those lines for V6 and we can reconsider how to move forward at that time.
And then I read Michael's comment again, and again and again...
Quoted 11 lines
Thanks,
MathieuQuoted 7 lines
That said, I do not have a strong preference for deciding the default
-mbehavior at this stage. If it is premature to make that decision before the memory-backend and conversion interfaces have settled, I am happy to keep the explicit guest-memfd backend requirement for now and revisit the default behavior later.
For the time being I will hold back on moving forward with this request. Let's revisit at some point in the future.
Quoted 116 lines
Quoted 116 lines
Thanks,
KoheiQuoted 113 lines
Lorenzo
[0] https://lore.kernel.org/kvm/[email protected]/
Quoted 108 lines
Thanks,
GavinQuoted 104 lines
Thanks,
MathieuQuoted 100 lines
Thanks,
KoheiQuoted 96 lines
Thanks,
LorenzoQuoted 92 lines
Thanks,
Mike
Quoted 88 lines
qapi/qom.json +4
-0+ 'data': {} } + ## # @ObjectType: #@@ -1346,6 +1357,7 @@ { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, 'qtest', + 'rme-guest', 'rng-builtin', 'rng-egd', { 'name': 'rng-random',@@ -1427,6 +1439,7 @@ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', + 'rme-guest': 'RmeGuestProperties', 'rng-builtin': 'RngProperties', 'rng-egd': 'RngEgdProperties', 'rng-random': { 'type': 'RngRandomProperties',target/arm/kvm-rme.c new file +42
-0@@ -0,0 +1,42 @@ +/* +* QEMU Arm RME support +* +* SPDX-License-Identifier: GPL-2.0-or-later +* +* Copyright Linaro 2026 +*/ + +#include "qemu/osdep.h" + +#include "hw/core/boards.h" +#include "hw/core/cpu.h" +#include "kvm_arm.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "system/confidential-guest-support.h" +#include "system/kvm.h" +#include "system/runstate.h" + +#define TYPE_RME_GUEST "rme-guest" +OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) + +struct RmeGuest { +ConfidentialGuestSupport parent_obj; +}; + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES (RmeGuest, rme_guest,RME_GUEST , +CONFIDENTIAL_GUEST_SUPPORT , + { TYPE_USER_CREATABLE }, { }) + +static void rme_guest_class_init (ObjectClass *oc,const void *data) +{ +} + +static void rme_guest_init (Object *obj) +{ +} + +static void rme_guest_finalize (Object *obj) +{ +}target/arm/meson.build +4
-1@@ -31,7 +31,10 @@ arm_common_user_system_ss.add(when: 'TARGET_AARCH64', if_true: files( arm_common_system_ss.add(files( 'arm-qmp-cmds.c', )) -arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c')) +arm_system_ss.add(when: 'CONFIG_KVM', if_true: files( + 'hyp_gdbstub.c', + 'kvm.c', + 'kvm-rme.c')) arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) arm_user_ss.add(files('cpu.c'))Signature · 1 line
2.43.0
RFC v4 4/24 target/arm/kvm-rme: Add mechanic to initialize realms
In reply to Mathieu PoirierInitialise an @rme_guest object and install a handler to get notified when the Realm is ready to start. That way we can finish reading the Realm once we know everything is in place.
--- target/arm/kvm-rme.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 15 +++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-)
target/arm/kvm-rme.c +51 -0
@@ -13,6 +13,7 @@#include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h"
@@ -29,12 +30,62 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,CONFIDENTIAL_GUEST_SUPPORT , { TYPE_USER_CREATABLE }, { }) +static RmeGuest *rme_guest; + +static void rme_vm_state_change (void *opaque,bool running,RunState state) +{ +if (!running) { +return ; + } + +kvm_mark_guest_state_protected (); +} + +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) +{ +KVMState *s =KVM_STATE (current_accel ()); +static Error *rme_mig_blocker; + +if (!rme_guest) { +return 0 ; + } + +if (!kvm_vm_check_extension (s,KVM_CAP_ARM_RMI )) { +error_setg (errp,"VM doesn't support Realms" ); +return -ENODEV ; + } + +error_setg (&rme_mig_blocker,"RME: migration is not implemented" ); +migrate_add_blocker (&rme_mig_blocker, &error_fatal); + +/* +* The realm activation is done last, when the VM starts, after all images +* have been loaded and all vcpus finalized. +*/ +qemu_add_vm_change_state_handler (rme_vm_state_change,NULL ); + + cgs->require_guest_memfd = true; + cgs->ready = true; +return 0 ; +} +static void rme_guest_class_init (ObjectClass *oc,const void *data) { +ConfidentialGuestSupportClass *klass =CONFIDENTIAL_GUEST_SUPPORT_CLASS (oc); + + klass->kvm_init = kvm_arm_rme_init; }static void rme_guest_init (Object *obj) { +ConfidentialGuestSupport *cgs =CONFIDENTIAL_GUEST_SUPPORT (obj); + +if (rme_guest) { +error_report ("a single instance of RmeGuest is supported" ); +exit (1 ); + } + rme_guest =RME_GUEST (obj); + cgs->allow_convert_in_place = true; }static void rme_guest_finalize (Object *obj)
target/arm/kvm.c +13 -2
@@ -33,6 +33,7 @@#include "hw/pci/pci.h" #include "exec/memattrs.h" #include "system/address-spaces.h" +#include "system/confidential-guest-support.h" #include "gdbstub/enums.h" #include "hw/core/boards.h" #include "hw/core/irq.h"
@@ -596,7 +597,8 @@ int kvm_arch_get_default_type(MachineState *ms)int kvm_arch_init (MachineState *ms,KVMState *s) { -int ret; +Error *local_err =NULL ; +int ret =0 ;/* For ARM interrupt delivery is always asynchronous, * whether we are using an in-kernel VGIC or not. */
@@ -610,6 +612,15 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_has_mp_state =kvm_check_extension (s,KVM_CAP_MP_STATE ); +/* Initialize confidential guest (Realm) if needed */ +if (ms->cgs) { + ret =confidential_guest_kvm_init (ms->cgs, &local_err); +if (ret <0 ) { +error_report_err (local_err); +return ret; + } + } +/* Check whether user space can specify guest syndrome value */ cap_has_inject_serror_esr =kvm_check_extension (s,KVM_CAP_ARM_INJECT_SERROR_ESR );
@@ -660,7 +671,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) hw_breakpoints =g_array_sized_new (true, true,sizeof (HWBreakpoint), max_hw_bps); -return 0 ; +return ret; }unsigned long kvm_arch_vcpu_id (CPUState *cpu)
Signature · 1 line
2.43.0
Re: [RFC v4 04/24] target/arm/kvm-rme: Add mechanic to initialize realms
Quoted 110 lines · Mathieu Poirier
Initialise an @rme_guest object and install a handler to get notified when the Realm is ready to start. That way we can finish reading the Realm once we know everything is in place.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 15 +++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-)target/arm/kvm-rme.c +51
-0@@ -13,6 +13,7 @@#include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -29,12 +30,62 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,CONFIDENTIAL_GUEST_SUPPORT , { TYPE_USER_CREATABLE }, { }) +static RmeGuest *rme_guest; + +static void rme_vm_state_change (void *opaque,bool running,RunState state) +{ +if (!running) { +return ; + } + +kvm_mark_guest_state_protected (); +} + +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) +{ +KVMState *s =KVM_STATE (current_accel ()); +static Error *rme_mig_blocker; + +if (!rme_guest) { +return 0 ; + } + +if (!kvm_vm_check_extension (s,KVM_CAP_ARM_RMI )) { +error_setg (errp,"VM doesn't support Realms" ); +return -ENODEV ; + } + +error_setg (&rme_mig_blocker,"RME: migration is not implemented" ); +migrate_add_blocker (&rme_mig_blocker, &error_fatal); + +/* +* The realm activation is done last, when the VM starts, after all images +* have been loaded and all vcpus finalized. +*/ +qemu_add_vm_change_state_handler (rme_vm_state_change,NULL ); + + cgs->require_guest_memfd = true; + cgs->ready = true; +return 0 ; +} +static void rme_guest_class_init (ObjectClass *oc,const void *data) { +ConfidentialGuestSupportClass *klass =CONFIDENTIAL_GUEST_SUPPORT_CLASS (oc); + + klass->kvm_init = kvm_arm_rme_init; }static void rme_guest_init (Object *obj) { +ConfidentialGuestSupport *cgs =CONFIDENTIAL_GUEST_SUPPORT (obj); + +if (rme_guest) { +error_report ("a single instance of RmeGuest is supported" ); +exit (1 ); + } + rme_guest =RME_GUEST (obj); + cgs->allow_convert_in_place = true; }static void rme_guest_finalize (Object *obj)target/arm/kvm.c +3
-1@@ -33,6 +33,7 @@#include "hw/pci/pci.h" #include "exec/memattrs.h" #include "system/address-spaces.h" +#include "system/confidential-guest-support.h" #include "gdbstub/enums.h" #include "hw/core/boards.h" #include "hw/core/irq.h" @@ -596,7 +597,8 @@ int kvm_arch_get_default_type(MachineState *ms)int kvm_arch_init (MachineState *ms,KVMState *s) { -int ret; +Error *local_err =NULL ; +int ret =0 ;/* For ARM interrupt delivery is always asynchronous, * whether we are using an in-kernel VGIC or not. */
target/arm/kvm.c int kvm_arch_init(MachineState *ms, KVMState *s) · line 618
Quoted 7 lines
target/arm/kvm.c +4
-0@@ -610,6 +612,15 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_has_mp_state =kvm_check_extension (s,KVM_CAP_MP_STATE ); +/* Initialize confidential guest (Realm) if needed */ +if (ms->cgs) { + ret =confidential_guest_kvm_init (ms->cgs, &local_err); +if (ret <0 ) {
^^^^^
Code alignment issue here.
Quoted 9 lines
target/arm/kvm.c +5
-0+error_report_err (local_err); +return ret; + } + } +/* Check whether user space can specify guest syndrome value */ cap_has_inject_serror_esr =kvm_check_extension (s,KVM_CAP_ARM_INJECT_SERROR_ESR );
target/arm/kvm.c int kvm_arch_init(MachineState *ms, KVMState *s) · line 677
Quoted 8 lines
target/arm/kvm.c +1
-1@@ -660,7 +671,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) hw_breakpoints =g_array_sized_new (true, true,sizeof (HWBreakpoint), max_hw_bps); -return 0 ; +return ret; }unsigned long kvm_arch_vcpu_id (CPUState *cpu)
Thanks,
Gavin
RFC v4 5/24 target/arm/kvm: Split kvm_arch_get/put_registers
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
For a Realm, KVM is much more restrictive on the registers a VMM can initialize. To prepare for Realm VM initialization, split the get/put register functions for a non-secure VM in their own function.
--- target/arm/kvm.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-)
target/arm/kvm.c +28 -2
@@ -2169,7 +2169,7 @@ static int kvm_arch_put_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } -int kvm_arch_put_registers (CPUState *cs,KvmPutState level,Error **errp) +static int kvm_arm_put_core_regs (CPUState *cs,Error **errp) {uint64_t val;uint32_t fpr;
@@ -2272,6 +2272,19 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)return ret; } +return 0 ; +} + +int kvm_arch_put_registers (CPUState *cs,KvmPutState level,Error **errp) +{ +int ret; +ARMCPU *cpu =ARM_CPU (cs); + + ret =kvm_arm_put_core_regs (cs, errp); +if (ret) { +return ret; + } +write_cpustate_to_list (cpu, true);if (!write_list_to_kvmstate (cpu, level)) {
@@ -2354,7 +2367,7 @@ static int kvm_arch_get_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } -int kvm_arch_get_registers (CPUState *cs,Error **errp) +static int kvm_arm_get_core_regs (CPUState *cs,Error **errp) {uint64_t val;unsigned int el;
@@ -2457,6 +2470,19 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) }vfp_set_fpcr (env, fpr); +return 0 ; +} + +int kvm_arch_get_registers (CPUState *cs,Error **errp) +{ +int ret; +ARMCPU *cpu =ARM_CPU (cs); + + ret =kvm_arm_get_core_regs (cs, errp); +if (ret) { +return ret; + } + ret =kvm_get_vcpu_events (cpu);if (ret) {return ret;
Signature · 1 line
2.43.0
RFC v4 6/24 target/arm/kvm-rme: Initialize vCPU
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
The target code calls kvm_arm_vcpu_init() to mark the vCPU as part of a Realm. For a Realm vCPU, only x0-x7 can be set at runtime. Before boot, the PC can also be set, and is ignored at runtime. KVM also accepts a few system register changes during initial configuration, as returned by KVM_GET_REG_LIST.
--- target/arm/cpu.h | 3 +++ target/arm/kvm-rme.c | 9 ++++++++ target/arm/kvm-stub.c | 5 ++++ target/arm/kvm.c | 54 +++++++++++++++++++++++++++++++++++++++++-- target/arm/kvm_arm.h | 10 ++++++++ 5 files changed, 79 insertions(+), 2 deletions(-)
target/arm/cpu.h +3 -0
@@ -1054,6 +1054,9 @@ struct ArchCPU {/* KVM steal time */ OnOffAuto kvm_steal_time; +/* Realm Management Extension */ +bool kvm_rme; +/* Uniprocessor system with MP extensions */ bool mp_is_up;
target/arm/kvm-rme.c +9 -0
@@ -69,6 +69,15 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)return 0 ; } +void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +if (!rme_guest) { +return ; + } + + cpu->kvm_rme = true; +} +static void rme_guest_class_init (ObjectClass *oc,const void *data) {ConfidentialGuestSupportClass *klass =CONFIDENTIAL_GUEST_SUPPORT_CLASS (oc);
target/arm/kvm-stub.c +5 -0
@@ -119,3 +119,8 @@ char *kvm_print_register_name(uint64_t regidx) {g_assert_not_reached (); } + +void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +g_assert_not_reached (); +}
target/arm/kvm.c +52 -2
84 lines not on this page · raw message
target/arm/kvm_arm.h +10 -0
@@ -240,4 +240,14 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3);*/ char *kvm_print_register_name (uint64_t regidx); +/** +* kvm_arm_rme_vcpu_init +* @cs: the CPU +* +* If the user requested a Realm, setup the given vCPU accordingly. Realm vCPUs +* behave a little differently, for example most of their register state is +* hidden from the host. +*/ +void kvm_arm_rme_vcpu_init (ARMCPU *cpu); +#endif
Signature · 1 line
2.43.0
Re: [RFC v4 06/24] target/arm/kvm-rme: Initialize vCPU
Quoted 23 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
The target code calls
kvm_arm_vcpu_init()to mark the vCPU as part of a Realm. For a Realm vCPU, only x0-x7 can be set at runtime. Before boot, the PC can also be set, and is ignored at runtime. KVM also accepts a few system register changes during initial configuration, as returned byKVM_GET_REG_LIST.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/cpu.h | 3 +++ target/arm/kvm-rme.c | 9 ++++++++ target/arm/kvm-stub.c | 5 ++++ target/arm/kvm.c | 54 +++++++++++++++++++++++++++++++++++++++++-- target/arm/kvm_arm.h | 10 ++++++++ 5 files changed, 79 insertions(+), 2 deletions(-)target/arm/cpu.h +0
-0
target/arm/cpu.h struct ArchCPU { · line 1059
Quoted 6 lines
target/arm/cpu.h +3
-0@@ -1054,6 +1054,9 @@ struct ArchCPU {/* KVM steal time */ OnOffAuto kvm_steal_time; +/* Realm Management Extension */ +bool kvm_rme; +
This field seems redundant to MachineState::cgs since all vCPUs support RME (Realm Management Extension) when MachineState::cgs points a valid instance. So I'm wandering why we need to maintain the redundant information here?
Quoted 10 lines
target/arm/cpu.h +0
-0/* Uniprocessor system with MP extensions */ bool mp_is_up;target/arm/kvm-rme.c +0
-0@@ -69,6 +69,15 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)return 0 ; }
target/arm/kvm-rme.c static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp) · line 80
Quoted 10 lines
target/arm/kvm-rme.c +9
-0+void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +if (!rme_guest) { +return ; + } + + cpu->kvm_rme = true; +} +
This could be simplified to:
cpu->kvm_rme = !!rme_guest;
Quoted 117 lines
target/arm/kvm-rme.c +0
-0static void rme_guest_class_init (ObjectClass *oc,const void *data) {ConfidentialGuestSupportClass *klass =CONFIDENTIAL_GUEST_SUPPORT_CLASS (oc);target/arm/kvm-stub.c +5
-0@@ -119,3 +119,8 @@ char *kvm_print_register_name(uint64_t regidx) {g_assert_not_reached (); } + +void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +g_assert_not_reached (); +}target/arm/kvm.c +52
-2@@ -2015,6 +2015,8 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu->kvm_init_features[0 ] |=1 <<KVM_ARM_VCPU_HAS_EL2 ; } +kvm_arm_rme_vcpu_init (cpu); +/* Do KVM_ARM_VCPU_INIT ioctl */ ret =kvm_arm_vcpu_init (cpu);if (ret) {@@ -2169,6 +2171,29 @@ static int kvm_arch_put_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } +static int kvm_arm_rme_put_core_regs (CPUState *cs,Error **errp) +{ +int i, ret; +ARMCPU *cpu =ARM_CPU (cs); +CPUARMState *env = &cpu->env; + +/* The RME ABI only allows us to set 8 GPRs and the PC */ +for (i =0 ; i <8 ; i++) { + ret =kvm_set_one_reg (cs,AARCH64_CORE_REG (regs.regs[i]), + &env->xregs[i]); +if (ret) { +return ret; + } + } + + ret =kvm_set_one_reg (cs,AARCH64_CORE_REG (regs.pc), &env->pc); +if (ret) { +return ret; + } + +return 0 ; +} +static int kvm_arm_put_core_regs (CPUState *cs,Error **errp) {uint64_t val;@@ -2280,7 +2305,11 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)int ret;ARMCPU *cpu =ARM_CPU (cs); - ret =kvm_arm_put_core_regs (cs, errp); +if (cpu->kvm_rme) { + ret =kvm_arm_rme_put_core_regs (cs, errp); + }else { + ret =kvm_arm_put_core_regs (cs, errp); + }if (ret) {return ret; }@@ -2367,6 +2396,23 @@ static int kvm_arch_get_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } +static int kvm_arm_rme_get_core_regs (CPUState *cs,Error **errp) +{ +int i, ret; +ARMCPU *cpu =ARM_CPU (cs); +CPUARMState *env = &cpu->env; + +for (i =0 ; i <8 ; i++) { + ret =kvm_get_one_reg (cs,AARCH64_CORE_REG (regs.regs[i]), + &env->xregs[i]); +if (ret) { +return ret; + } + } + +return 0 ; +} +static int kvm_arm_get_core_regs (CPUState *cs,Error **errp) {uint64_t val;@@ -2478,7 +2524,11 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp)int ret;ARMCPU *cpu =ARM_CPU (cs); - ret =kvm_arm_get_core_regs (cs, errp); +if (cpu->kvm_rme) { + ret =kvm_arm_rme_get_core_regs (cs, errp); + }else { + ret =kvm_arm_get_core_regs (cs, errp); + }if (ret) {return ret; }target/arm/kvm_arm.h +0
-0@@ -240,4 +240,14 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3);*/ char *kvm_print_register_name (uint64_t regidx);
target/arm/kvm_arm.h void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3); · line 252
Quoted 10 lines
target/arm/kvm_arm.h +10
-0+/** +* kvm_arm_rme_vcpu_init +* @cs: the CPU +* +* If the user requested a Realm, setup the given vCPU accordingly. Realm vCPUs +* behave a little differently, for example most of their register state is +* hidden from the host. +*/ +void kvm_arm_rme_vcpu_init (ARMCPU *cpu); +
The comments here look outdated. This function simply set ARMCPU::kvm_rme to indicate RME should be supported for this given vCPU. So the comments would be something as below.
/*
*
* Mark that RME (Realm Management Extension) should be supported for the given
* vCPU if user has requested it. Realm vCPUs behave a little differently, for
* example most of their register states are confidential and invisible to us. */
target/arm/kvm_arm.h void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3); · line 253
Quoted 1 line
target/arm/kvm_arm.h +0
-0#endif
Thanks,
Gavin
Re: [RFC v4 06/24] target/arm/kvm-rme: Initialize vCPU
Quoted 19 lines · Gavin Shan
Quoted 18 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
The target code calls
kvm_arm_vcpu_init()to mark the vCPU as part of a Realm. For a Realm vCPU, only x0-x7 can be set at runtime. Before boot, the PC can also be set, and is ignored at runtime. KVM also accepts a few system register changes during initial configuration, as returned byKVM_GET_REG_LIST.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/cpu.h | 3 +++ target/arm/kvm-rme.c | 9 ++++++++ target/arm/kvm-stub.c | 5 ++++ target/arm/kvm.c | 54 +++++++++++++++++++++++++++++++++++++++++-- target/arm/kvm_arm.h | 10 ++++++++ 5 files changed, 79 insertions(+), 2 deletions(-)
Quoted 15 lines
target/arm/cpu.h struct ArchCPU { · line 1058
Quoted 10 lines
target/arm/cpu.h +3
-0@@ -1054,6 +1054,9 @@ struct ArchCPU {/* KVM steal time */ OnOffAuto kvm_steal_time; +/* Realm Management Extension */ +bool kvm_rme; +This field seems redundant to
MachineState::cgssince all vCPUs support RME (Realm Management Extension) whenMachineState::cgspoints a valid instance. So I'm wandering why we need to maintain the redundant information here?
It is redundant, at least at this time. I have removed it in favour of MACHINE(qdev_get_machine())->cgs where cpu->kvm_rme was used. With that it was possible to get rid of function kvm_arm_rme_vcpu_init().
Quoted 161 lines
Quoted 8 lines
target/arm/cpu.h +0
-0/* Uniprocessor system with MP extensions */ bool mp_is_up;target/arm/kvm-rme.c +0
-0@@ -69,6 +69,15 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)return 0 ;target/arm/kvm-rme.c static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp) · line 79
Quoted 10 lines
target/arm/kvm-rme.c +9
-0} +void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +if (!rme_guest) { +return ; + } + + cpu->kvm_rme = true; +} +This could be simplified to:
cpu->kvm_rme = !!rme_guest;Quoted 111 lines
target/arm/kvm-rme.c +0
-0static void rme_guest_class_init (ObjectClass *oc,const void *data) {ConfidentialGuestSupportClass *klass =CONFIDENTIAL_GUEST_SUPPORT_CLASS (oc);target/arm/kvm-stub.c +5
-0@@ -119,3 +119,8 @@ char *kvm_print_register_name(uint64_t regidx) {g_assert_not_reached (); } + +void kvm_arm_rme_vcpu_init (ARMCPU *cpu) +{ +g_assert_not_reached (); +}target/arm/kvm.c +52
-2@@ -2015,6 +2015,8 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu->kvm_init_features[0 ] |=1 <<KVM_ARM_VCPU_HAS_EL2 ; } +kvm_arm_rme_vcpu_init (cpu); +/* Do KVM_ARM_VCPU_INIT ioctl */ ret =kvm_arm_vcpu_init (cpu);if (ret) {@@ -2169,6 +2171,29 @@ static int kvm_arch_put_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } +static int kvm_arm_rme_put_core_regs (CPUState *cs,Error **errp) +{ +int i, ret; +ARMCPU *cpu =ARM_CPU (cs); +CPUARMState *env = &cpu->env; + +/* The RME ABI only allows us to set 8 GPRs and the PC */ +for (i =0 ; i <8 ; i++) { + ret =kvm_set_one_reg (cs,AARCH64_CORE_REG (regs.regs[i]), + &env->xregs[i]); +if (ret) { +return ret; + } + } + + ret =kvm_set_one_reg (cs,AARCH64_CORE_REG (regs.pc), &env->pc); +if (ret) { +return ret; + } + +return 0 ; +} +static int kvm_arm_put_core_regs (CPUState *cs,Error **errp) {uint64_t val;@@ -2280,7 +2305,11 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)int ret;ARMCPU *cpu =ARM_CPU (cs); - ret =kvm_arm_put_core_regs (cs, errp); +if (cpu->kvm_rme) { + ret =kvm_arm_rme_put_core_regs (cs, errp); + }else { + ret =kvm_arm_put_core_regs (cs, errp); + }if (ret) {return ret; }@@ -2367,6 +2396,23 @@ static int kvm_arch_get_sve(CPUState *cs, uint32_t vq, bool have_ffr)return 0 ; } +static int kvm_arm_rme_get_core_regs (CPUState *cs,Error **errp) +{ +int i, ret; +ARMCPU *cpu =ARM_CPU (cs); +CPUARMState *env = &cpu->env; + +for (i =0 ; i <8 ; i++) { + ret =kvm_get_one_reg (cs,AARCH64_CORE_REG (regs.regs[i]), + &env->xregs[i]); +if (ret) { +return ret; + } + } + +return 0 ; +} +static int kvm_arm_get_core_regs (CPUState *cs,Error **errp) {uint64_t val;@@ -2478,7 +2524,11 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp)int ret;ARMCPU *cpu =ARM_CPU (cs); - ret =kvm_arm_get_core_regs (cs, errp); +if (cpu->kvm_rme) { + ret =kvm_arm_rme_get_core_regs (cs, errp); + }else { + ret =kvm_arm_get_core_regs (cs, errp); + }if (ret) {return ret; }target/arm/kvm_arm.h +0
-0@@ -240,4 +240,14 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3);*/ char *kvm_print_register_name (uint64_t regidx);target/arm/kvm_arm.h void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3); · line 251
Quoted 10 lines
target/arm/kvm_arm.h +10
-0+/** +* kvm_arm_rme_vcpu_init +* @cs: the CPU +* +* If the user requested a Realm, setup the given vCPU accordingly. Realm vCPUs +* behave a little differently, for example most of their register state is +* hidden from the host. +*/ +void kvm_arm_rme_vcpu_init (ARMCPU *cpu); +The comments here look outdated. This function simply set
ARMCPU::kvm_rmeto indicate RME should be supported for this given vCPU. So the comments would be something as below./*
*
* Mark that RME (Realm Management Extension) should be supported for the given
* vCPU if user has requested it. Realm vCPUs behave a little differently, for
* example most of their register states are confidential and invisible to us. */target/arm/kvm_arm.h void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3); · line 252
Quoted 1 line
target/arm/kvm_arm.h +0
-0#endif Thanks,
Gavin
RFC v4 7/24 target/arm/kvm: Create scratch Realm VM when requested
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
When a Realm is requested, create a scratch Realm VM by setting bit 8 of the argument given to the KVM_CREATE_VM ioctl(). Bit 7-0 are reserved for the guest PA size.
--- target/arm/kvm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
target/arm/kvm.c +5 -1
@@ -108,7 +108,9 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray, struct kvm_vcpu_init *init) {int ret =0 , kvmfd =-1 , vmfd =-1 , cpufd =-1 ; +MachineState *ms =MACHINE (qdev_get_machine ());int max_vm_pa_size; +int vm_type; kvmfd =qemu_open_old ("/dev/kvm" ,O_RDWR );if (kvmfd <0 ) {
@@ -118,8 +120,10 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray,if (max_vm_pa_size <0 ) { max_vm_pa_size =0 ; } + + vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL );do { - vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size); + vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size | vm_type); }while (vmfd ==-1 && errno ==EINTR );if (vmfd <0 ) { goto err;
Signature · 1 line
2.43.0
Re: [RFC v4 07/24] target/arm/kvm: Create scratch Realm VM when requested
Quoted 3 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When a Realm is requested, create a scratch Realm VM by setting bit 8
nit:KVM_VM_TYPE_ARM_REALM is no longer defined as 1 << 8, so shouldn't this be updated as well?
Quoted 5 lines
of the argument given to the
KVM_CREATE_VMioctl(). Bit 7-0 are reserved for the guest PA size.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>
Re: [RFC v4 07/24] target/arm/kvm: Create scratch Realm VM when requested
Quoted 8 lines · Kohei Enju
Quoted 3 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When a Realm is requested, create a scratch Realm VM by setting bit 8
nit:
KVM_VM_TYPE_ARM_REALMis no longer defined as 1 << 8, so shouldn't this be updated as well?
This changes often - I'll look into it.
Quoted 6 lines
Quoted 6 lines
of the argument given to the
KVM_CREATE_VMioctl(). Bit 7-0 are reserved for the guest PA size.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>
Re: [RFC v4 07/24] target/arm/kvm: Create scratch Realm VM when requested
In reply to Mathieu PoirierQuoted 17 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When a Realm is requested, create a scratch Realm VM by setting bit 8 of the argument given to the
KVM_CREATE_VMioctl(). Bit 7-0 are reserved for the guest PA size.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)target/arm/kvm.c +0
-0
target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 114
Quoted 7 lines
target/arm/kvm.c +2
-0@@ -108,7 +108,9 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray, struct kvm_vcpu_init *init) {int ret =0 , kvmfd =-1 , vmfd =-1 , cpufd =-1 ; +MachineState *ms =MACHINE (qdev_get_machine ());int max_vm_pa_size; +int vm_type;
@vm_type can be initialized when it's declared.
MachineState *ms = MACHINE(qdev_get_machine());
int vm_type = ms->cgs ? KVM_VM_TYPE_ARM_REALM : KVM_VM_TYPE_ARM_NORMAL;
int max_vm_pa_size;target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 124
Quoted 8 lines
target/arm/kvm.c +2
-0kvmfd =qemu_open_old ("/dev/kvm" ,O_RDWR );if (kvmfd <0 ) {@@ -118,8 +120,10 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray,if (max_vm_pa_size <0 ) { max_vm_pa_size =0 ; } + + vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL );
() aren't needed.
target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 129
Quoted 6 lines
target/arm/kvm.c +1
-1do { - vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size); + vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size | vm_type); }while (vmfd ==-1 && errno ==EINTR );if (vmfd <0 ) { goto err;
Thanks,
Gavin
Re: [RFC v4 07/24] target/arm/kvm: Create scratch Realm VM when requested
Quoted 32 lines · Gavin Shan
Quoted 17 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When a Realm is requested, create a scratch Realm VM by setting bit 8 of the argument given to the
KVM_CREATE_VMioctl(). Bit 7-0 are reserved for the guest PA size.Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)target/arm/kvm.c +0
-0target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 114
Quoted 7 lines
target/arm/kvm.c +2
-0@@ -108,7 +108,9 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray, struct kvm_vcpu_init *init) {int ret =0 , kvmfd =-1 , vmfd =-1 , cpufd =-1 ; +MachineState *ms =MACHINE (qdev_get_machine ());int max_vm_pa_size; +int vm_type;@vm_type can be initialized when it's declared.
MachineState *ms = MACHINE(qdev_get_machine()); int vm_type = ms->cgs ? KVM_VM_TYPE_ARM_REALM : KVM_VM_TYPE_ARM_NORMAL; int max_vm_pa_size;
Quoted 11 lines
target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 124
Quoted 8 lines
target/arm/kvm.c +2
-0kvmfd =qemu_open_old ("/dev/kvm" ,O_RDWR );if (kvmfd <0 ) {@@ -118,8 +120,10 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray,if (max_vm_pa_size <0 ) { max_vm_pa_size =0 ; } + + vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL );() aren't needed.
All fixed.
Quoted 10 lines
target/arm/kvm.c bool kvm_arm_create_scratch_host_vcpu(int *fdarray, · line 129
Quoted 6 lines
target/arm/kvm.c +1
-1do { - vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size); + vmfd =ioctl (kvmfd,KVM_CREATE_VM , max_vm_pa_size | vm_type); }while (vmfd ==-1 && errno ==EINTR );if (vmfd <0 ) { goto err;Thanks,
Gavin
RFC v4 8/24 target/arm/kvm: Use kvm_vm_check_extension() where necessary
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
The Arm KVM code can return different values from KVM_CHECK_EXTENSION depending on the VM type. Use kvm_vm_check_extension() where necessary to ensure we get the right response from KVM.
--- target/arm/kvm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
target/arm/kvm.c +5 -5
@@ -331,7 +331,7 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); } -if (kvm_check_extension (kvm_state,KVM_CAP_ARM_PMU_V3 )) { +if (kvm_vm_check_extension (kvm_state,KVM_CAP_ARM_PMU_V3 )) { init.features[0 ] |=1 <<KVM_ARM_VCPU_PMU_V3 ; pmu_supported = true; features |=1ULL <<ARM_FEATURE_PMU ;
@@ -636,7 +636,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)return -EINVAL ; } -if (kvm_check_extension (s,KVM_CAP_ARM_NISV_TO_USER )) { +if (kvm_vm_check_extension (s,KVM_CAP_ARM_NISV_TO_USER )) {if (kvm_vm_enable_cap (s,KVM_CAP_ARM_NISV_TO_USER ,0 )) {error_report ("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap" ); }else {
@@ -667,11 +667,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } } - max_hw_wps =kvm_check_extension (s,KVM_CAP_GUEST_DEBUG_HW_WPS ); + max_hw_wps =kvm_vm_check_extension (s,KVM_CAP_GUEST_DEBUG_HW_WPS ); hw_watchpoints =g_array_sized_new (true, true,sizeof (HWWatchpoint), max_hw_wps); - max_hw_bps =kvm_check_extension (s,KVM_CAP_GUEST_DEBUG_HW_BPS ); + max_hw_bps =kvm_vm_check_extension (s,KVM_CAP_GUEST_DEBUG_HW_BPS ); hw_breakpoints =g_array_sized_new (true, true,sizeof (HWBreakpoint), max_hw_bps);
@@ -1913,7 +1913,7 @@ void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa)void kvm_arm_steal_time_finalize (ARMCPU *cpu,Error **errp) { -bool has_steal_time =kvm_check_extension (kvm_state,KVM_CAP_STEAL_TIME ); +bool has_steal_time =kvm_vm_check_extension (kvm_state,KVM_CAP_STEAL_TIME );if (cpu->kvm_steal_time ==ON_OFF_AUTO_AUTO ) {if (!has_steal_time || !arm_feature (&cpu->env,ARM_FEATURE_AARCH64 )) {
Signature · 1 line
2.43.0
RFC v4 9/24 hw/core/loader: Add a ROM loader notifier
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Add a function to register a notifier that is invoked when ROMs get loaded into guest memory.
It will be used by Arm confidential guest support, in order to register all blobs loaded into memory with KVM, so that their content is moved into Realm state and measured into the initial VM state.
--- hw/core/loader.c | 15 +++++++++++++++ include/hw/core/loader.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+)
hw/core/loader.c +15 -0
@@ -74,6 +74,8 @@#endif static int roms_loaded; +static NotifierList rom_loader_notifier = +NOTIFIER_LIST_INITIALIZER (rom_loader_notifier);/* return the size or -1 if error */ int64_t get_image_size (const char *filename,Error **errp)
@@ -1201,6 +1203,11 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,return mr; } +void rom_add_load_notifier (Notifier *notifier) +{ +notifier_list_add (&rom_loader_notifier, notifier); +} +/* This function is specific for elf program because we don't need to allocate * all the rom. We just allocate the first part and the rest is just zeros. This * is why romsize and datasize are different. Also, this function takes its own
@@ -1242,6 +1249,7 @@ ssize_t rom_add_option(const char *file, int32_t bootindex)static void rom_reset (void *unused) {Rom *rom; +RomLoaderNotifyData notify; QTAILQ_FOREACH(rom, &roms, next) {if (rom->fw_file) {
@@ -1290,6 +1298,13 @@ static void rom_reset(void *unused)address_space_flush_icache_range (rom->as, rom->addr, rom->datasize);trace_loader_write_rom (rom->name, rom->addr, rom->datasize, rom->isrom); + + notify = (RomLoaderNotifyData ) { + .addr = rom->addr, + .len = rom->datasize, + .data = rom->data, + }; +notifier_list_notify (&rom_loader_notifier, ¬ify); } }
include/hw/core/loader.h +17 -0
@@ -342,6 +342,23 @@ void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size);ssize_t rom_add_vga (const char *file);ssize_t rom_add_option (const char *file,int32_t bootindex); +typedef struct RomLoaderNotifyData { +/* Address of the blob in guest memory */ +hwaddr addr; +/* Length of the blob */ +size_t len; +/* Blog data */ +uint8_t *data; +}RomLoaderNotifyData ; + +/** +* rom_add_load_notifier - Add a notifier for loaded images +* +* Add a notifier that will be invoked with a RomLoaderNotifyData structure for +* each blob loaded into guest memory, after the blob is loaded. +*/ +void rom_add_load_notifier (Notifier *notifier); +/* This is the usual maximum in uboot, so if a uImage overflows this, it would * overflow on real hardware too. */ #define UBOOT_MAX_DECOMPRESSED_BYTES (64 << 20)
Signature · 1 line
2.43.0
Re: [RFC v4 09/24] hw/core/loader: Add a ROM loader notifier
Quoted 51 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a function to register a notifier that is invoked when ROMs get loaded into guest memory.
It will be used by Arm confidential guest support, in order to register all blobs loaded into memory with KVM, so that their content is moved into Realm state and measured into the initial VM state.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/core/loader.c | 15 +++++++++++++++ include/hw/core/loader.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+)hw/core/loader.c +8
-0@@ -74,6 +74,8 @@#endif static int roms_loaded; +static NotifierList rom_loader_notifier = +NOTIFIER_LIST_INITIALIZER (rom_loader_notifier);/* return the size or -1 if error */ int64_t get_image_size (const char *filename,Error **errp)@@ -1201,6 +1203,11 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,return mr; } +void rom_add_load_notifier (Notifier *notifier) +{ +notifier_list_add (&rom_loader_notifier, notifier); +} +/* This function is specific for elf program because we don't need to allocate * all the rom. We just allocate the first part and the rest is just zeros. This * is why romsize and datasize are different. Also, this function takes its own @@ -1242,6 +1249,7 @@ ssize_t rom_add_option(const char *file, int32_t bootindex)static void rom_reset (void *unused) {Rom *rom; +RomLoaderNotifyData notify; QTAILQ_FOREACH(rom, &roms, next) {if (rom->fw_file) {
hw/core/loader.c static void rom_reset(void *unused) · line 1307
Quoted 10 lines
hw/core/loader.c +7
-0@@ -1290,6 +1298,13 @@ static void rom_reset(void *unused)address_space_flush_icache_range (rom->as, rom->addr, rom->datasize);trace_loader_write_rom (rom->name, rom->addr, rom->datasize, rom->isrom); + + notify = (RomLoaderNotifyData ) { + .addr = rom->addr, + .len = rom->datasize, + .data = rom->data, + }; +notifier_list_notify (&rom_loader_notifier, ¬ify);
I think it will easier to review this if it's squashed into the next patch where the fields are utilized.
-Mike
Re: [RFC v4 09/24] hw/core/loader: Add a ROM loader notifier
In reply to Mathieu PoirierQuoted 69 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a function to register a notifier that is invoked when ROMs get loaded into guest memory.
It will be used by Arm confidential guest support, in order to register all blobs loaded into memory with KVM, so that their content is moved into Realm state and measured into the initial VM state.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/core/loader.c | 15 +++++++++++++++ include/hw/core/loader.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+)hw/core/loader.c +15
-0@@ -74,6 +74,8 @@#endif static int roms_loaded; +static NotifierList rom_loader_notifier = +NOTIFIER_LIST_INITIALIZER (rom_loader_notifier);/* return the size or -1 if error */ int64_t get_image_size (const char *filename,Error **errp)@@ -1201,6 +1203,11 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,return mr; } +void rom_add_load_notifier (Notifier *notifier) +{ +notifier_list_add (&rom_loader_notifier, notifier); +} +/* This function is specific for elf program because we don't need to allocate * all the rom. We just allocate the first part and the rest is just zeros. This * is why romsize and datasize are different. Also, this function takes its own @@ -1242,6 +1249,7 @@ ssize_t rom_add_option(const char *file, int32_t bootindex)static void rom_reset (void *unused) {Rom *rom; +RomLoaderNotifyData notify; QTAILQ_FOREACH(rom, &roms, next) {if (rom->fw_file) {@@ -1290,6 +1298,13 @@ static void rom_reset(void *unused)address_space_flush_icache_range (rom->as, rom->addr, rom->datasize);trace_loader_write_rom (rom->name, rom->addr, rom->datasize, rom->isrom); + + notify = (RomLoaderNotifyData ) { + .addr = rom->addr, + .len = rom->datasize, + .data = rom->data, + }; +notifier_list_notify (&rom_loader_notifier, ¬ify); } }include/hw/core/loader.h +0
-0
include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 350
Quoted 9 lines
include/hw/core/loader.h +6
-0@@ -342,6 +342,23 @@ void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size);ssize_t rom_add_vga (const char *file);ssize_t rom_add_option (const char *file,int32_t bootindex); +typedef struct RomLoaderNotifyData { + /* Address of the blob in guest memory */ + hwaddr addr; + /* Length of the blob */ + size_t len; + /* Blog data */
^^^^
I guess it would be 'Blob'.
include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 353
Quoted 3 lines
include/hw/core/loader.h +3
-0+uint8_t *data; +} RomLoaderNotifyData; +
There are enough space at the tail of field declaration lines, where the comments can be put:
typedef struct RomLoaderNotifyData {
hwaddr addr; /* Address of the blob in guest memory */
size_t len; /* Length of the blob */
uint8_t *data; /* Blob data */} RomLoaderNotifyData;
include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 364
Quoted 11 lines
include/hw/core/loader.h +8
-0+/** +* rom_add_load_notifier - Add a notifier for loaded images +* +* Add a notifier that will be invoked with a RomLoaderNotifyData structure for +* each blob loaded into guest memory, after the blob is loaded. +*/ +void rom_add_load_notifier (Notifier *notifier); +/* This is the usual maximum in uboot, so if a uImage overflows this, it would * overflow on real hardware too. */ #define UBOOT_MAX_DECOMPRESSED_BYTES (64 << 20)
Thanks,
Gavin
Re: [RFC v4 09/24] hw/core/loader: Add a ROM loader notifier
Quoted 82 lines · Gavin Shan
Quoted 63 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a function to register a notifier that is invoked when ROMs get loaded into guest memory.
It will be used by Arm confidential guest support, in order to register all blobs loaded into memory with KVM, so that their content is moved into Realm state and measured into the initial VM state.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/core/loader.c | 15 +++++++++++++++ include/hw/core/loader.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+)hw/core/loader.c +15
-0@@ -74,6 +74,8 @@#endif static int roms_loaded; +static NotifierList rom_loader_notifier = +NOTIFIER_LIST_INITIALIZER (rom_loader_notifier);/* return the size or -1 if error */ int64_t get_image_size (const char *filename,Error **errp)@@ -1201,6 +1203,11 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,return mr; } +void rom_add_load_notifier (Notifier *notifier) +{ +notifier_list_add (&rom_loader_notifier, notifier); +} +/* This function is specific for elf program because we don't need to allocate * all the rom. We just allocate the first part and the rest is just zeros. This * is why romsize and datasize are different. Also, this function takes its own @@ -1242,6 +1249,7 @@ ssize_t rom_add_option(const char *file, int32_t bootindex)static void rom_reset (void *unused) {Rom *rom; +RomLoaderNotifyData notify; QTAILQ_FOREACH(rom, &roms, next) {if (rom->fw_file) {@@ -1290,6 +1298,13 @@ static void rom_reset(void *unused)address_space_flush_icache_range (rom->as, rom->addr, rom->datasize);trace_loader_write_rom (rom->name, rom->addr, rom->datasize, rom->isrom); + + notify = (RomLoaderNotifyData ) { + .addr = rom->addr, + .len = rom->datasize, + .data = rom->data, + }; +notifier_list_notify (&rom_loader_notifier, ¬ify); } }include/hw/core/loader.h +0
-0include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 349
Quoted 8 lines
include/hw/core/loader.h +6
-0@@ -342,6 +342,23 @@ void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size);ssize_t rom_add_vga (const char *file);ssize_t rom_add_option (const char *file,int32_t bootindex); +typedef struct RomLoaderNotifyData { + /* Address of the blob in guest memory */ + hwaddr addr; + /* Length of the blob */ + size_t len; + /* Blog data */^^^^I guess it would be 'Blob'.
include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 353
Quoted 3 lines
include/hw/core/loader.h +3
-0+uint8_t *data; +} RomLoaderNotifyData; +There are enough space at the tail of field declaration lines, where the comments can be put:
Quoted 6 lines
typedef struct RomLoaderNotifyData {
hwaddr addr; /* Address of the blob in guest memory */ size_t len; /* Length of the blob */ uint8_t *data; /* Blob data */} RomLoaderNotifyData;
Fixed
Quoted 16 lines
include/hw/core/loader.h void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); · line 364
Quoted 12 lines
include/hw/core/loader.h +8
-0+/** +* rom_add_load_notifier - Add a notifier for loaded images +* +* Add a notifier that will be invoked with a RomLoaderNotifyData structure for +* each blob loaded into guest memory, after the blob is loaded. +*/ +void rom_add_load_notifier (Notifier *notifier); +/* This is the usual maximum in uboot, so if a uImage overflows this, it would * overflow on real hardware too. */ #define UBOOT_MAX_DECOMPRESSED_BYTES (64 << 20)Thanks,
Gavin
RFC v4 10/24 target/arm/kvm-rme: Keep track of images loaded in Realm memory
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM).
--- target/arm/kvm-rme.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
target/arm/kvm-rme.c +52 -0
@@ -10,6 +10,7 @@#include "hw/core/boards.h" #include "hw/core/cpu.h" +#include "hw/core/loader.h" #include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h"
@@ -22,8 +23,18 @@#define TYPE_RME_GUEST "rme-guest" OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) +#define RME_PAGE_SIZE qemu_real_host_page_size() + +typedef struct { +hwaddr base; +hwaddr size; +uint8_t *data; +}RmeRamRegion ; +struct RmeGuest {ConfidentialGuestSupport parent_obj; +Notifier rom_load_notifier; +GSList *ram_regions; }; OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,
@@ -41,6 +52,44 @@ static void rme_vm_state_change(void *opaque, bool running, RunState state)kvm_mark_guest_state_protected (); } +static gint rme_compare_ram_regions (gconstpointer a,gconstpointer b) +{ +const RmeRamRegion *ra = a; +const RmeRamRegion *rb = b; + +g_assert (ra->base != rb->base); +return ra->base < rb->base ?-1 :1 ; +} + +static void rme_rom_load_notify (Notifier *notifier,void *data) +{ +RmeRamRegion *region; +RomLoaderNotifyData *rom = data; + +if (rom->addr ==-1 ) { +/* +* These blobs (ACPI tables) are not loaded into guest RAM at reset. +* Instead the firmware will load them via fw_cfg and measure them +* itself. +*/ +return ; + } + + region =g_new0 (RmeRamRegion,1 ); + region->base = rom->addr; + region->size = rom->len; + region->data = rom->data; + +/* +* The Realm Initial Measurement (RIM) depends on the order in which we +* initialize and populate the RAM regions. To help a verifier +* independently calculate the RIM, sort regions by GPA. +*/ + rme_guest->ram_regions =g_slist_insert_sorted (rme_guest->ram_regions, + region, + rme_compare_ram_regions); +} +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) {KVMState *s =KVM_STATE (current_accel ());
@@ -58,6 +107,9 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)error_setg (&rme_mig_blocker,"RME: migration is not implemented" );migrate_add_blocker (&rme_mig_blocker, &error_fatal); + rme_guest->rom_load_notifier.notify = rme_rom_load_notify; +rom_add_load_notifier (&rme_guest->rom_load_notifier); +/* * The realm activation is done last, when the VM starts, after all images * have been loaded and all vcpus finalized.
Signature · 1 line
2.43.0
Re: [RFC v4 10/24] target/arm/kvm-rme: Keep track of images loaded in Realm memory
Quoted 52 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM).
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)target/arm/kvm-rme.c +16
-0@@ -10,6 +10,7 @@#include "hw/core/boards.h" #include "hw/core/cpu.h" +#include "hw/core/loader.h" #include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" @@ -22,8 +23,18 @@#define TYPE_RME_GUEST "rme-guest" OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) +#define RME_PAGE_SIZE qemu_real_host_page_size() + +typedef struct { +hwaddr base; +hwaddr size; +uint8_t *data; +}RmeRamRegion ; +struct RmeGuest {ConfidentialGuestSupport parent_obj; +Notifier rom_load_notifier; +GSList *ram_regions; }; OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,@@ -41,6 +52,44 @@ static void rme_vm_state_change(void *opaque, bool running, RunState state)kvm_mark_guest_state_protected (); } +static gint rme_compare_ram_regions (gconstpointer a,gconstpointer b) +{ +const RmeRamRegion *ra = a; +const RmeRamRegion *rb = b; +
target/arm/kvm-rme.c static void rme_vm_state_change(void *opaque, bool running, RunState state) · line 69
Quoted 10 lines
target/arm/kvm-rme.c +10
-0+g_assert (ra->base != rb->base); +return ra->base < rb->base ?-1 :1 ; +} + +static void rme_rom_load_notify (Notifier *notifier,void *data) +{ +RmeRamRegion *region; +RomLoaderNotifyData *rom = data; + +if (rom->addr ==-1 ) {
Are these entries also added via the rom_reset() path in the previous patch? If so, wouldn't it be better to filter them out there?
Also, if that's where these entries are added, then it looks like we might call address_space_flush_icache_range() with this -1 addr before adding it to the notifier list. Is that expected?
-Mike
Quoted 40 lines
target/arm/kvm-rme.c +26
-0+/* +* These blobs (ACPI tables) are not loaded into guest RAM at reset. +* Instead the firmware will load them via fw_cfg and measure them +* itself. +*/ +return ; + } + + region =g_new0 (RmeRamRegion,1 ); + region->base = rom->addr; + region->size = rom->len; + region->data = rom->data; + +/* +* The Realm Initial Measurement (RIM) depends on the order in which we +* initialize and populate the RAM regions. To help a verifier +* independently calculate the RIM, sort regions by GPA. +*/ + rme_guest->ram_regions =g_slist_insert_sorted (rme_guest->ram_regions, + region, + rme_compare_ram_regions); +} +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) {KVMState *s =KVM_STATE (current_accel ());@@ -58,6 +107,9 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)error_setg (&rme_mig_blocker,"RME: migration is not implemented" );migrate_add_blocker (&rme_mig_blocker, &error_fatal); + rme_guest->rom_load_notifier.notify = rme_rom_load_notify; +rom_add_load_notifier (&rme_guest->rom_load_notifier); +/* * The realm activation is done last, when the VM starts, after all images * have been loaded and all vcpus finalized. Signature · 1 line
2.43.0
Re: [RFC v4 10/24] target/arm/kvm-rme: Keep track of images loaded in Realm memory
Hi Michael - thanks for taking the time to review this work.
Quoted 58 lines · Michael Roth
Quoted 57 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM).
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)target/arm/kvm-rme.c +21
-0@@ -10,6 +10,7 @@#include "hw/core/boards.h" #include "hw/core/cpu.h" +#include "hw/core/loader.h" #include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" @@ -22,8 +23,18 @@#define TYPE_RME_GUEST "rme-guest" OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) +#define RME_PAGE_SIZE qemu_real_host_page_size() + +typedef struct { +hwaddr base; +hwaddr size; +uint8_t *data; +}RmeRamRegion ; +struct RmeGuest {ConfidentialGuestSupport parent_obj; +Notifier rom_load_notifier; +GSList *ram_regions; }; OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,@@ -41,6 +52,44 @@ static void rme_vm_state_change(void *opaque, bool running, RunState state)kvm_mark_guest_state_protected (); } +static gint rme_compare_ram_regions (gconstpointer a,gconstpointer b) +{ +const RmeRamRegion *ra = a; +const RmeRamRegion *rb = b; + +g_assert (ra->base != rb->base); +return ra->base < rb->base ?-1 :1 ; +} + +static void rme_rom_load_notify (Notifier *notifier,void *data)
Quoted 8 lines
target/arm/kvm-rme.c static void rme_vm_state_change(void *opaque, bool running, RunState state) · line 69
Quoted 5 lines
target/arm/kvm-rme.c +5
-0+{ +RmeRamRegion *region; +RomLoaderNotifyData *rom = data; + +if (rom->addr ==-1 ) {Are these entries also added via the
rom_reset()path in the previous patch? If so, wouldn't it be better to filter them out there?
Duly noted. I will also wrap the previous patch into this one.
Quoted 4 lines
Also, if that's where these entries are added, then it looks like we might call
address_space_flush_icache_range()with this -1 addr before adding it to the notifier list. Is that expected?
Function address_space_flush_icache_range() is indeed called with @rom->addr set to -1 (0xffffffffffffffff). Since this address is not accessible, the inner loop of the function skips over the entire Rom area without ever calling flush_idcache_range().
Regards,
Mathieu
Quoted 43 lines
-Mike
Quoted 40 lines
target/arm/kvm-rme.c +26
-0+/* +* These blobs (ACPI tables) are not loaded into guest RAM at reset. +* Instead the firmware will load them via fw_cfg and measure them +* itself. +*/ +return ; + } + + region =g_new0 (RmeRamRegion,1 ); + region->base = rom->addr; + region->size = rom->len; + region->data = rom->data; + +/* +* The Realm Initial Measurement (RIM) depends on the order in which we +* initialize and populate the RAM regions. To help a verifier +* independently calculate the RIM, sort regions by GPA. +*/ + rme_guest->ram_regions =g_slist_insert_sorted (rme_guest->ram_regions, + region, + rme_compare_ram_regions); +} +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) {KVMState *s =KVM_STATE (current_accel ());@@ -58,6 +107,9 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)error_setg (&rme_mig_blocker,"RME: migration is not implemented" );migrate_add_blocker (&rme_mig_blocker, &error_fatal); + rme_guest->rom_load_notifier.notify = rme_rom_load_notify; +rom_add_load_notifier (&rme_guest->rom_load_notifier); +/* * The realm activation is done last, when the VM starts, after all images * have been loaded and all vcpus finalized. Signature · 1 line
2.43.0
Re: [RFC v4 10/24] target/arm/kvm-rme: Keep track of images loaded in Realm memory
In reply to Mathieu PoirierQuoted 26 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM).
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)target/arm/kvm-rme.c +1
-0@@ -10,6 +10,7 @@#include "hw/core/boards.h" #include "hw/core/cpu.h" +#include "hw/core/loader.h" #include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" @@ -22,8 +23,18 @@#define TYPE_RME_GUEST "rme-guest"
target/arm/kvm-rme.c line 33
Quoted 10 lines
target/arm/kvm-rme.c +8
-0OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) +#define RME_PAGE_SIZE qemu_real_host_page_size() + +typedef struct { +hwaddr base; +hwaddr size; +uint8_t *data; +}RmeRamRegion ; +
This is the equivalent to 'RomLoaderNotifyData' defined in PATCH[09/24]. We may use 'RomLoaderNotifyData' if it can be renamed to reflect its purpose, no need to define an identical structure.
Quoted 53 lines
target/arm/kvm-rme.c +40
-0struct RmeGuest {ConfidentialGuestSupport parent_obj; +Notifier rom_load_notifier; +GSList *ram_regions; }; OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,@@ -41,6 +52,44 @@ static void rme_vm_state_change(void *opaque, bool running, RunState state)kvm_mark_guest_state_protected (); } +static gint rme_compare_ram_regions (gconstpointer a,gconstpointer b) +{ +const RmeRamRegion *ra = a; +const RmeRamRegion *rb = b; + +g_assert (ra->base != rb->base); +return ra->base < rb->base ?-1 :1 ; +} + +static void rme_rom_load_notify (Notifier *notifier,void *data) +{ +RmeRamRegion *region; +RomLoaderNotifyData *rom = data; + +if (rom->addr ==-1 ) { +/* +* These blobs (ACPI tables) are not loaded into guest RAM at reset. +* Instead the firmware will load them via fw_cfg and measure them +* itself. +*/ +return ; + } + + region =g_new0 (RmeRamRegion,1 ); + region->base = rom->addr; + region->size = rom->len; + region->data = rom->data; + +/* +* The Realm Initial Measurement (RIM) depends on the order in which we +* initialize and populate the RAM regions. To help a verifier +* independently calculate the RIM, sort regions by GPA. +*/ + rme_guest->ram_regions =g_slist_insert_sorted (rme_guest->ram_regions, + region, + rme_compare_ram_regions); +} +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) {KVMState *s =KVM_STATE (current_accel ());
target/arm/kvm-rme.c static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp) · line 115
Quoted 9 lines
target/arm/kvm-rme.c +3
-0@@ -58,6 +107,9 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)error_setg (&rme_mig_blocker,"RME: migration is not implemented" );migrate_add_blocker (&rme_mig_blocker, &error_fatal); + rme_guest->rom_load_notifier.notify = rme_rom_load_notify; +rom_add_load_notifier (&rme_guest->rom_load_notifier); +/* * The realm activation is done last, when the VM starts, after all images * have been loaded and all vcpus finalized.
Thanks,
Gavin
Re: [RFC v4 10/24] target/arm/kvm-rme: Keep track of images loaded in Realm memory
Quoted 31 lines · Gavin Shan
Quoted 30 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM).
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)target/arm/kvm-rme.c +5
-0@@ -10,6 +10,7 @@#include "hw/core/boards.h" #include "hw/core/cpu.h" +#include "hw/core/loader.h" #include "kvm_arm.h" #include "migration/blocker.h" #include "qapi/error.h" @@ -22,8 +23,18 @@#define TYPE_RME_GUEST "rme-guest" OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) +#define RME_PAGE_SIZE qemu_real_host_page_size() + +typedef struct { + hwaddr base;
Quoted 9 lines
target/arm/kvm-rme.c line 33
Quoted 4 lines
target/arm/kvm-rme.c +4
-0+hwaddr size; +uint8_t *data; +} RmeRamRegion; +This is the equivalent to 'RomLoaderNotifyData' defined in PATCH[09/24]. We may use 'RomLoaderNotifyData' if it can be renamed to reflect its purpose, no need to define an identical structure.
I ended up using 'RomLoaderNotifyData' in kvm-rme.c instead of 'RmeRamRegion'.
Quoted 63 lines
Quoted 51 lines
target/arm/kvm-rme.c +40
-0struct RmeGuest {ConfidentialGuestSupport parent_obj; +Notifier rom_load_notifier; +GSList *ram_regions; }; OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,@@ -41,6 +52,44 @@ static void rme_vm_state_change(void *opaque, bool running, RunState state)kvm_mark_guest_state_protected (); } +static gint rme_compare_ram_regions (gconstpointer a,gconstpointer b) +{ +const RmeRamRegion *ra = a; +const RmeRamRegion *rb = b; + +g_assert (ra->base != rb->base); +return ra->base < rb->base ?-1 :1 ; +} + +static void rme_rom_load_notify (Notifier *notifier,void *data) +{ +RmeRamRegion *region; +RomLoaderNotifyData *rom = data; + +if (rom->addr ==-1 ) { +/* +* These blobs (ACPI tables) are not loaded into guest RAM at reset. +* Instead the firmware will load them via fw_cfg and measure them +* itself. +*/ +return ; + } + + region =g_new0 (RmeRamRegion,1 ); + region->base = rom->addr; + region->size = rom->len; + region->data = rom->data; + +/* +* The Realm Initial Measurement (RIM) depends on the order in which we +* initialize and populate the RAM regions. To help a verifier +* independently calculate the RIM, sort regions by GPA. +*/ + rme_guest->ram_regions =g_slist_insert_sorted (rme_guest->ram_regions, + region, + rme_compare_ram_regions); +} +static int kvm_arm_rme_init (ConfidentialGuestSupport *cgs,Error **errp) {KVMState *s =KVM_STATE (current_accel ());target/arm/kvm-rme.c static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp) · line 114
Quoted 8 lines
target/arm/kvm-rme.c +3
-0@@ -58,6 +107,9 @@ static int kvm_arm_rme_init(ConfidentialGuestSupport *cgs, Error **errp)error_setg (&rme_mig_blocker,"RME: migration is not implemented" );migrate_add_blocker (&rme_mig_blocker, &error_fatal); + rme_guest->rom_load_notifier.notify = rme_rom_load_notify; +rom_add_load_notifier (&rme_guest->rom_load_notifier); +/* * The realm activation is done last, when the VM starts, after all images * have been loaded and all vcpus finalized. Thanks,
Gavin
RFC v4 11/24 target/arm/kvm-rme: Populate Realm with runtime images
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)
target/arm/kvm-rme.c +76 -0
@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h"
@@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer; +hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ()); + +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret; +} + +static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }
Signature · 1 line
2.43.0
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 29 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +2
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range(const RmeRamRegion *region, bool measure,
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 10 lines
target/arm/kvm-rme.c +10
-0+ Error **errp) +{ +int ret; +void *buffer; +hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());
s/qemu_real_host_page_size()/RME_PAGE_SIZE
Quoted 34 lines
target/arm/kvm-rme.c +34
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { + error_setg_errno(errp, -ret, + "failed to populate realm [0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx")",
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 101
Quoted 10 lines
target/arm/kvm-rme.c +10
-0+ start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret; +} +
I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when RME_PAGE_SIZE is 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe for kvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.
Quoted 19 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {return ; }
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 130
Quoted 10 lines
target/arm/kvm-rme.c +6
-0+g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }
Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
I think that IPA base and source_uaddr should be host page size aligned.
Quoted 37 lines
Quoted 37 lines
target/arm/kvm-rme.c +37
-0+if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + }
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 101
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+ +qemu_vfree (buffer); + +return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example,
I don't think they should be allowed either.
Quoted 8 lines
the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
Yes, given how current code is written this is wrong.
Quoted 2 lines
- In "
memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.
I can't follow you here. We are filling a temporary buffer so that KVM can populate from it ?
Anyway - we should refactor the code to discard regions unaligned to host page size.
Thanks,
Lorenzo
Quoted 31 lines
Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
In reply to Gavin ShanQuoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
I refactored this function in V5 [1], along with the above declarations.
[1]. https://lore.kernel.org/kvm/[email protected]/
Quoted 43 lines
Quoted 43 lines
target/arm/kvm-rme.c +42
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret;
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 99
Quoted 2 lines
target/arm/kvm-rme.c +2
-0+} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.
To make sure I understand your point, please expand on what would be an unaligned regions. In your example, [0 128KB] is aligned on 64KB boundries.
Quoted 4 lines
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
I'm confused. ROUND_UP(64KB+4KB, 64KB) would be 128KB. What am I missing?
Quoted 2 lines
- In "
memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.
I agree with you. That part was refactored in V5 [1]:
memcpy(buffer + (base - start), region->data, region->size);
Quoted 32 lines
Quoted 18 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 102 lines · Mathieu Poirier
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
I refactored this function in V5 [1], along with the above declarations.
[1]. https://lore.kernel.org/kvm/[email protected]/
Quoted 43 lines
Quoted 43 lines
target/arm/kvm-rme.c +42
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 99
Quoted 2 lines
target/arm/kvm-rme.c +2
-0+} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.To make sure I understand your point, please expand on what would be an unaligned regions. In your example, [0 128KB] is aligned on 64KB boundries.
Quoted 1 line
Quoted 6 lines
Quoted 3 lines
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
I'm confused.
ROUND_UP(64KB+4KB, 64KB)would be 128KB. What am I missing?
ROUND_UP(64KB+4KB, 64KB) corresponds to ROUND_UP(size+base, 64KB) for local variable @end instead of @aligned_size. @aligned_size is calculated as ROUND_UP(64KB, 64KB) and the output is still 64KB.
Quoted 36 lines
Quoted 2 lines
- In "
memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.I agree with you. That part was refactored in V5 [1]:
memcpy(buffer + (base - start), region->data, region->size);Quoted 29 lines
Quoted 28 lines
target/arm/kvm-rme.c +20
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }
Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 105 lines · Gavin Shan
Quoted 104 lines · Mathieu Poirier
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
I refactored this function in V5 [1], along with the above declarations.
[1]. https://lore.kernel.org/kvm/[email protected]/
Quoted 43 lines
Quoted 43 lines
target/arm/kvm-rme.c +42
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 99
Quoted 2 lines
target/arm/kvm-rme.c +2
-0+} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.To make sure I understand your point, please expand on what would be an unaligned regions. In your example, [0 128KB] is aligned on 64KB boundries.
Quoted 3 lines
Even if the unaligned regions are allowed, they seem not well handled.
Quoted 15 lines
Quoted 4 lines
Quoted 1 line
- @aligned_size is still 64KB instead of the 128KB ?
I'm confused.
ROUND_UP(64KB+4KB, 64KB)would be 128KB. What am I missing?
ROUND_UP(64KB+4KB, 64KB)corresponds toROUND_UP(size+base, 64KB)for local variable @end instead of @aligned_size. @aligned_size is calculated asROUND_UP(64KB, 64KB)and the output is still 64KB.Quoted 6 lines
Quoted 2 lines
- In "
memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.I agree with you. That part was refactored in V5 [1]:
memcpy(buffer + (base - start), region->data, region->size);
I misunderstood Gavin's comment on this, so the issue isn't the memcpy per-se (that was the impression I had) but rather in relation to using the buffer in
kvm_vm_ioctl(kvm_state, KVM_ARM_RMI_POPULATE, &populate_args, 0);
with populate_args.base = start (that was aligned down).
Thanks,
Lorenzo
Quoted 33 lines
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
target/arm/kvm-rme.c +15
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp);Quoted 8 lines
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 7 lines
target/arm/kvm-rme.c +5
-0+g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
In reply to Gavin ShanQuoted 105 lines · Gavin Shan
Quoted 104 lines · Mathieu Poirier
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
I refactored this function in V5 [1], along with the above declarations.
[1]. https://lore.kernel.org/kvm/[email protected]/
Quoted 43 lines
Quoted 43 lines
target/arm/kvm-rme.c +42
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); + +return ret;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 99
Quoted 2 lines
target/arm/kvm-rme.c +2
-0+} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE). I guess we probably just reject unaligned regions if they're not expected.To make sure I understand your point, please expand on what would be an unaligned regions. In your example, [0 128KB] is aligned on 64KB boundries.
Quoted 3 lines
Even if the unaligned regions are allowed, they seem not well handled.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
- @aligned_size is still 64KB instead of the 128KB ?
I'm confused.
ROUND_UP(64KB+4KB, 64KB)would be 128KB. What am I missing?
ROUND_UP(64KB+4KB, 64KB)corresponds toROUND_UP(size+base, 64KB)for local variable @end instead of @aligned_size. @aligned_size is calculated asROUND_UP(64KB, 64KB)and the output is still 64KB.
Thanks for the explanation - that part was also addressed in V5. I will spin-off a proper V6 where we can continue the discussion on updated code.
Quoted 41 lines
Quoted 37 lines
Quoted 3 lines
- In "
memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.I agree with you. That part was refactored in V5 [1]:
memcpy(buffer + (base - start), region->data, region->size);Quoted 29 lines
Quoted 28 lines
target/arm/kvm-rme.c +20
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
In reply to Gavin ShanQuoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be qemu_real_host_page_size(), KVM configures it that way.
Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +
Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 69
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).
Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
Thanks,
Lorenzo
Quoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 95 lines · Lorenzo Pieralisi
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be
qemu_real_host_page_size(), KVM configures it that way.Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 69
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).
Quoted 6 lines
Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 64KB host. With the alignment considered, we're populating [0 64KB] for region [0 4KB], and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed by TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is overwritten by the second population.
Thanks,
Gavin
Quoted 43 lines
Thanks,
LorenzoQuoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 103 lines · Gavin Shan
Quoted 95 lines · Lorenzo Pieralisi
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be
qemu_real_host_page_size(), KVM configures it that way.Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 69
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).Quoted 6 lines
Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
Quoted 5 lines
For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 64KB host. With the alignment considered, we're populating [0 64KB] for region [0 4KB], and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed by TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is overwritten by the second population.
It is not allowed by the RMM and it is a VMM bug that we have to prevent.
Thanks,
Lorenzo
Quoted 47 lines
Thanks,
GavinQuoted 43 lines
Thanks,
LorenzoQuoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 104 lines · Lorenzo Pieralisi
Quoted 103 lines · Gavin Shan
Quoted 101 lines · Lorenzo Pieralisi
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be
qemu_real_host_page_size(), KVM configures it that way.Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 69
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
Quoted 8 lines
Quoted 5 lines
For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 64KB host. With the alignment considered, we're populating [0 64KB] for region [0 4KB], and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed by TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is overwritten by the second population.
It is not allowed by the RMM and it is a VMM bug that we have to prevent.
Ok, thanks for your confirm. It's why I asked if we ever see an unaligned Rom region. If all Rom regions are aligned to host page size, then we needn't to handle the unaligned Rom regions in rme_populate_range(). Otherwise, we need come up with a solution to address the issue.
The solution would be to generate a temporary region list based on the existing Rom region list. For each region in the temporary list, its start/size are well aligned to host page size, and the temporary buffer is allocated, and the data is properly copied over from the original Rom region. The population is done based on the temporary list. For example, we need to have [0 64kb], [128kb 192kb] regions in the temporary list if we have Rom region [0 1kb], [4kb 5kb] [16kb 17kb], [132kb 133kb], [136kb 140kb]. The host page size is assumed to be 64kb in the example.
[0 64kb] covers [0 1kb], [4kb 5kb] [16kb 17kb] [128kb 192kb] covers [132kb 133kb], [136kb 140kb]
Thanks,
Gavin
Quoted 51 lines
Thanks,
LorenzoQuoted 47 lines
Thanks,
GavinQuoted 43 lines
Thanks,
LorenzoQuoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to[4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 127 lines · Gavin Shan
Quoted 104 lines · Lorenzo Pieralisi
Quoted 103 lines · Gavin Shan
Quoted 101 lines · Lorenzo Pieralisi
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 57
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be
qemu_real_host_page_size(), KVM configures it that way.Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 69
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
Quoted 8 lines
Quoted 5 lines
For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 64KB host. With the alignment considered, we're populating [0 64KB] for region [0 4KB], and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed by TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is overwritten by the second population.
It is not allowed by the RMM and it is a VMM bug that we have to prevent.
Ok, thanks for your confirm. It's why I asked if we ever see an unaligned Rom region. If all Rom regions are aligned to host page size, then we needn't to handle the unaligned Rom regions in
rme_populate_range(). Otherwise, we need come up with a solution to address the issue.The solution would be to generate a temporary region list based on the existing Rom region list. For each region in the temporary list, its start/size are well aligned to host page size, and the temporary buffer is allocated, and the data is properly copied over from the original Rom region. The population is done based on the temporary list. For example, we need to have [0 64kb], [128kb 192kb] regions in the temporary list if we have Rom region [0 1kb], [4kb 5kb] [16kb 17kb], [132kb 133kb], [136kb 140kb]. The host page size is assumed to be 64kb in the example.
Quoted 2 lines
[0 64kb] covers [0 1kb], [4kb 5kb] [16kb 17kb] [128kb 192kb] covers [132kb 133kb], [136kb 140kb]
That's exactly what needs to be done.
Thanks,
Lorenzo
Quoted 55 lines
Thanks,
GavinQuoted 51 lines
Thanks,
LorenzoQuoted 47 lines
Thanks,
GavinQuoted 43 lines
Thanks,
LorenzoQuoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to[4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 129
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
Re: [RFC v4 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Quoted 128 lines · Lorenzo Pieralisi
Quoted 127 lines · Gavin Shan
Quoted 104 lines · Lorenzo Pieralisi
Quoted 103 lines · Gavin Shan
Quoted 101 lines · Lorenzo Pieralisi
Quoted 32 lines · Gavin Shan
Quoted 31 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Lorenzo Pieralisi <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)target/arm/kvm-rme.c +6
-0@@ -15,6 +15,7 @@#include "migration/blocker.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "system/confidential-guest-support.h" #include "system/kvm.h" @@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST,static RmeGuest *rme_guest; +static int rme_populate_range (const RmeRamRegion *region,bool measure, +Error **errp) +{ +int ret; +void *buffer;Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 55
Quoted 6 lines
target/arm/kvm-rme.c +6
-0+hwaddr size = region->size; +hwaddr base = region->base; +hwaddr start =QEMU_ALIGN_DOWN (base,RME_PAGE_SIZE ); +hwaddr end =QEMU_ALIGN_UP (base + size,RME_PAGE_SIZE ); +struct kvm_arm_rmi_populate populate_args; +size_t aligned_size =ROUND_UP (region->size,qemu_real_host_page_size ());s/qemu_real_host_page_size()/RME_PAGE_SIZE
It will always have to be
qemu_real_host_page_size(), KVM configures it that way.Quoted 41 lines
Quoted 41 lines
target/arm/kvm-rme.c +41
-0+ +if (!region->data) { +return -ENODEV ; + } + + ret =kvm_set_memory_attributes_private (start, end - start); +if (ret) { +error_report ("RME: failed to configure initial" +"private guest memory" ); +return ret; + } + +/* Allocate page-aligned memory */ + buffer =qemu_memalign (qemu_real_host_page_size (), aligned_size); + +if (!buffer) { +return -ENOMEM ; + } + +memset (buffer,0 , aligned_size); +memcpy (buffer, region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate ) { + .base = start, + .size = end - start, + .source_uaddr = (uintptr_t )buffer, + .flags = measure ?KVM_ARM_RMI_POPULATE_FLAGS_MEASURE :0 , + }; + +while (populate_args.size >0 ) { + ret =kvm_vm_ioctl (kvm_state,KVM_ARM_RMI_POPULATE , &populate_args,0 ); +if (ret) { +error_setg_errno (errp, -ret, +"failed to populate realm [0x%" HWADDR_PRIx", 0x%" HWADDR_PRIx")" , + start, end); +break ; + } + } + +qemu_vfree (buffer); +Quoted 8 lines
target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 99
Quoted 3 lines
target/arm/kvm-rme.c +3
-0+return ret; +} +I doubt that the unaligned regions (RmeRamRegion) are allowed. For example, the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when
RME_PAGE_SIZEis 64KB. The question is how do we know the added regions due to the alignment ([0 4KB] and [64KB+4KB 128KB]) are safe forkvm_vm_ioctl(KVM_ARM_RMI_POPULATE).Getting back to this because it is important. Can you define "safe" here ?
I think it is VMM's role to load with the required alignment and make sure it does not double populate (that is anyway prevented by KVM), what was your concern here to make sure we are in agreement ?
Quoted 8 lines
Quoted 5 lines
For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 64KB host. With the alignment considered, we're populating [0 64KB] for region [0 4KB], and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed by TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is overwritten by the second population.
It is not allowed by the RMM and it is a VMM bug that we have to prevent.
Ok, thanks for your confirm. It's why I asked if we ever see an unaligned Rom region. If all Rom regions are aligned to host page size, then we needn't to handle the unaligned Rom regions in
rme_populate_range(). Otherwise, we need come up with a solution to address the issue.The solution would be to generate a temporary region list based on the existing Rom region list. For each region in the temporary list, its start/size are well aligned to host page size, and the temporary buffer is allocated, and the data is properly copied over from the original Rom region. The population is done based on the temporary list. For example, we need to have [0 64kb], [128kb 192kb] regions in the temporary list if we have Rom region [0 1kb], [4kb 5kb] [16kb 17kb], [132kb 133kb], [136kb 140kb]. The host page size is assumed to be 64kb in the example.
Quoted 5 lines
Quoted 2 lines
[0 64kb] covers [0 1kb], [4kb 5kb] [16kb 17kb] [128kb 192kb] covers [132kb 133kb], [136kb 140kb]That's exactly what needs to be done.
That is also what I understood. My goal is to present this enhancement in RFCv6.
Quoted 58 lines
Thanks,
LorenzoQuoted 55 lines
Thanks,
GavinQuoted 51 lines
Thanks,
LorenzoQuoted 47 lines
Thanks,
GavinQuoted 43 lines
Thanks,
LorenzoQuoted 39 lines
I guess we probably just reject unaligned regions if they're not expected.
Even if the unaligned regions are allowed, they seem not well handled.
- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be copied to[4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.Quoted 17 lines
target/arm/kvm-rme.c +14
-0+static void rme_populate_ram_region (gpointer data,gpointer err) +{ +Error **errp = err; +const RmeRamRegion *region = data; + +if (*errp) { +return ; + } + +rme_populate_range (region,/* measure */ true, errp); +} +static void rme_vm_state_change (void *opaque,bool running,RunState state) { +Error *errp =NULL ; +if (!running) {target/arm/kvm-rme.c OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, · line 126
Quoted 10 lines
target/arm/kvm-rme.c +6
-0return ; } +g_slist_foreach (rme_guest->ram_regions, rme_populate_ram_region, &errp); +g_slist_free_full (g_steal_pointer (&rme_guest->ram_regions), g_free); +if (errp) { +return ; + } +kvm_mark_guest_state_protected (); }Thanks,
Gavin
RFC v4 12/24 target/arm/cpu: Set number of breakpoints and watchpoints in KVM
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Add "num-breakpoints" and "num-watchpoints" CPU parameters to configure the debug features that KVM presents to the guest. The KVM vCPU configuration is modified by calling SET_ONE_REG on the ID register.
This is needed for Realm VMs, whose parameters include breakpoints and watchpoints, and influence the Realm Initial Measurement.
--- target/arm/arm-qmp-cmds.c | 1 + target/arm/cpu.h | 4 ++ target/arm/cpu64.c | 81 +++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 56 +++++++++++++++++++++++++++ 4 files changed, 142 insertions(+)
target/arm/arm-qmp-cmds.c +1 -0
@@ -76,6 +76,7 @@ static const char *cpu_model_advertised_features[] = {"sve1408" ,"sve1536" ,"sve1664" ,"sve1792" ,"sve1920" ,"sve2048" ,"kvm-no-adjvtime" ,"kvm-steal-time" ,"pauth" ,"pauth-impdef" ,"pauth-qarma3" ,"pauth-qarma5" , +"num-breakpoints" ,"num-watchpoints" ,NULL };
target/arm/cpu.h +4 -0
@@ -1173,6 +1173,10 @@ struct ArchCPU {/* Generic timer counter frequency, in Hz */ uint64_t gt_cntfrq_hz; + +/* Allows to override the default configuration */ +uint8_t num_bps; +uint8_t num_wps; }; typedef struct ARMCPUInfo {
target/arm/cpu64.c +81 -0
93 lines not on this page · raw message
target/arm/kvm.c +56 -0
68 lines not on this page · raw message
Signature · 1 line
2.43.0
Re: [RFC v4 12/24] target/arm/cpu: Set number of breakpoints and watchpoints in KVM
Quoted 35 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add "num-breakpoints" and "num-watchpoints" CPU parameters to configure the debug features that KVM presents to the guest. The KVM vCPU configuration is modified by calling
SET_ONE_REGon the ID register.This is needed for Realm VMs, whose parameters include breakpoints and watchpoints, and influence the Realm Initial Measurement.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/arm-qmp-cmds.c | 1 + target/arm/cpu.h | 4 ++ target/arm/cpu64.c | 81 +++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 56 +++++++++++++++++++++++++++ 4 files changed, 142 insertions(+)target/arm/arm-qmp-cmds.c +1
-0@@ -76,6 +76,7 @@ static const char *cpu_model_advertised_features[] = {"sve1408" ,"sve1536" ,"sve1664" ,"sve1792" ,"sve1920" ,"sve2048" ,"kvm-no-adjvtime" ,"kvm-steal-time" ,"pauth" ,"pauth-impdef" ,"pauth-qarma3" ,"pauth-qarma5" , +"num-breakpoints" ,"num-watchpoints" ,NULL };target/arm/cpu.h +0
-0
target/arm/cpu.h struct ArchCPU { · line 1181
Quoted 9 lines
target/arm/cpu.h +4
-0@@ -1173,6 +1173,10 @@ struct ArchCPU {/* Generic timer counter frequency, in Hz */ uint64_t gt_cntfrq_hz; + +/* Allows to override the default configuration */ +uint8_t num_bps; +uint8_t num_wps; };
May improve the comments to indicate: these two fields are only needed by RME-vCPUs.
/* Override the default configuration, only for RME vCPUs */
Quoted 64 lines
target/arm/cpu.h +0
-0typedef struct ARMCPUInfo {target/arm/cpu64.c +55
-0@@ -666,6 +666,86 @@ void aarch64_add_pauth_properties(Object *obj) } } +#if defined(CONFIG_KVM ) +static void arm_cpu_get_num_wps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); + + val = cpu->num_wps; +if (val ==0 ) { + val =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,WRPS ) +1 ; + } + +visit_type_uint8 (v, name, &val, errp); +} + +static void arm_cpu_set_num_wps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); +uint8_t max_wps =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,WRPS ) +1 ; + +if (!visit_type_uint8 (v, name, &val, errp)) { +return ; + } + +if (val <2 || val > max_wps) { +error_setg (errp,"invalid number of watchpoints" ); +return ; + } + + cpu->num_wps = val; +} + +static void arm_cpu_get_num_bps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); + + val = cpu->num_bps; +if (val ==0 ) { + val =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,BRPS ) +1 ; + } + +visit_type_uint8 (v, name, &val, errp); +} + +static void arm_cpu_set_num_bps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val;
target/arm/cpu64.c void aarch64_add_pauth_properties(Object *obj) · line 733
Quoted 10 lines
target/arm/cpu64.c +10
-0+ARMCPU *cpu =ARM_CPU (obj); +uint8_t max_bps =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,BRPS ) +1 ; + +if (!visit_type_uint8 (v, name, &val, errp)) { +return ; + } + +if (val <2 || val > max_bps) { +error_setg (errp,"invalid number of breakpoints" );
^^^^^
Code alignment issue here.
Quoted 67 lines
target/arm/cpu64.c +16
-0+ return; + } + + cpu->num_bps = val; +} + +static void aarch64_add_kvm_writable_properties (Object *obj) +{ +object_property_add (obj,"num-breakpoints" ,"uint8" , arm_cpu_get_num_bps, + arm_cpu_set_num_bps,NULL ,NULL ); +object_property_add (obj,"num-watchpoints" ,"uint8" , arm_cpu_get_num_wps, + arm_cpu_set_num_wps,NULL ,NULL ); +} +#endif /* CONFIG_KVM */ +void aarch64_cpu_lpa2_finalize (ARMCPU *cpu,Error **errp) {uint64_t t;@@ -807,6 +887,7 @@ void aarch64_host_initfn(Object *obj)kvm_arm_set_cpreg_mig_tolerances (cpu);kvm_arm_set_cpu_features_from_host (cpu);aarch64_add_sve_properties (obj); +aarch64_add_kvm_writable_properties (obj);#elif defined(CONFIG_HVF )hvf_arm_set_cpu_features_from_host (cpu);#elif defined(CONFIG_WHPX )target/arm/kvm.c +33
-0@@ -912,6 +912,56 @@ out:return ret; } +#define KVM_REG_ARM_ID_AA64DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 5, 0) + +static void kvm_arm_configure_aa64dfr0 (ARMCPU *cpu) +{ +int ret; +uint64_t val, newval; +CPUState *cs =CPU (cpu); + +if (!cpu->num_bps && !cpu->num_wps) { +return ; + } + + newval = cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ]; +if (cpu->num_bps) { +uint64_t ctx_cmps =FIELD_EX64 (newval,ID_AA64DFR0 ,CTX_CMPS ); + +/* CTX_CMPs is never greater than BRPs */ + ctx_cmps =MIN (ctx_cmps, cpu->num_bps -1 ); + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,BRPS , cpu->num_bps -1 ); + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,CTX_CMPS , ctx_cmps); + } +if (cpu->num_wps) { + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,WRPS , cpu->num_wps -1 ); + } + ret =kvm_set_one_reg (cs,KVM_REG_ARM_ID_AA64DFR0_EL1 , &newval); +if (ret) { +error_report ("Failed to set KVM_REG_ARM_ID_AA64DFR0_EL1" ); +return ; + } + +/* +* Check if the write succeeded. KVM does offer the writable mask for this +* register, but this way we also check if the value we wrote was sane.
target/arm/kvm.c out: · line 957
Quoted 10 lines
target/arm/kvm.c +10
-0+*/ + ret =kvm_get_one_reg (cs,KVM_REG_ARM_ID_AA64DFR0_EL1 , &val); +if (ret) { +error_report ("Failed to get KVM_REG_ARM_ID_AA64DFR0_EL1" ); +return ; + } + +if (val != newval) { +error_report ("Failed to update KVM_REG_ARM_ID_AA64DFR0_EL1" ); + }
These two checks could be combined since we needn't to know how the write has been failing.
if (ret || val != newval) {
error_report("Failed to update KVM_REG_ARM_ID_AA64DFR0_EL1");
}Quoted 11 lines
target/arm/kvm.c +7
-0+} + +static void kvm_arm_configure_vcpu_regs (ARMCPU *cpu) +{ +kvm_arm_configure_aa64dfr0 (cpu); +} +/** * kvm_arm_cpreg_level: * @regidx: KVM register index
target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1184
Quoted 7 lines
target/arm/kvm.c +4
-0@@ -1128,6 +1178,12 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)fprintf (stderr,"kvm_arm_vcpu_init failed: %s\n" ,strerror (-ret));abort (); } + +/* +* Before loading the KVM values into CPUState, update the KVM configuration +*/
Can be squeezed into one line:
/* Update KVM state before it's loaded to CPUState */
target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1186
Quoted 2 lines
target/arm/kvm.c +2
-0+kvm_arm_configure_vcpu_regs (cpu); +
The newly added properties ("num-breakpoints", "num-watchpoints") are only needed by RME-vCPUs, but they're also visible to the normal vCPUs. So do we need to bail without adding the properties if RME isn't supported by the vCPUs in kvm_arm_configure_vcpu_regs() ?
target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1189
Quoted 3 lines
target/arm/kvm.c +0
-0if (!write_kvmstate_to_list (cpu)) {fprintf (stderr,"write_kvmstate_to_list failed\n" );abort ();
Thanks,
Gavin
Re: [RFC v4 12/24] target/arm/cpu: Set number of breakpoints and watchpoints in KVM
Quoted 230 lines · Gavin Shan
Quoted 34 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Add "num-breakpoints" and "num-watchpoints" CPU parameters to configure the debug features that KVM presents to the guest. The KVM vCPU configuration is modified by calling
SET_ONE_REGon the ID register.This is needed for Realm VMs, whose parameters include breakpoints and watchpoints, and influence the Realm Initial Measurement.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- target/arm/arm-qmp-cmds.c | 1 + target/arm/cpu.h | 4 ++ target/arm/cpu64.c | 81 +++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 56 +++++++++++++++++++++++++++ 4 files changed, 142 insertions(+)target/arm/arm-qmp-cmds.c +1
-0@@ -76,6 +76,7 @@ static const char *cpu_model_advertised_features[] = {"sve1408" ,"sve1536" ,"sve1664" ,"sve1792" ,"sve1920" ,"sve2048" ,"kvm-no-adjvtime" ,"kvm-steal-time" ,"pauth" ,"pauth-impdef" ,"pauth-qarma3" ,"pauth-qarma5" , +"num-breakpoints" ,"num-watchpoints" ,NULL };target/arm/cpu.h +0
-0target/arm/cpu.h struct ArchCPU { · line 1179
Quoted 7 lines
target/arm/cpu.h +4
-0@@ -1173,6 +1173,10 @@ struct ArchCPU {/* Generic timer counter frequency, in Hz */ uint64_t gt_cntfrq_hz; + +/* Allows to override the default configuration */ +uint8_t num_bps; +uint8_t num_wps; };May improve the comments to indicate: these two fields are only needed by RME-vCPUs.
/* Override the default configuration, only for RME vCPUs */Quoted 63 lines
target/arm/cpu.h +0
-0typedef struct ARMCPUInfo {target/arm/cpu64.c +55
-0@@ -666,6 +666,86 @@ void aarch64_add_pauth_properties(Object *obj) } } +#if defined(CONFIG_KVM ) +static void arm_cpu_get_num_wps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); + + val = cpu->num_wps; +if (val ==0 ) { + val =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,WRPS ) +1 ; + } + +visit_type_uint8 (v, name, &val, errp); +} + +static void arm_cpu_set_num_wps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); +uint8_t max_wps =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,WRPS ) +1 ; + +if (!visit_type_uint8 (v, name, &val, errp)) { +return ; + } + +if (val <2 || val > max_wps) { +error_setg (errp,"invalid number of watchpoints" ); +return ; + } + + cpu->num_wps = val; +} + +static void arm_cpu_get_num_bps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val; +ARMCPU *cpu =ARM_CPU (obj); + + val = cpu->num_bps; +if (val ==0 ) { + val =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,BRPS ) +1 ; + } + +visit_type_uint8 (v, name, &val, errp); +} + +static void arm_cpu_set_num_bps (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +uint8_t val;target/arm/cpu64.c void aarch64_add_pauth_properties(Object *obj) · line 732
Quoted 10 lines
target/arm/cpu64.c +10
-0+ARMCPU *cpu =ARM_CPU (obj); +uint8_t max_bps =FIELD_EX64 (cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ], +ID_AA64DFR0 ,BRPS ) +1 ; + +if (!visit_type_uint8 (v, name, &val, errp)) { +return ; + } + +if (val <2 || val > max_bps) { +error_setg (errp,"invalid number of breakpoints" );^^^^^Code alignment issue here.
Quoted 66 lines
target/arm/cpu64.c +16
-0+ return; + } + + cpu->num_bps = val; +} + +static void aarch64_add_kvm_writable_properties (Object *obj) +{ +object_property_add (obj,"num-breakpoints" ,"uint8" , arm_cpu_get_num_bps, + arm_cpu_set_num_bps,NULL ,NULL ); +object_property_add (obj,"num-watchpoints" ,"uint8" , arm_cpu_get_num_wps, + arm_cpu_set_num_wps,NULL ,NULL ); +} +#endif /* CONFIG_KVM */ +void aarch64_cpu_lpa2_finalize (ARMCPU *cpu,Error **errp) {uint64_t t;@@ -807,6 +887,7 @@ void aarch64_host_initfn(Object *obj)kvm_arm_set_cpreg_mig_tolerances (cpu);kvm_arm_set_cpu_features_from_host (cpu);aarch64_add_sve_properties (obj); +aarch64_add_kvm_writable_properties (obj);#elif defined(CONFIG_HVF )hvf_arm_set_cpu_features_from_host (cpu);#elif defined(CONFIG_WHPX )target/arm/kvm.c +33
-0@@ -912,6 +912,56 @@ out:return ret; } +#define KVM_REG_ARM_ID_AA64DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 5, 0) + +static void kvm_arm_configure_aa64dfr0 (ARMCPU *cpu) +{ +int ret; +uint64_t val, newval; +CPUState *cs =CPU (cpu); + +if (!cpu->num_bps && !cpu->num_wps) { +return ; + } + + newval = cpu->isar.idregs[ID_AA64DFR0_EL1_IDX ]; +if (cpu->num_bps) { +uint64_t ctx_cmps =FIELD_EX64 (newval,ID_AA64DFR0 ,CTX_CMPS ); + +/* CTX_CMPs is never greater than BRPs */ + ctx_cmps =MIN (ctx_cmps, cpu->num_bps -1 ); + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,BRPS , cpu->num_bps -1 ); + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,CTX_CMPS , ctx_cmps); + } +if (cpu->num_wps) { + newval =FIELD_DP64 (newval,ID_AA64DFR0 ,WRPS , cpu->num_wps -1 ); + } + ret =kvm_set_one_reg (cs,KVM_REG_ARM_ID_AA64DFR0_EL1 , &newval); +if (ret) { +error_report ("Failed to set KVM_REG_ARM_ID_AA64DFR0_EL1" ); +return ; + } + +/* +* Check if the write succeeded. KVM does offer the writable mask for this +* register, but this way we also check if the value we wrote was sane. target/arm/kvm.c out: · line 956
Quoted 10 lines
target/arm/kvm.c +10
-0+*/ + ret =kvm_get_one_reg (cs,KVM_REG_ARM_ID_AA64DFR0_EL1 , &val); +if (ret) { +error_report ("Failed to get KVM_REG_ARM_ID_AA64DFR0_EL1" ); +return ; + } + +if (val != newval) { +error_report ("Failed to update KVM_REG_ARM_ID_AA64DFR0_EL1" ); + }These two checks could be combined since we needn't to know how the write has been failing.
if (ret || val != newval) { error_report("Failed to update KVM_REG_ARM_ID_AA64DFR0_EL1"); }Quoted 11 lines
target/arm/kvm.c +7
-0+} + +static void kvm_arm_configure_vcpu_regs (ARMCPU *cpu) +{ +kvm_arm_configure_aa64dfr0 (cpu); +} +/** * kvm_arm_cpreg_level: * @regidx: KVM register index target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1184
Quoted 7 lines
target/arm/kvm.c +4
-0@@ -1128,6 +1178,12 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)fprintf (stderr,"kvm_arm_vcpu_init failed: %s\n" ,strerror (-ret));abort (); } + +/* +* Before loading the KVM values into CPUState, update the KVM configuration +*/ Can be squeezed into one line:
Quoted 9 lines
/* Update KVM state before it's loaded to CPUState */target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1186
Quoted 2 lines
target/arm/kvm.c +2
-0+kvm_arm_configure_vcpu_regs (cpu); +The newly added properties ("num-breakpoints", "num-watchpoints") are only needed by RME-vCPUs, but they're also visible to the normal vCPUs. So do we need to bail without adding the properties if RME isn't supported by the vCPUs in
kvm_arm_configure_vcpu_regs()?
I added a check for confidential-guest-support in the get() functions of both options. I also addressed the rest of your comments above.
Thanks for the review,
Mathieu
Quoted 7 lines
target/arm/kvm.c void kvm_arm_reset_vcpu(ARMCPU *cpu) · line 1189
Quoted 3 lines
target/arm/kvm.c +0
-0if (!write_kvmstate_to_list (cpu)) {fprintf (stderr,"write_kvmstate_to_list failed\n" );abort ();Thanks,
Gavin
RFC v4 13/24 target/arm/cpu: Set number of PMU counters in KVM
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Add a "num-pmu-counters" CPU parameter to configure the number of counters that KVM presents to the guest. This is needed for Realm VMs, whose parameters include the number of PMU counters and influence the Realm Initial Measurement.
--- target/arm/arm-qmp-cmds.c | 2 +- target/arm/cpu.h | 3 +++ target/arm/cpu64.c | 41 +++++++++++++++++++++++++++++++++++++++ target/arm/kvm.c | 34 ++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-)
target/arm/arm-qmp-cmds.c +1 -1
@@ -76,7 +76,7 @@ static const char *cpu_model_advertised_features[] = {"sve1408" ,"sve1536" ,"sve1664" ,"sve1792" ,"sve1920" ,"sve2048" ,"kvm-no-adjvtime" ,"kvm-steal-time" ,"pauth" ,"pauth-impdef" ,"pauth-qarma3" ,"pauth-qarma5" , -"num-breakpoints" ,"num-watchpoints" , +"num-breakpoints" ,"num-watchpoints" ,"num-pmu-counters" ,NULL };
target/arm/cpu.h +3 -0
@@ -1177,6 +1177,7 @@ struct ArchCPU {/* Allows to override the default configuration */ uint8_t num_bps;uint8_t num_wps; +int8_t num_pmu_ctrs; }; typedef struct ARMCPUInfo {
@@ -2133,6 +2134,8 @@ FIELD(MFAR, FPA, 12, 40) FIELD(MFAR, NSE, 62, 1) FIELD(MFAR, NS, 63, 1) +FIELD(PMCR, N, 11, 5) +QEMU_BUILD_BUG_ON (ARRAY_SIZE (((ARMCPU *)0 )->ccsidr) <=R_V7M_CSSELR_INDEX_MASK );/* If adding a feature bit which corresponds to a Linux ELF
target/arm/cpu64.c +41 -0
53 lines not on this page · raw message
target/arm/kvm.c +34 -0
@@ -957,9 +957,43 @@ static void kvm_arm_configure_aa64dfr0(ARMCPU *cpu) } } +#define KVM_REG_ARM_PMCR_EL0 ARM64_SYS_REG(3, 3, 9, 12, 0) + +static void kvm_arm_configure_pmcr (ARMCPU *cpu) +{ +int ret; +uint64_t val, newval; +CPUState *cs =CPU (cpu); + +if (cpu->num_pmu_ctrs ==-1 ) { +return ; + } + + newval =FIELD_DP64 (cpu->isar.reset_pmcr_el0,PMCR ,N , cpu->num_pmu_ctrs); + ret =kvm_set_one_reg (cs,KVM_REG_ARM_PMCR_EL0 , &newval); +if (ret) { +error_report ("Failed to set KVM_REG_ARM_PMCR_EL0" ); +return ; + } + +/* +* Check if the write succeeded, since older versions of KVM ignore it. +*/ + ret =kvm_get_one_reg (cs,KVM_REG_ARM_PMCR_EL0 , &val); +if (ret) { +error_report ("Failed to get KVM_REG_ARM_PMCR_EL0" ); +return ; + } + +if (val != newval) { +error_report ("Failed to update KVM_REG_ARM_PMCR_EL0" ); + } +} +static void kvm_arm_configure_vcpu_regs (ARMCPU *cpu) {kvm_arm_configure_aa64dfr0 (cpu); +kvm_arm_configure_pmcr (cpu); }/**
Signature · 1 line
2.43.0
RFC v4 14/24 target/arm/cpu: Don't read Realm registers
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
The host cannot access registers of a Realm. Instead of showing all registers as zero in "info registers", display a message about this restriction.
--- target/arm/cpu.c | 5 +++++ 1 file changed, 5 insertions(+)
target/arm/cpu.c +5 -0
@@ -965,6 +965,11 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)const char *ns_status;bool sve; +if (cpu->kvm_rme) { +qemu_fprintf (f,"the CPU registers are confidential to the realm\n" ); +return ; + } +qemu_fprintf (f," PC=%016" PRIx64" " , env->pc);for (i =0 ; i <32 ; i++) {if (i ==31 ) {
Signature · 1 line
2.43.0
RFC v4 15/24 hw/arm/virt: Set proper conduit method for Realms
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
The HVC conduit for PSCI is not supported for Realms, so default to SMC.
--- hw/arm/virt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
hw/arm/virt.c +7 -1
@@ -274,6 +274,11 @@ static const int a15irqmap[] = { [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */ }; +static bool virt_machine_is_confidential (VirtMachineState *vms) +{ +return MACHINE (vms)->cgs; +} +static void create_randomness (MachineState *ms,const char *node) { struct {
@@ -2952,10 +2957,11 @@ static void machvirt_init(MachineState *machine)* if the guest has EL2 then we will use SMC as the conduit, * and otherwise we will use HVC (for backwards compatibility and * because if we're using KVM then we must use HVC). +* Realm guests must also use SMC. */ if (vms->secure && firmware_loaded) { vms->psci_conduit =QEMU_PSCI_CONDUIT_DISABLED ; - }else if (vms->virt) { + }else if (vms->virt ||virt_machine_is_confidential (vms)) { vms->psci_conduit =QEMU_PSCI_CONDUIT_SMC ; }else { vms->psci_conduit =QEMU_PSCI_CONDUIT_HVC ;
Signature · 1 line
2.43.0
RFC v4 16/24 hw/arm/virt: Embed Realm VM type with IPA address space
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Set the Ream VM bit in the IPA address space size when needed.
--- hw/arm/virt.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
hw/arm/virt.c +10 -1
@@ -97,6 +97,8 @@#include "qemu/guest-random.h" #include "hw/watchdog/sbsa_gwdt.h" +#include <linux/kvm.h> +static GlobalProperty arm_virt_compat_defaults[] = { {TYPE_VIRTIO_IOMMU_PCI ,"aw-bits" ,"48" }, };
@@ -4053,9 +4055,12 @@ static int virt_kvm_type(MachineState *ms, const char *type_str)VirtMachineState *vms =VIRT_MACHINE (ms);int max_vm_pa_size, requested_pa_size;bool fixed_ipa; +int vm_type; max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa); + vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL ); +/* we freeze the memory map to compute the highest gpa */ virt_set_memmap (vms, max_vm_pa_size);
@@ -4080,7 +4085,11 @@ static int virt_kvm_type(MachineState *ms, const char *type_str)* the implicit legacy 40b IPA setting, in which case the kvm_type * must be 0. */ -return fixed_ipa ?0 : requested_pa_size; +if (fixed_ipa) { +return 0 ; + } + +return requested_pa_size | vm_type; } static int virt_get_physical_address_range(MachineState *ms,
Signature · 1 line
2.43.0
Re: [RFC v4 16/24] hw/arm/virt: Embed Realm VM type with IPA address space
Quoted 24 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
Set the Ream VM bit in the IPA address space size when needed.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/arm/virt.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)hw/arm/virt.c +2
-0@@ -97,6 +97,8 @@#include "qemu/guest-random.h" #include "hw/watchdog/sbsa_gwdt.h" +#include <linux/kvm.h> +static GlobalProperty arm_virt_compat_defaults[] = { {TYPE_VIRTIO_IOMMU_PCI ,"aw-bits" ,"48" }, };
hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4059
Quoted 5 lines
hw/arm/virt.c +1
-0@@ -4053,9 +4055,12 @@ static int virt_kvm_type(MachineState *ms, const char *type_str)VirtMachineState *vms =VIRT_MACHINE (ms);int max_vm_pa_size, requested_pa_size;bool fixed_ipa; +int vm_type;
Lets initialize @vm_type when it's declared:
VirtMachineState *vms = VIRT_MACHINE(ms)
int vm_type = ms->cgs ? KVM_VM_TYPE_ARM_REALM : KVM_VM_TYPE_ARM_NORMAL;
int max_vm_pa_size, requested_pa_size;
bool fixed_ipa;Quoted 10 lines
hw/arm/virt.c +2
-0max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa); + vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL ); +/* we freeze the memory map to compute the highest gpa */ virt_set_memmap (vms, max_vm_pa_size);@@ -4080,7 +4085,11 @@ static int virt_kvm_type(MachineState *ms, const char *type_str)* the implicit legacy 40b IPA setting, in which case the kvm_type * must be 0.
hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4095
Quoted 10 lines
hw/arm/virt.c +5
-1*/ -return fixed_ipa ?0 : requested_pa_size; +if (fixed_ipa) { +return 0 ; + } + +return requested_pa_size | vm_type; } static int virt_get_physical_address_range(MachineState *ms,
Thanks,
Gavin
RFC v4 17/24 hw/arm/virt: Reserve one bit of guest physical address for RME
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
When RME is enabled, the upper GPA bit is used to distinguish protected from unprotected addresses. Reserve it when setting up the guest memory map.
--- hw/arm/virt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
hw/arm/virt.c +15 -5
@@ -4054,17 +4054,27 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) {VirtMachineState *vms =VIRT_MACHINE (ms);int max_vm_pa_size, requested_pa_size; +int rme_reserve_bit =0 ;bool fixed_ipa;int vm_type; - max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa); - vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL ); +if (vm_type) { +/* +* With RME, the upper GPA bit differentiates Realm from NS memory. +* Reserve the upper bit to ensure that highmem devices will fit. +*/ + rme_reserve_bit =1 ; + } + + max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa) - + rme_reserve_bit; +/* we freeze the memory map to compute the highest gpa */ virt_set_memmap (vms, max_vm_pa_size); - requested_pa_size =64 -clz64 (vms->highest_gpa); + requested_pa_size =64 -clz64 (vms->highest_gpa) + rme_reserve_bit;/* * KVM requires the IPA size to be at least 32 bits.
@@ -4073,11 +4083,11 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) requested_pa_size =32 ; } -if (requested_pa_size > max_vm_pa_size) { +if (requested_pa_size > max_vm_pa_size + rme_reserve_bit) {error_report ("-m and ,maxmem option values " "require an IPA range (%d bits) larger than " "the one supported by the host (%d bits)" , - requested_pa_size, max_vm_pa_size); + requested_pa_size, max_vm_pa_size + rme_reserve_bit);return -1 ; }/*
Signature · 1 line
2.43.0
Re: [RFC v4 17/24] hw/arm/virt: Reserve one bit of guest physical address for RME
Quoted 25 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When RME is enabled, the upper GPA bit is used to distinguish protected from unprotected addresses. Reserve it when setting up the guest memory map.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/arm/virt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)hw/arm/virt.c +1
-1@@ -4054,17 +4054,27 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) {VirtMachineState *vms =VIRT_MACHINE (ms);int max_vm_pa_size, requested_pa_size; +int rme_reserve_bit =0 ;bool fixed_ipa;int vm_type; - max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa);
hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4069
Quoted 10 lines
hw/arm/virt.c +7
-1- vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL ); +if (vm_type) { +/* +* With RME, the upper GPA bit differentiates Realm from NS memory. +* Reserve the upper bit to ensure that highmem devices will fit. +*/ + rme_reserve_bit =1 ; + }
"if (vm_type)" are mapped to any VM types other than KVM_VM_TYPE_ARM_NORMAL, meaning it can be PKVM in theory. So this would be:
if (vm_type == KVM_VM_TYPE_ARM_REALM) {
...
}Quoted 16 lines
hw/arm/virt.c +5
-1+ + max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa) - + rme_reserve_bit; +/* we freeze the memory map to compute the highest gpa */ virt_set_memmap (vms, max_vm_pa_size); - requested_pa_size =64 -clz64 (vms->highest_gpa); + requested_pa_size =64 -clz64 (vms->highest_gpa) + rme_reserve_bit;/* * KVM requires the IPA size to be at least 32 bits. @@ -4073,11 +4083,11 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) requested_pa_size =32 ; }
hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4093
Quoted 10 lines
hw/arm/virt.c +2
-2-if (requested_pa_size > max_vm_pa_size) { +if (requested_pa_size > max_vm_pa_size + rme_reserve_bit) {error_report ("-m and ,maxmem option values " "require an IPA range (%d bits) larger than " "the one supported by the host (%d bits)" , - requested_pa_size, max_vm_pa_size); + requested_pa_size, max_vm_pa_size + rme_reserve_bit);return -1 ; }/*
Thanks,
Gavin
Re: [RFC v4 17/24] hw/arm/virt: Reserve one bit of guest physical address for RME
Quoted 38 lines · Gavin Shan
Quoted 23 lines · Mathieu Poirier
From: Jean-Philippe Brucker <[email protected]>
When RME is enabled, the upper GPA bit is used to distinguish protected from unprotected addresses. Reserve it when setting up the guest memory map.
Signed-off-by Jean-Philippe Brucker <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- hw/arm/virt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)hw/arm/virt.c +1
-0@@ -4054,17 +4054,27 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) {VirtMachineState *vms =VIRT_MACHINE (ms);int max_vm_pa_size, requested_pa_size; +int rme_reserve_bit =0 ;bool fixed_ipa;int vm_type;hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4067
Quoted 10 lines
hw/arm/virt.c +7
-2- max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa); - vm_type = (ms->cgs ?KVM_VM_TYPE_ARM_REALM :KVM_VM_TYPE_ARM_NORMAL ); +if (vm_type) { +/* +* With RME, the upper GPA bit differentiates Realm from NS memory. +* Reserve the upper bit to ensure that highmem devices will fit. +*/ + rme_reserve_bit =1 ; + }"if (
vm_type)" are mapped to any VM types other thanKVM_VM_TYPE_ARM_NORMAL, meaning it can be PKVM in theory. So this would be:
Quoted 3 lines
if (vm_type == KVM_VM_TYPE_ARM_REALM) {
...
}I agree.
Quoted 28 lines
Quoted 14 lines
hw/arm/virt.c +5
-1+ + max_vm_pa_size =kvm_arm_get_max_vm_ipa_size (ms, &fixed_ipa) - + rme_reserve_bit; +/* we freeze the memory map to compute the highest gpa */ virt_set_memmap (vms, max_vm_pa_size); - requested_pa_size =64 -clz64 (vms->highest_gpa); + requested_pa_size =64 -clz64 (vms->highest_gpa) + rme_reserve_bit;/* * KVM requires the IPA size to be at least 32 bits. @@ -4073,11 +4083,11 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) requested_pa_size =32 ; }hw/arm/virt.c static int virt_kvm_type(MachineState *ms, const char *type_str) · line 4092
Quoted 10 lines
hw/arm/virt.c +2
-2-if (requested_pa_size > max_vm_pa_size) { +if (requested_pa_size > max_vm_pa_size + rme_reserve_bit) {error_report ("-m and ,maxmem option values " "require an IPA range (%d bits) larger than " "the one supported by the host (%d bits)" , - requested_pa_size, max_vm_pa_size); + requested_pa_size, max_vm_pa_size + rme_reserve_bit);return -1 ; }/* Thanks,
Gavin
RFC v4 18/24 hw/arm/virt: Disable DTB randomness for confidential VMs
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
The dtb-randomness feature, which adds random seeds to the DTB, isn't really compatible with confidential VMs since it randomizes the Realm Initial Measurement. Enabling it is not an error, but it prevents attestation. It also isn't useful to a Realm, which doesn't trust host input.
Currently the feature is automatically enabled, unless the user disables it on the command-line. Change it to OnOffAuto, and automatically disable it for confidential VMs, unless the user explicitly enables it.
--- docs/system/arm/virt.rst | 9 +++++---- hw/arm/virt.c | 41 +++++++++++++++++++++++++--------------- include/hw/arm/virt.h | 2 +- 3 files changed, 32 insertions(+), 20 deletions(-)
docs/system/arm/virt.rst +5 -4
@@ -238,10 +238,11 @@ dtb-randomness rng-seed and kaslr-seed nodes (in both "/chosen" and "/secure-chosen") to use for features like the random number generator and address space randomisation. The default is - ``on``. You will want to disable it if your trusted boot chain - will verify the DTB it is passed, since this option causes the - DTB to be non-deterministic. It would be the responsibility of - the firmware to come up with a seed and pass it on if it wants to. + ``off`` for confidential VMs, and ``on`` otherwise. You will want + to disable it if your trusted boot chain will verify the DTB it is + passed, since this option causes the DTB to be non-deterministic. + It would be the responsibility of the firmware to come up with a + seed and pass it on if it wants to. dtb-kaslr-seed A deprecated synonym for dtb-randomness.
hw/arm/virt.c +26 -15
94 lines not on this page · raw message
include/hw/arm/virt.h +1 -1
@@ -176,7 +176,7 @@ struct VirtMachineState {bool virt;bool ras;bool mte; -bool dtb_randomness; +OnOffAuto dtb_randomness;bool second_ns_uart_present;OnOffAuto acpi;VirtGICType gic_version;
Signature · 1 line
2.43.0
RFC v4 19/24 hw/arm/virt: Move virt_flash_create() to machvirt_init()
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
For confidential VMs we'll want to skip flash device creation. Unfortunately, in virt_instance_init() the machine->cgs member has not yet been initialized, so we cannot check whether confidential guest is enabled. Move virt_flash_create() to machvirt_init(), where we can access the machine->cgs member.
--- hw/arm/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
hw/arm/virt.c +2 -2
@@ -2911,6 +2911,8 @@ static void machvirt_init(MachineState *machine)unsigned int smp_cpus = machine->smp.cpus;unsigned int max_cpus = machine->smp.max_cpus; +virt_flash_create (vms); + possible_cpus = mc->possible_cpu_arch_ids (machine);/*
@@ -4435,8 +4437,6 @@ static void virt_instance_init(Object *obj) vms->virtio_transports =NUM_VIRTIO_TRANSPORTS ; -virt_flash_create (vms); - vms->oem_id =g_strndup (ACPI_BUILD_APPNAME6 ,6 ); vms->oem_table_id =g_strndup (ACPI_BUILD_APPNAME8 ,8 );cxl_machine_init (obj, &vms->cxl_devices_state);
Signature · 1 line
2.43.0
RFC v4 20/24 hw/arm/virt: Use RAM instead of flash for confidential guest firmware
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Use RAM instead of flash to store firmware image and boot information, including UEFI variables. That way the firmware can be measured and included in the Realm's initial measurements. It also prevents variable stored in flash and modified as part of the boot process to be leaked outside the Realm.
--- hw/arm/boot.c | 37 +++++++++++++++++++++++++-- hw/arm/virt.c | 58 +++++++++++++++++++++++++++++++++++++++++++ include/hw/arm/boot.h | 9 +++++++ 3 files changed, 102 insertions(+), 2 deletions(-)
hw/arm/boot.c +35 -2
@@ -1112,7 +1112,36 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, } } -static void arm_setup_firmware_boot (ARMCPU *cpu,struct arm_boot_info *info) +static void arm_setup_confidential_firmware_boot (ARMCPU *cpu, +struct arm_boot_info *info, +const char *firmware_filename) +{ +ssize_t fw_size; +const char *fname; +AddressSpace *as =arm_boot_address_space (cpu, info); + + fname =qemu_find_file (QEMU_FILE_TYPE_BIOS , firmware_filename); +if (!fname) { +error_report ("Could not find firmware image '%s'" , firmware_filename); +exit (1 ); + } + +/* +* Load the firmware image in the Realm's address space. Mapping of the +* firmware area in the Realm's address space is done in function +* virt_confidential_firmware_init(). +*/ + fw_size =load_image_targphys_as (firmware_filename, + info->firmware_base, + info->firmware_max_size, as,NULL ); +if (fw_size <=0 ) { +error_report ("could not load firmware '%s'" , firmware_filename); +exit (1 ); + } +} + +static void arm_setup_firmware_boot (ARMCPU *cpu,struct arm_boot_info *info, +const char *firmware_filename) {/* Set up for booting firmware (which might load a kernel via fw_cfg) */
@@ -1168,6 +1197,10 @@ static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) } } +if (info->confidential) { +arm_setup_confidential_firmware_boot (cpu, info, firmware_filename); + } +/* * We will start from address 0 (typically a boot ROM image) in the * same way as hardware. Leave env->boot_info NULL, so that
@@ -1212,7 +1245,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)/* Load the kernel. */ if (!info->kernel_filename || info->firmware_loaded) { -arm_setup_firmware_boot (cpu, info); +arm_setup_firmware_boot (cpu, info, ms->firmware); }else {arm_setup_direct_kernel_boot (cpu, info); }
hw/arm/virt.c +58 -0
89 lines not on this page · raw message
include/hw/arm/boot.h +9 -0
@@ -113,6 +113,10 @@ struct arm_boot_info {*/ bool firmware_loaded; +/* Used when loading firmware into RAM */ +hwaddr firmware_base; +hwaddr firmware_max_size; +/* Address at which board specific loader/setup code exists. If enabled, * this code-blob will run before anything else. It must return to the * caller via the link register. There is no stack set up. Enabled by
@@ -136,6 +140,11 @@ struct arm_boot_info {/* CPU having load the kernel and that should be the first to boot. */ ARMCPU *primary_cpu; + +/* +* Confidential guest boot loads everything into RAM so it can be measured. +*/ +bool confidential; };/**
Signature · 1 line
2.43.0
RFC v4 21/24 target/arm/kvm-rme: Add DMA remapping for the shared memory region
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
In Arm CCA, the guest-physical address space is split in half. The top half represents memory shared between guest and host, and the bottom half is private to the guest. From QEMU's point of view, the two halves are merged into a single region, and pages within this region are either shared or private.
Virtual devices implemented by the host are only allowed to access the top half. For emulated MMIO, KVM strips the GPA before returning to QEMU, so the GPA already belongs to QEMU's merged view of guest memory. However DMA addresses cannot be stripped this way and need special handling by the VMM.
When emulating DMA the VMM needs to translate the addresses into its merged view. Add an IOMMU memory region on the top half, that retargets DMA accesses to the merged sysmem.
--- hw/arm/virt.c | 2 + target/arm/kvm-rme.c | 106 ++++++++++++++++++++++++++++++++++++++++++ target/arm/kvm-stub.c | 4 ++ target/arm/kvm_arm.h | 10 ++++ 4 files changed, 122 insertions(+)
hw/arm/virt.c +2 -0
@@ -3327,6 +3327,8 @@ static void machvirt_init(MachineState *machine) vms->fw_cfg, OBJECT(vms)); } +kvm_arm_rme_init_gpa_space (vms->highest_gpa, vms->bus); + vms->bootinfo.ram_size = machine->ram_size; vms->bootinfo.board_id =-1 ; vms->bootinfo.loader_start = vms->memmap[VIRT_MEM ].base;
target/arm/kvm-rme.c +106 -0
132 lines not on this page · raw message
target/arm/kvm-stub.c +4 -0
@@ -42,6 +42,10 @@ bool kvm_arm_el2_supported(void)return false; } +void kvm_arm_rme_init_gpa_space (hwaddr highest_gpa,PCIBus *pci_bus) +{ +} +/* * These functions should never actually be called without KVM support. */
target/arm/kvm_arm.h +10 -0
@@ -250,4 +250,14 @@ char *kvm_print_register_name(uint64_t regidx);*/ void kvm_arm_rme_vcpu_init (ARMCPU *cpu); +/** +* kvm_arm_rme_setup_gpa +* @highest_gpa: highest address of the lower half of the guest address space +* @pci_bus: The main PCI bus, for which PCI queries DMA address spaces +* +* Setup the guest-physical address space for a Realm. Install a memory region +* and notifier to manage the shared upper half of the address space. +*/ +void kvm_arm_rme_init_gpa_space (hwaddr highest_gpa,PCIBus *pci_bus); +#endif
Signature · 1 line
2.43.0
RFC v4 22/24 docs/interop/firmware.json: Add arm-rme firmware feature
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Some distributions provide packages continaing firmware to be run under QEMU, such as "qemu-efi-aarch64" or "edk2-aarch64". Those packages also contain descriptors in /usr/share/qemu/firmware/*.json listing the firmware features, so that environments like libvirt can figure out which firmware they can load.
Define an optional feature for arm64 firmware to indicate that a firmware supports running in a Realm. Firmware implementations need extra support for running in a Realm, in particular to distinguish shared from private guest memory.
--- docs/interop/firmware.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
docs/interop/firmware.json +4 -1
@@ -161,6 +161,9 @@ # options related to this feature are documented in # "docs/system/i386/amd-memory-encryption.rst". # +# @arm-rme: The firmware supports running in a Realm, under the Arm Realm +# Management Extension (RME). +# # @intel-tdx: The firmware supports running under Intel Trust Domain # Extensions (TDX). #
@@ -229,7 +232,7 @@ { 'enum' : 'FirmwareFeature', 'data' : [ 'acpi-s3', 'acpi-s4', 'amd-sev', 'amd-sev-es', 'amd-sev-snp', - 'intel-tdx', + 'arm-rme', 'intel-tdx', 'enrolled-keys', 'requires-smm', 'secure-boot', 'host-uefi-vars', 'verbose-dynamic', 'verbose-static' ] }
Signature · 1 line
2.43.0
RFC v4 23/24 hw/arm/boot: Load DTB as is for confidential VMs
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
Load DTB without modifications when provided. That way it is possible for a verification entity to reconstruct the Realm's initial measurement.
--- hw/arm/boot.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
hw/arm/boot.c +8 -1
@@ -477,7 +477,14 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,g_autoptr (MemoryDeviceInfoList) md_list =NULL ;Error *err =NULL ; -if (binfo->dtb_filename) { +if (binfo->dtb_filename && binfo->confidential) { +/* +* If the user is providing a DTB for a confidential VM, it is already +* tailored to this configuration and measured. Load it as is, without +* any modification. +*/ +return rom_add_file_fixed_as (binfo->dtb_filename, addr,-1 , as); + }else if (binfo->dtb_filename) {char *filename; filename =qemu_find_file (QEMU_FILE_TYPE_DTB , binfo->dtb_filename);if (!filename) {
Signature · 1 line
2.43.0
RFC v4 24/24 hw/arm/boot: Skip bootloader for confidential guests
In reply to Mathieu PoirierFrom: Jean-Philippe Brucker <[email protected]>
An independent verifier needs to reconstruct the content of guest memory in order to attest that it is running trusted code. To avoid having to reconstruct the bootloader generated by QEMU, skip this step and jump directly to the kernel, with the DTB address in x0 as specified by the Linux boot protocol [1].
[1] https://docs.kernel.org/arch/arm64/booting.html
--- hw/arm/boot.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
hw/arm/boot.c +18 -6
@@ -731,7 +731,13 @@ static void do_cpu_reset(void *opaque)if (cpu == info->primary_cpu) {AddressSpace *as =arm_boot_address_space (cpu, info); -cpu_set_pc (cs, info->loader_start); +if (info->confidential) { +assert (is_a64 (env)); + env->xregs[0 ] = info->dtb_start; +cpu_set_pc (cs, info->entry); + }else { +cpu_set_pc (cs, info->loader_start); + }if (!have_dtb (info)) {set_kernel_args (info, as);
@@ -821,7 +827,8 @@ static ssize_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry, }static uint64_t load_aarch64_image (const char *filename,hwaddr mem_base, -hwaddr *entry,AddressSpace *as) +hwaddr *entry,AddressSpace *as, +bool confidential) {const size_t max_bytes =LOAD_IMAGE_MAX_DECOMPRESSED_BYTES ;hwaddr kernel_load_offset =KERNEL64_LOAD_ADDR ;
@@ -873,7 +880,8 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,* bootloader, we can just load it starting at 2MB+offset rather * than 0MB + offset. */ -if (kernel_load_offset <BOOTLOADER_MAX_SIZE ) { +if (kernel_load_offset <BOOTLOADER_MAX_SIZE && + !confidential) { kernel_load_offset +=2 * MiB; } }
@@ -957,7 +965,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, }if (arm_feature (&cpu->env,ARM_FEATURE_AARCH64 ) && kernel_size <0 ) { kernel_size =load_aarch64_image (info->kernel_filename, - info->loader_start, &entry, as); + info->loader_start, &entry, as, + info->confidential); is_linux =1 ;if (kernel_size >=0 ) { image_low_addr = entry;
@@ -1098,8 +1107,11 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, fixupcontext[FIXUP_ENTRYPOINT_LO ] = entry; fixupcontext[FIXUP_ENTRYPOINT_HI ] = entry >>32 ; -arm_write_bootloader ("bootloader" , as, info->loader_start, - primary_loader, fixupcontext); +/* Immediately jump to the kernel when guest is a Realm */ +if (!info->confidential) { +arm_write_bootloader ("bootloader" , as, info->loader_start, + primary_loader, fixupcontext); + }if (info->write_board_setup) { info->write_board_setup (cpu, info);
Signature · 1 line
2.43.0
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \
-M confidential-guest-support=rme0,memory-backend=ram0 \
-object rme-guest,id=rme0,convert-in-place=on \
-object memory-backend-guest-memfd,id=ram0,size=1G,share=on \
-cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
Mathieu
Quoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructions
Give this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \
-M virt,virtualization=on,secure=on,gic-version=3,acpi=off \
-cpu max,x-rme=on -m 4G -smp 8 \
-serial mon:stdio -monitor none -nographic -nodefaults \
-bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \
-kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \
-initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \
-append kvm-arm.mode=rmm \
-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \
-device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \
-device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \
-device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \
-device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \
-fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \
-netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \
-device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \
-machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \
-smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \
-object memory-backend-guest-memfd,id=mem0,size=2G,share=on \
-numa node,nodeid=0,cpus=0-3,memdev=mem0 \
-serial mon:stdio -monitor none -nographic -nodefaults \
-kernel /mnt/linux/arch/arm64/boot/Image \
-initrd /mnt/buildroot/output/images/rootfs.cpio.xz \
-append earlycon=pl011,mmio,0x10009000000Found issues
============
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "/tmp/mem" 0x40000000 0x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end <= target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end <= target_start)
(2) qemu emulation can't be stopped and resumed
(qemu) stop
(qemu) cont
Failed to set KVM_REG_ARM_TIMER_CNT
(3) qemu is terminiated on qmp command 'system_reset'
(qemu) system_reset
cpus are not resettable, terminating
(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminating
(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
-object rme-guest,id=rme0,convert-in-place=on \
-machine virt,gic-version=3,confidential-guest-support=rme0 \
-m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \
-object memory-backend-guest-memfd,id=mem0,size=2G,share=on \
-numa node,nodeid=0,cpus=0-3,memdev=mem0 \
-serial mon:stdio -monitor none -nographic -nodefaults \
-kernel /mnt/linux/arch/arm64/boot/Image \
-initrd /mnt/buildroot/output/images/rootfs.cpio.xz \
-append earlycon=pl011,mmio,0x10009000000 \
-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \
-device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \
-device virtio-iommu-pci,bus=pcie.0 \
-drive file=/mnt/disk.qcow2,if=none,id=drive0 \
-device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \
-netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \
-device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0
:
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510]
[ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026
[ 0.000000] KASLR enabled
[ 0.000000] Machine model: linux,dummy-virt
[ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '')
[ 0.000000] printk: legacy bootconsole [pl11] enabled
[ 0.000000] efi: UEFI not found.
[ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT
[ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf]
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.1 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] psci: SMC Calling Convention v1.2
[ 0.000000] RME: Using RSI version 1.0
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff]
[ 0.000000] DMA32 empty
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
:
[ 6.664423] Serial: AMBA PL011 UART driver
[ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1
[ 7.213181] printk: console [ttyAMA0] enabled
[ 8.536454] HugeTLB: registered 1.00 Gi<...The realm guest stops here, no output since then...>
Thanks,
Gavin
Good day,
Quoted 44 lines · Gavin Shan
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \
-M confidential-guest-support=rme0,memory-backend=ram0 \
-object rme-guest,id=rme0,convert-in-place=on \
-object memory-backend-guest-memfd,id=ram0,size=1G,share=on \
-cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
MathieuQuoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructions
Quoted 3 lines
Give this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
Thank you for taking the time.
Quoted 5 lines
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
I am currently focused on the SBSA machine but will try to reproduce your manipulations using 'upstream-v5' that I just posted.
Note that upstream-v5 doesn't address any of the comments you posted today. Since upstream-v4 was based on v16, I wanted to send another revision that is based on the very latest (v21) to keep pace with Suzuki and Steven.
I am off to Linux Plumbers next week but rest assured that I will look into your comments (and the content herein) when I'm back.
Thanks,
Mathieu
Quoted 110 lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \ -M virt,virtualization=on,secure=on,gic-version=3,acpi=off \ -cpu max,x-rme=on -m 4G -smp 8 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \ -kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \ -initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \ -append kvm-arm.mode=rmm \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \ -device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \ -device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \ -fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \ -netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000Found issues
============(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)(2) qemu emulation can't be stopped and resumed
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNT(3) qemu is terminiated on qmp command '
system_reset'(qemu)
system_reset
cpus are not resettable, terminating(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminating(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
(quoted diff) +0
-16-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device virtio-iommu-pci,bus=pcie.0 \ -drive file=/mnt/disk.qcow2,if=none,id=drive0 \ -device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \ -netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0 :[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510] [ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026 [ 0.000000] KASLR enabled [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '') [ 0.000000] printk: legacy bootconsole [pl11] enabled [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT [ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv1.1 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] psci: MIGRATE_INFO_TYPE not supported. [ 0.000000] psci: SMC Calling Convention v1.2 [ 0.000000] RME: Using RSI version 1.0 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff] [ 0.000000] DMA32 empty [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node : [ 6.664423] Serial: AMBA PL011 UART driver [ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1 [ 7.213181] printk: console [ttyAMA0] enabled [ 8.536454] HugeTLB: registered 1.00 Gi<...The realm guest stops here, no output since then...>
Thanks,
Gavin
Hi Gavin,
Quoted 82 lines · Gavin Shan
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \
-M confidential-guest-support=rme0,memory-backend=ram0 \
-object rme-guest,id=rme0,convert-in-place=on \
-object memory-backend-guest-memfd,id=ram0,size=1G,share=on \
-cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
MathieuQuoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructionsGive this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \ -M virt,virtualization=on,secure=on,gic-version=3,acpi=off \ -cpu max,x-rme=on -m 4G -smp 8 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \ -kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \ -initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \ -append kvm-arm.mode=rmm \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \ -device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \ -device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \ -fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \ -netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000
Quoted 2 lines
Found issues
============
I was able to do the same manipulations on my side, but using the SBSA machine for system emulation, with results as described below:
Quoted 8 lines
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)
On my side this command causes the Realm to abort, as I expected it to be. Realm memory should not be observable from the host. There may be a debug mode to enable this kind of operation but I will have to look at the documentation for details.
Quoted 6 lines
(2) qemu emulation can't be stopped and resumed
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNT
That too I was expecting. Anything that can comprimise a Realm will cause the HW to abort. I'll investigate the "Failed to set KVM_REG_ARM_TIMER_CNT" error message though.
Quoted 5 lines
(3) qemu is terminiated on qmp command '
system_reset'(qemu)
system_reset
cpus are not resettable, terminating
Quoted 8 lines
(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminating
I suspect 'system_reset' from the monitor and a 'reboot' from the command line will, at some point, end up following the same sequence. I need to think about the 'reboot' use case further.
Quoted 10 lines
(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
(quoted diff) +0
-6-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \
Review
Quoted 10 lines
(quoted diff) +0
-10-kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device virtio-iommu-pci,bus=pcie.0 \ -drive file=/mnt/disk.qcow2,if=none,id=drive0 \ -device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \ -netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0
I added the following to my Realm's boot command parameters:
-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \
-device virtio-iommu-pci,bus=pcie.0 \
Quoted 26 lines
: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510] [ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026 [ 0.000000] KASLR enabled [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '') [ 0.000000] printk: legacy bootconsole [pl11] enabled [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT [ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv1.1 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] psci: MIGRATE_INFO_TYPE not supported. [ 0.000000] psci: SMC Calling Convention v1.2 [ 0.000000] RME: Using RSI version 1.0 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff] [ 0.000000] DMA32 empty [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node : [ 6.664423] Serial: AMBA PL011 UART driver [ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1 [ 7.213181] printk: console [ttyAMA0] enabled [ 8.536454] HugeTLB: registered 1.00 Gi
Quoted 2 lines
<...The realm guest stops here, no output since then...>
On my side I get to user space but virtio-serial and virtio-net don't work. I'm guessing virtio-iommu-pci does the same thing as this patch [1], but virtio devices are disrupted because it is not configured properly. I need to investigate to find the best approach to follow, i.e implicitly use (and configure) a virtio-iommu-pci or make sure that [1] and a virtio-iommu-pci device can play nice together.
Thanks,
Mathieu
[1]. [RFC v4 21/24] target/arm/kvm-rme: Add DMA remapping for the shared memory region
Quoted 3 lines
Thanks,
Gavin
Hi Mathieu,
Quoted 85 lines · Mathieu Poirier
Hi Gavin,
Quoted 82 lines · Gavin Shan
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \ -M confidential-guest-support=rme0,memory-backend=ram0 \ -object rme-guest,id=rme0,convert-in-place=on \ -object memory-backend-guest-memfd,id=ram0,size=1G,share=on \ -cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
MathieuQuoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructionsGive this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \ -M virt,virtualization=on,secure=on,gic-version=3,acpi=off \ -cpu max,x-rme=on -m 4G -smp 8 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \ -kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \ -initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \ -append kvm-arm.mode=rmm \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \ -device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \ -device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \ -fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \ -netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000
Quoted 6 lines
Quoted 2 lines
Found issues
============I was able to do the same manipulations on my side, but using the SBSA machine for system emulation, with results as described below:
Thanks for double check on your side. Just a head up: I will re-run the broken test cases with (RFCv5) qemu series and share the result. I expect we will have more discussions on those broken test cases under RFCv5 series if you agree. I don't know when I get a chance to try RFCv5 series, but hopefully next week or early of the week after that.
Cheers,
Gavin
Quoted 118 lines
Quoted 8 lines
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)On my side this command causes the Realm to abort, as I expected it to be. Realm memory should not be observable from the host. There may be a debug mode to enable this kind of operation but I will have to look at the documentation for details.
Quoted 6 lines
(2) qemu emulation can't be stopped and resumed
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNTThat too I was expecting. Anything that can comprimise a Realm will cause the HW to abort. I'll investigate the "Failed to set
KVM_REG_ARM_TIMER_CNT" error message though.Quoted 5 lines
(3) qemu is terminiated on qmp command '
system_reset'(qemu)
system_reset
cpus are not resettable, terminatingQuoted 8 lines
(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminatingI suspect '
system_reset' from the monitor and a 'reboot' from the command line will, at some point, end up following the same sequence. I need to think about the 'reboot' use case further.Quoted 10 lines
(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
(quoted diff) +0
-6-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \Review
Quoted 10 lines
(quoted diff) +0
-10-kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device virtio-iommu-pci,bus=pcie.0 \ -drive file=/mnt/disk.qcow2,if=none,id=drive0 \ -device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \ -netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0I added the following to my Realm's boot command parameters:
(quoted diff) +0
-2-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device virtio-iommu-pci,bus=pcie.0 \Quoted 28 lines
: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510] [ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026 [ 0.000000] KASLR enabled [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '') [ 0.000000] printk: legacy bootconsole [pl11] enabled [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT [ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv1.1 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] psci: MIGRATE_INFO_TYPE not supported. [ 0.000000] psci: SMC Calling Convention v1.2 [ 0.000000] RME: Using RSI version 1.0 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff] [ 0.000000] DMA32 empty [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node : [ 6.664423] Serial: AMBA PL011 UART driver [ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1 [ 7.213181] printk: console [ttyAMA0] enabled [ 8.536454] HugeTLB: registered 1.00 GiQuoted 2 lines
<...The realm guest stops here, no output since then...>
On my side I get to user space but virtio-serial and virtio-net don't work. I'm guessing virtio-iommu-pci does the same thing as this patch [1], but virtio devices are disrupted because it is not configured properly. I need to investigate to find the best approach to follow, i.e implicitly use (and configure) a virtio-iommu-pci or make sure that [1] and a virtio-iommu-pci device can play nice together.
Thanks,
Mathieu[1]. [RFC v4 21/24] target/arm/kvm-rme: Add DMA remapping for the shared memory region
Quoted 3 lines
Thanks,
Gavin
Quoted 95 lines · Gavin Shan
Hi Mathieu,
Quoted 85 lines · Mathieu Poirier
Hi Gavin,
Quoted 82 lines · Gavin Shan
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \ -M confidential-guest-support=rme0,memory-backend=ram0 \ -object rme-guest,id=rme0,convert-in-place=on \ -object memory-backend-guest-memfd,id=ram0,size=1G,share=on \ -cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
MathieuQuoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructionsGive this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \ -M virt,virtualization=on,secure=on,gic-version=3,acpi=off \ -cpu max,x-rme=on -m 4G -smp 8 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \ -kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \ -initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \ -append kvm-arm.mode=rmm \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \ -device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \ -device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \ -fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \ -netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000Quoted 6 lines
Quoted 2 lines
Found issues
============I was able to do the same manipulations on my side, but using the SBSA machine for system emulation, with results as described below:
Quoted 6 lines
Thanks for double check on your side. Just a head up: I will re-run the broken test cases with (RFCv5) qemu series and share the result. I expect we will have more discussions on those broken test cases under RFCv5 series if you agree. I don't know when I get a chance to try RFCv5 series, but hopefully next week or early of the week after that.
I omitted to mention that I used RFCv5 for my manipulations on SBSA, so I expect you'll find the same problems as with RFCv4. No need to rush to do the test since my next revision will _not_ address any of those issues. For RFCv6 I want to concentrate on the other comments you and Kohei made and keep the bigger issues (the ones you raised here) for future revision. That way we make progess on this patchset and keep synchronized with the KVM patches Suzuki and Steven release.
We can discuss further at the KVM forum if you are there.
Quoted 121 lines
Cheers,
GavinQuoted 117 lines
Quoted 8 lines
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)On my side this command causes the Realm to abort, as I expected it to be. Realm memory should not be observable from the host. There may be a debug mode to enable this kind of operation but I will have to look at the documentation for details.
Quoted 6 lines
(2) qemu emulation can't be stopped and resumed
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNTThat too I was expecting. Anything that can comprimise a Realm will cause the HW to abort. I'll investigate the "Failed to set
KVM_REG_ARM_TIMER_CNT" error message though.Quoted 5 lines
(3) qemu is terminiated on qmp command '
system_reset'(qemu)
system_reset
cpus are not resettable, terminatingQuoted 8 lines
(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminatingI suspect '
system_reset' from the monitor and a 'reboot' from the command line will, at some point, end up following the same sequence. I need to think about the 'reboot' use case further.Quoted 10 lines
(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
(quoted diff) +0
-6-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \Review
Quoted 10 lines
(quoted diff) +0
-10-kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device virtio-iommu-pci,bus=pcie.0 \ -drive file=/mnt/disk.qcow2,if=none,id=drive0 \ -device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \ -netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0I added the following to my Realm's boot command parameters:
(quoted diff) +0
-2-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device virtio-iommu-pci,bus=pcie.0 \Quoted 28 lines
: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510] [ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026 [ 0.000000] KASLR enabled [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '') [ 0.000000] printk: legacy bootconsole [pl11] enabled [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT [ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv1.1 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] psci: MIGRATE_INFO_TYPE not supported. [ 0.000000] psci: SMC Calling Convention v1.2 [ 0.000000] RME: Using RSI version 1.0 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff] [ 0.000000] DMA32 empty [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node : [ 6.664423] Serial: AMBA PL011 UART driver [ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1 [ 7.213181] printk: console [ttyAMA0] enabled [ 8.536454] HugeTLB: registered 1.00 GiQuoted 2 lines
<...The realm guest stops here, no output since then...>
On my side I get to user space but virtio-serial and virtio-net don't work. I'm guessing virtio-iommu-pci does the same thing as this patch [1], but virtio devices are disrupted because it is not configured properly. I need to investigate to find the best approach to follow, i.e implicitly use (and configure) a virtio-iommu-pci or make sure that [1] and a virtio-iommu-pci device can play nice together.
Thanks,
Mathieu[1]. [RFC v4 21/24] target/arm/kvm-rme: Add DMA remapping for the shared memory region
Quoted 3 lines
Thanks,
Gavin
Quoted 111 lines · Mathieu Poirier
Quoted 95 lines · Gavin Shan
Hi Mathieu,
Quoted 85 lines · Mathieu Poirier
Hi Gavin,
Quoted 82 lines · Gavin Shan
Hi Mathieu,
Quoted 32 lines · Mathieu Poirier
This patchset provides minimal functionality to start a Realm VM from an Arm RME capable host using the following command line:
qemu-system-aarch64 \ -M confidential-guest-support=rme0,memory-backend=ram0 \ -object rme-guest,id=rme0,convert-in-place=on \ -object memory-backend-guest-memfd,id=ram0,size=1G,share=on \ -cpu host -M virt -enable-kvm -M gic-version=3,its=on -nodefaults ..It is a refactoring of Jean-Philippe Brucker's initial work dating from a while back. It is compatible with Steven Price's v16 revision [1] of his work adding CCA support to KVM.
This revision is based on Michael Roth's work on guest memfd in-place memory conversion [2], rebased to QEMU master. I left out the AMD specific changes from Michael's work because I can't test the result. Other than the modications to the linux headers, this series is identical to V3.
It was tested on the QEMU SBSA machine. For convenience, a repository is hosted here [3], along with the TF-A [4] and RMM [5] for the SBSA machine (compatible with Steven's v16 patchset). The Repository for the kernel [6] is also available. Note that for the latter, defines for
KVM_CAP_GUEST_MEMFD_MEMORY_ATTRIBUTESandKVM_CAP_ARM_RMIhave been modified to follow QEMU master.Instructions to compile and run the entire stack can be found here [7].
Device Assignment is not included.
Thanks,
MathieuQuoted 8 lines
[1]. https://lore.kernel.org/kvm/[email protected]/
[2]. https://lore.kernel.org/kvm/[email protected]/
[3]. https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4?ref_type=heads
[4]. https://gitlab.com/Linaro/cca-public/tf-a/trusted-firmware-a/-/tree/cca/v13?ref_type=heads
[5]. https://gitlab.com/Linaro/cca-public/rmm/-/tree/cca/v16?ref_type=heads
[6]. https://gitlab.com/Linaro/cca-public/linux/-/tree/upstream-v4?ref_type=heads
[7]. https://gitlab.com/Linaro/cca-public/build-instructionsGive this series and (v19) arm/cca host series [1] a try, and found the following issues. I'm sharing the found issues that I need take chance to look at them closely in future.
[1] https://git.gitlab.arm.com/linux-arm/linux-cca.git (branch: cca/cca-host/kvm-v19/integration)
Note that the host is emulated using qemu (TCG mode) via 'virt' platform, using the following command lines
laptop$ /home/gshan/sandbox/cca/host/qemu/build/qemu-system-aarch64 \ -M virt,virtualization=on,secure=on,gic-version=3,acpi=off \ -cpu max,x-rme=on -m 4G -smp 8 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -bios /home/gshan/sandbox/cca/host/tf-a/flash.bin \ -kernel /home/gshan/sandbox/cca/host/linux/arch/arm64/boot/Image \ -initrd /home/gshan/sandbox/cca/host/buildroot/output/images/rootfs.cpio.xz \ -append kvm-arm.mode=rmm \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device pcie-root-port,bus=pcie.0,chassis=3,id=pcie.3 \ -device pcie-root-port,bus=pcie.0,chassis=4,id=pcie.4 \ -device virtio-9p-device,fsdev=shr0,mount_tag=shr0 \ -fsdev local,security_model=none,path=/home/gshan/sandbox/cca/guest,id=shr0 \ -netdev tap,id=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:80The realm VM is started using the following command lines.
host$ qemu-system-aarch64 -enable-kvm -object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 -m 2G -cpu host \ -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \ -kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000Quoted 6 lines
Quoted 2 lines
Found issues
============I was able to do the same manipulations on my side, but using the SBSA machine for system emulation, with results as described below:
Quoted 6 lines
Thanks for double check on your side. Just a head up: I will re-run the broken test cases with (RFCv5) qemu series and share the result. I expect we will have more discussions on those broken test cases under RFCv5 series if you agree. I don't know when I get a chance to try RFCv5 series, but hopefully next week or early of the week after that.
I omitted to mention that I used RFCv5 for my manipulations on SBSA, so I expect you'll find the same problems as with RFCv4. No need to rush to do the test since my next revision will _not_ address any of those issues. For RFCv6 I want to concentrate on the other comments you and Kohei made and keep the bigger issues (the ones you raised here) for future revision. That way we make progess on this patchset and keep synchronized with the KVM patches Suzuki and Steven release.
Quoted 15 lines
We can discuss further at the KVM forum if you are there.
Quoted 13 lines
Cheers,
GavinQuoted 10 lines
Quoted 8 lines
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)On my side this command causes the Realm to abort, as I expected it to be.
Hi Mathieu, Gavin.
I've tested RFC v5, and I reproduced issue (1) on my side as well:
(qemu) dump-guest-memory -p "/tmp/mem" 0x40000000 0x10000000 Failed to set KVM_REG_ARM_TIMER_CNT
./qemu-ram-realm.sh: line 21: 77580 Aborted (core dumped) $QEMU -no-reboot -M confidential-guest-support=rme0,memory-backend=ram0 ...
This was resolved by adding kvm-no-adjvtime=on.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Realm memory should not be observable from the host. There may be a debug mode to enable this kind of operation but I will have to look at the documentation for details.
Quoted 2 lines
(2) qemu emulation can't be stopped and resumed
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNTThat too I was expecting. Anything that can comprimise a Realm will cause the HW to abort. I'll investigate the "Failed to set
KVM_REG_ARM_TIMER_CNT" error message though.
kvm-no-adjvtime=on also resolved issue (2) above.
Setting KVM_REG_ARM_TIMER_CNT for Realm VMs is not allowed, so we should either add this option or consider making it the default for Realm VMs in the future. What do you think?
Thanks,
Kohei
Quoted 95 lines
Quoted 95 lines
Quoted 94 lines
Quoted 6 lines
(3) qemu is terminiated on qmp command '
system_reset'(qemu)
system_reset
cpus are not resettable, terminatingQuoted 8 lines
(4) 'reboot' from the guest doesn't work
root@guest:~# reboot : Requesting system reboot [ 123.264893] reboot: Restarting system qemu-system-aarch64: cpus are not resettable, terminatingI suspect '
system_reset' from the monitor and a 'reboot' from the command line will, at some point, end up following the same sequence. I need to think about the 'reboot' use case further.Quoted 10 lines
(5) Incompatible to virtio-iommu-pci. The realm guest doesn't boot up if a virtio-iommu-pci device is specified in the command lines
host$ qemu-system-aarch64 -enable-kvm \
(quoted diff) +0
-6-object rme-guest,id=rme0,convert-in-place=on \ -machine virt,gic-version=3,confidential-guest-support=rme0 \ -m 2G -cpu host -smp maxcpus=4,cpus=4,sockets=1,clusters=1,cores=2,threads=2 \ -object memory-backend-guest-memfd,id=mem0,size=2G,share=on \ -numa node,nodeid=0,cpus=0-3,memdev=mem0 \ -serial mon:stdio -monitor none -nographic -nodefaults \Review
Quoted 10 lines
(quoted diff) +0
-10-kernel /mnt/linux/arch/arm64/boot/Image \ -initrd /mnt/buildroot/output/images/rootfs.cpio.xz \ -append earlycon=pl011,mmio,0x10009000000 \ -device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device pcie-root-port,bus=pcie.0,chassis=2,id=pcie.2 \ -device virtio-iommu-pci,bus=pcie.0 \ -drive file=/mnt/disk.qcow2,if=none,id=drive0 \ -device virtio-blk-pci,id=virtblk0,bus=pcie.1,drive=drive0,num-queues=4 \ -netdev tap,id=tap1,vhost=on,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,bus=pcie.2,netdev=tap1,mac=b8:3f:d2:1d:3e:c0I added the following to my Realm's boot command parameters:
(quoted diff) +0
-2-device pcie-root-port,bus=pcie.0,chassis=1,id=pcie.1 \ -device virtio-iommu-pci,bus=pcie.0 \Quoted 28 lines
: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x000f0510] [ 0.000000] Linux version 7.2.0-rc5-gavin-gf5098b6bae76 ([email protected]) (gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), GNU ld version 2.41-65.el10) #47 SMP PREEMPT Mon Jul 27 02:29:03 EDT 2026 [ 0.000000] KASLR enabled [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: pl11 at MMIO 0x0000010009000000 (options '') [ 0.000000] printk: legacy bootconsole [pl11] enabled [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: Reserved memory: No reserved-memory node in the DT [ 0.000000] NODE_DATA(0) allocated [mem 0xbfbecb00-0xbfbf09bf] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv1.1 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] psci: MIGRATE_INFO_TYPE not supported. [ 0.000000] psci: SMC Calling Convention v1.2 [ 0.000000] RME: Using RSI version 1.0 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000040000000-0x00000000bfffffff] [ 0.000000] DMA32 empty [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node : [ 6.664423] Serial: AMBA PL011 UART driver [ 7.151312] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 13, base_baud = 0) is a PL011 rev1 [ 7.213181] printk: console [ttyAMA0] enabled [ 8.536454] HugeTLB: registered 1.00 GiQuoted 2 lines
<...The realm guest stops here, no output since then...>
On my side I get to user space but virtio-serial and virtio-net don't work. I'm guessing virtio-iommu-pci does the same thing as this patch [1], but virtio devices are disrupted because it is not configured properly. I need to investigate to find the best approach to follow, i.e implicitly use (and configure) a virtio-iommu-pci or make sure that [1] and a virtio-iommu-pci device can play nice together.
Thanks,
Mathieu[1]. [RFC v4 21/24] target/arm/kvm-rme: Add DMA remapping for the shared memory region
Quoted 3 lines
Thanks,
Gavin
On Tue, Nov 10, 2026 at 05:01:14PM +0900, Kohei Enju wrote:
[...]
Quoted 34 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 7 lines
(1) qemu is terminiated on qmp command 'dump-guest-memory'
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000
**
ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start) Bail out! ERROR:../system/memory_mapping.c:215:guest_phys_block_add_section: assertion failed: (predecessor->target_end<=target_start)On my side this command causes the Realm to abort, as I expected it to be.
Hi Mathieu, Gavin.
I've tested RFC v5, and I reproduced issue (1) on my side as well:
(qemu) dump-guest-memory -p "
/tmp/mem"0x400000000x10000000Failed to setKVM_REG_ARM_TIMER_CNT
./qemu-ram-realm.sh: line 21: 77580 Aborted (core dumped) $QEMU -no-reboot -M confidential-guest-support=rme0,memory-backend=ram0 ...This was resolved by adding kvm-no-adjvtime=on.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Realm memory should not be observable from the host. There may be a debug mode to enable this kind of operation but I will have to look at the documentation for details.
Quoted 2 lines
(2) qemu emulation can't be stopped and resumed
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
(qemu) stop
(qemu) cont
Failed to setKVM_REG_ARM_TIMER_CNTThat too I was expecting. Anything that can comprimise a Realm will cause the HW to abort. I'll investigate the "Failed to set
KVM_REG_ARM_TIMER_CNT" error message though.
Quoted 5 lines
kvm-no-adjvtime=on also resolved issue (2) above.
Setting
KVM_REG_ARM_TIMER_CNTfor Realm VMs is not allowed, so we should either add this option or consider making it the default for Realm VMs in the future. What do you think?
I think that we should do something like we do for *put_registers(), where we detect whether we are running a Realm VM or not, regardless of the command line parameter or default that param to on for Realms.
Lorenzo