[RFC PATCH 3/7] target/i386: SEV: Add support for enabling debug-swap SEV feature

Naveen N Rao (AMD)
2025-09-11T11:57:38Z

Add support for enabling debug-swap VMSA SEV feature in SEV-ES and
SEV-SNP guests through a new "debug-swap" boolean property on SEV guest
objects. Though the boolean property is available for plain SEV guests,
check_sev_features() will reject setting this for plain SEV guests.

Add helpers for setting and querying the VMSA SEV features so that they
can be re-used for subsequent VMSA SEV features, and convert the
existing SVM_SEV_FEAT_SNP_ACTIVE definition to use the BIT() macro for
consistency with the new feature flag.

Sample command-line:
-machine q35,confidential-guest-support=sev0 \
-object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1,debug-swap=on

Signed-off-by: Naveen N Rao (AMD) <naveen@kernel.org>
---
target/i386/sev.h | 3 ++-
target/i386/sev.c | 29 +++++++++++++++++++++++++++++
qapi/qom.json | 6 +++++-
3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/target/i386/sev.h b/target/i386/sev.h
index 9db1a802f6bb..8e09b2ce1976 100644
--- a/target/i386/sev.h
+++ b/target/i386/sev.h
@@ -44,7 +44,8 @@ bool sev_snp_enabled(void);
#define SEV_SNP_POLICY_SMT 0x10000
#define SEV_SNP_POLICY_DBG 0x80000

-#define SVM_SEV_FEAT_SNP_ACTIVE 1
+#define SVM_SEV_FEAT_SNP_ACTIVE BIT(0)
+#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)

typedef struct SevKernelLoaderContext {
char *setup_data;
diff --git a/target/i386/sev.c b/target/i386/sev.c
index fa23b5c38e9b..b3e4d0f2c1d5 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -319,6 +319,20 @@ sev_set_guest_state(SevCommonState *sev_common, SevState new_state)
sev_common->state = new_state;
}

+static bool is_sev_feature_set(SevCommonState *sev_common, uint64_t feature)
+{
+ return !!(sev_common->sev_features & feature);
+}
+
+static void sev_set_feature(SevCommonState *sev_common, uint64_t feature, bool value)
+{
+ if (value) {
+ sev_common->sev_features |= feature;
+ } else {
+ sev_common->sev_features &= ~feature;
+ }
+}
+
static void
sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
size_t max_size)
@@ -2732,6 +2746,16 @@ static int cgs_set_guest_policy(ConfidentialGuestPolicyType policy_type,
return 0;
}

+static bool sev_common_get_debug_swap(Object *obj, Error **errp)
+{
+ return is_sev_feature_set(SEV_COMMON(obj), SVM_SEV_FEAT_DEBUG_SWAP);
+}
+
+static void sev_common_set_debug_swap(Object *obj, bool value, Error **errp)
+{
+ sev_set_feature(SEV_COMMON(obj), SVM_SEV_FEAT_DEBUG_SWAP, value);
+}
+
static void
sev_common_class_init(ObjectClass *oc, const void *data)
{
@@ -2749,6 +2773,11 @@ sev_common_class_init(ObjectClass *oc, const void *data)
sev_common_set_kernel_hashes);
object_class_property_set_description(oc, "kernel-hashes",
"add kernel hashes to guest firmware for measured Linux boot");
+ object_class_property_add_bool(oc, "debug-swap",
+ sev_common_get_debug_swap,
+ sev_common_set_debug_swap);
+ object_class_property_set_description(oc, "debug-swap",
+ "enable virtualization of debug registers");
}

static void
diff --git a/qapi/qom.json b/qapi/qom.json
index 830cb2ffe781..71cd8ad588b5 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -1010,13 +1010,17 @@
# designated guest firmware page for measured boot with -kernel
# (default: false) (since 6.2)
#
+# @debug-swap: enable virtualization of debug registers (default: false)
+# (since 10.2)
+#
# Since: 9.1
##
{ 'struct': 'SevCommonProperties',
'data': { '*sev-device': 'str',
'*cbitpos': 'uint32',
'reduced-phys-bits': 'uint32',
- '*kernel-hashes': 'bool' } }
+ '*kernel-hashes': 'bool',
+ '*debug-swap': 'bool' } }

##
# @SevGuestProperties:
--
2.50.1