From 32af24f1c5554d83e25d6cd505f6fc6282af4e5f Mon Sep 17 00:00:00 2001 From: Zhenchao Liu Date: Wed, 10 May 2023 14:02:49 +0800 Subject: [PATCH] Add AMD SEV-SNP secure guest support qemu cmdline sample: -object sev-snp-guest,id=sev0, \ cbitpos=51,reduced-phys-bits=1, \ policy=0x30000, \ id-block=YWFhYWFhYWFhYWFhYWFhCg==, \ id-auth=CxHK/OKLkXGn/KpAC7Wl1FSiisWDbGTEKz..., \ auth-key-enabled=on, \ host-data=LNkCWBRC5CcdGXirbNUV1OrsR28s..., \ guest-visible-workarounds=AA==, \ Signed-off-by: Zhenchao Liu --- virttest/qemu_capabilities.py | 1 + virttest/qemu_devices/qcontainer.py | 75 ++++++++++++++++++++--------- virttest/qemu_vm.py | 7 ++- virttest/shared/cfg/base.cfg | 10 +++- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/virttest/qemu_capabilities.py b/virttest/qemu_capabilities.py index 57a4a13f9b..097c984f42 100644 --- a/virttest/qemu_capabilities.py +++ b/virttest/qemu_capabilities.py @@ -27,6 +27,7 @@ class Flags(object): MACHINE_MEMORY_BACKEND = _auto_value() MIGRATION_PARAMS = _auto_value() SEV_GUEST = _auto_value() + SNP_GUEST = _auto_value() TDX_GUEST = _auto_value() FLOPPY_DEVICE = _auto_value() BLOCKJOB_BACKING_MASK_PROTOCOL = _auto_value() diff --git a/virttest/qemu_devices/qcontainer.py b/virttest/qemu_devices/qcontainer.py index 8354617a9f..b82d61db23 100644 --- a/virttest/qemu_devices/qcontainer.py +++ b/virttest/qemu_devices/qcontainer.py @@ -429,6 +429,9 @@ def _probe_capabilities(self): # -object sev-guest if self.has_object("sev-guest"): self.caps.set_flag(Flags.SEV_GUEST) + # -object sev-snp-guest + if self.has_object('sev-snp-guest'): + self.caps.set_flag(Flags.SNP_GUEST) # -object tdx-guest if self.has_object("tdx-guest"): self.caps.set_flag(Flags.TDX_GUEST) @@ -1400,8 +1403,8 @@ def machine_q35(machine_params): qdevices.QCPUBus(params.get("cpu_model"), [[""], [0]], "vcpu"), ) - # FIXME: Use -bios option to set firmware for a tdx vm - if params.get("vm_secure_guest_type") != "tdx": + # FIXME: Use -bios option to set firmware for a tdx/snp vm + if params.get("vm_secure_guest_type") not in ["snp", "tdx"]: pflash_devices = pflash_handler("ovmf", machine_params) devices.extend(pflash_devices) @@ -3936,31 +3939,44 @@ def secure_guest_object_define_by_params(self, obj_id, params): :return: the secret QObject device """ - def _gen_sev_obj_props(obj_id, params): + def _gen_sev_common_props(params): + """ + Generate the sev common properties, refer to SevCommonProperties + Required: cbitpos, reduced-phys-bits """ - Generate the properties of the sev-guest object. + sev_common_props = { + # FIXME: Set the following two properties from sev capabilities + # if they are not set yet + "cbitpos": int(params["vm_sev_cbitpos"]), + "reduced-phys-bits": int(params["vm_sev_reduced_phys_bits"]), + } - Follow libvirt's way to set the following options: - Required: - policy, cbitpos and reduced-phys-bits - Optional: - session-file, dh-cert-file and kernel-hashes(since 6.2) + if params.get("vm_sev_kernel_hashes"): + sev_common_props["kernel-hashes"] = params.get_boolean( + "vm_sev_kernel_hashes" + ) + if params.get("vm_sev_device"): + sev_common_props["sev-device"] = params["vm_sev_device"] - :return: a tuple of (backend, sev-guest QObject properties dict) + return sev_common_props + + def _gen_sev_obj_props(obj_id, params): + """ + Generate the sev-guest properties, refer to SevGuestProperties """ if Flags.SEV_GUEST not in self.caps: raise ValueError("Unsupported sev-guest object") backend, sev_obj_props = "sev-guest", {"id": obj_id} + sev_opts = params.get_dict("vm_secure_guest_object_options") + if sev_opts: + sev_obj_props.update(sev_opts) + + sev_obj_props.update(_gen_sev_common_props(params)) # Set policy=3 if vm_sev_policy is not set sev_obj_props["policy"] = int(params.get("vm_sev_policy", 3)) - # FIXME: Set the following two options from sev capabilities - # if they are not set yet - sev_obj_props["cbitpos"] = int(params["vm_sev_cbitpos"]) - sev_obj_props["reduced-phys-bits"] = int(params["vm_sev_reduced_phys_bits"]) - # FIXME: If these files are host dependent, we have to find # another way to set them, because different files are needed # when migrating the vm from one host to another @@ -3969,13 +3985,24 @@ def _gen_sev_obj_props(obj_id, params): if params.get("vm_sev_dh_cert_file"): sev_obj_props["dh-cert-file"] = params["vm_sev_dh_cert_file"] - if params.get("vm_sev_kernel_hashes"): - sev_obj_props["kernel-hashes"] = params.get_boolean( - "vm_sev_kernel_hashes" - ) - return backend, sev_obj_props + def _gen_snp_obj_props(obj_id, params): + """ + Generate the sev-snp-guest properties, refer to SevSnpGuestProperties + """ + if Flags.SNP_GUEST not in self.caps: + raise ValueError('Unsupported sev-snp-guest object') + + backend, snp_obj_props = 'sev-snp-guest', {'id': obj_id} + snp_opts = params.get_dict("vm_secure_guest_object_options") + if snp_opts: + snp_obj_props.update(snp_opts) + + snp_obj_props.update(_gen_sev_common_props(params)) + + return backend, snp_obj_props + def _gen_tdx_obj_props(obj_id, params): """ Generate the properties of the tdx-guest object. @@ -3992,13 +4019,17 @@ def _gen_tdx_obj_props(obj_id, params): return backend, tdx_obj_props - obj_props_handlers = {"sev": _gen_sev_obj_props, "tdx": _gen_tdx_obj_props} + obj_props_handlers = { + "sev": _gen_sev_obj_props, + "snp": _gen_snp_obj_props, + "tdx": _gen_tdx_obj_props, + } sectype = params["vm_secure_guest_type"] if sectype in obj_props_handlers: backend, properties = obj_props_handlers[sectype](obj_id, params) else: - raise ValueError("Unsupported secure guest: %s" % sectype) + raise ValueError(f"Unsupported secure guest: {sectype}") return qdevices.QObject(backend, properties) diff --git a/virttest/qemu_vm.py b/virttest/qemu_vm.py index 0340c33cf3..e8c41bc32d 100644 --- a/virttest/qemu_vm.py +++ b/virttest/qemu_vm.py @@ -1712,8 +1712,13 @@ def add_secure_guest_descriptor(params): sectype = params["vm_secure_guest_type"] sev_mach_props = {} + snp_mach_props = {} tdx_mach_props = {} - backend_props = {"sev": sev_mach_props, "tdx": tdx_mach_props} + backend_props = { + "sev": sev_mach_props, + "snp": snp_mach_props, + "tdx": tdx_mach_props, + } for k, v in backend_props.get(sectype, {}).items(): machine_dev.set_param(k, v) diff --git a/virttest/shared/cfg/base.cfg b/virttest/shared/cfg/base.cfg index c396f09873..93fba38482 100644 --- a/virttest/shared/cfg/base.cfg +++ b/virttest/shared/cfg/base.cfg @@ -1081,12 +1081,16 @@ uuid_dimm = "" # # Set the secure guest type, or specify per-vm values (required) #vm_secure_guest_type[_vm1] = sev -# Note: The following types are supported: sev +# Note: The following types are supported: sev, snp, tdx # Disable secure guest: vm_secure_guest_type[_vm1] = "" # # Set the secure guest object options, use a blank to join more options (optional) -# TODO: Currently this param is used for tdx guest object only #vm_secure_guest_object_options[_vm1] = "debug=on mrconfigid=xx mrowner=yy" +# Note: In order to keep consistent with the original specific sev params, properties +# defined by this param can be overwriten by the original ones, e.g. +# vm_sev_policy = 3 +# vm_secure_guest_object_options = "policy=7" +# Finally the sev policy is 3. # # AMD SEV secure guest params # @@ -1094,6 +1098,8 @@ uuid_dimm = "" #vm_sev_cbitpos[_vm1] = 51 # Set the reduced-phys-bits, or specify per-vm values (required) #vm_sev_reduced_phys_bits[_vm1] = 1 +# Set the sev device, or specify per-vm values (optional) +#vm_sev_device[_vm1] = /dev/sev # Set the policy, or specify per-vm values (optional) #vm_sev_policy[_vm1] = 7 # Note: VT can set a default value 3 if vm_sev_policy is not set,