From a2b13dd8d6e0282d76a583f36965b3a00cdb7eea Mon Sep 17 00:00:00 2001
From: liupingwei <tujipei@huawei.com>
Date: Wed, 12 Jun 2024 11:39:38 +0800
Subject: [PATCH] libvirt: support the virtCCA feature Add cvm parameter into
 the type of LaunchSecurity which is a optional filed for libvirt xml. Its
 purpose is to pass the cvm parameter through to qemu. Also this patch support
 virsh edit to save cvm parameter into libvirt temporary xml.

Signed-off-by: tujipei <tujipei@huawei.com>
---
 docs/schemas/domaincommon.rng | 67 ++++++++++++++++++++---------------
 src/conf/domain_conf.c        | 25 ++++++++++---
 src/conf/domain_conf.h        |  3 ++
 src/qemu/qemu_command.c       |  2 ++
 4 files changed, 63 insertions(+), 34 deletions(-)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index e3b51d333c..a49842a9d0 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -460,35 +460,44 @@
 
   <define name="launchSecurity">
     <element name="launchSecurity">
-      <attribute name="type">
-        <value>sev</value>
-      </attribute>
-      <interleave>
-        <element name="cbitpos">
-          <data type='unsignedInt'/>
-        </element>
-        <element name="reducedPhysBits">
-          <data type='unsignedInt'/>
-        </element>
-        <element name="policy">
-          <ref name='hexuint'/>
-        </element>
-        <optional>
-          <element name="handle">
-            <ref name='unsignedInt'/>
-          </element>
-        </optional>
-        <optional>
-          <element name="dhCert">
-            <data type="string"/>
-          </element>
-        </optional>
-        <optional>
-          <element name="session">
-            <data type="string"/>
-          </element>
-        </optional>
-      </interleave>
+      <choice>
+        <group>
+          <attribute name="type">
+              <value>sev</value>
+          </attribute>
+          <interleave>
+            <element name="cbitpos">
+              <data type='unsignedInt'/>
+            </element>
+            <element name="reducedPhysBits">
+              <data type='unsignedInt'/>
+            </element>
+            <element name="policy">
+              <ref name='hexuint'/>
+            </element>
+            <optional>
+              <element name="handle">
+                <ref name='unsignedInt'/>
+              </element>
+            </optional>
+            <optional>
+              <element name="dhCert">
+                <data type="string"/>
+              </element>
+            </optional>
+            <optional>
+              <element name="session">
+                <data type="string"/>
+              </element>
+            </optional>
+          </interleave>
+        </group>
+        <group>
+          <attribute name="type">
+              <value>cvm</value>
+          </attribute>
+        </group>
+      </choice>
     </element>
   </define>
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index cf807c7747..9219d08753 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1273,6 +1273,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
               VIR_DOMAIN_LAUNCH_SECURITY_LAST,
               "",
               "sev",
+              "cvm",
 );
 
 static virClassPtr virDomainObjClass;
@@ -16823,6 +16824,7 @@ virDomainSEVDefParseXML(xmlNodePtr sevNode,
     def->sectype = virDomainLaunchSecurityTypeFromString(type);
     switch ((virDomainLaunchSecurity) def->sectype) {
     case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+    case VIR_DOMAIN_LAUNCH_SECURITY_CVM:
         break;
     case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
     case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -22169,11 +22171,19 @@ virDomainDefParseXML(xmlDocPtr xml,
     ctxt->node = node;
     VIR_FREE(nodes);
 
-    /* Check for SEV feature */
+    /* Check for CVM/SEV feature */
     if ((node = virXPathNode("./launchSecurity", ctxt)) != NULL) {
-        def->sev = virDomainSEVDefParseXML(node, ctxt);
-        if (!def->sev)
-            goto error;
+        tmp = virXMLPropString(node, "type");
+        if((virDomainLaunchSecurity)virDomainLaunchSecurityTypeFromString(tmp) == VIR_DOMAIN_LAUNCH_SECURITY_CVM) {
+            def->cvm = true;
+        } else {
+            def->sev = virDomainSEVDefParseXML(node, ctxt);
+            if(!def->sev) {
+                VIR_FREE(tmp);
+                goto error;
+            }
+        }
+        VIR_FREE(tmp);
     }
 
     /* analysis of memory devices */
@@ -29861,7 +29871,12 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def,
     if (def->keywrap)
         virDomainKeyWrapDefFormat(buf, def->keywrap);
 
-    virDomainSEVDefFormat(buf, def->sev);
+    if (def->cvm) {
+        virBufferAddLit(buf, "<launchSecurity type='cvm'>\n");
+        virBufferAddLit(buf, "</launchSecurity>\n");
+    } else {
+        virDomainSEVDefFormat(buf, def->sev);
+    }
 
     virBufferAdjustIndent(buf, -2);
     virBufferAsprintf(buf, "</%s>\n", rootname);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7419bf8d7e..180975840c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2373,6 +2373,7 @@ struct _virDomainKeyWrapDef {
 typedef enum {
     VIR_DOMAIN_LAUNCH_SECURITY_NONE,
     VIR_DOMAIN_LAUNCH_SECURITY_SEV,
+    VIR_DOMAIN_LAUNCH_SECURITY_CVM,
 
     VIR_DOMAIN_LAUNCH_SECURITY_LAST,
 } virDomainLaunchSecurity;
@@ -2586,6 +2587,8 @@ struct _virDomainDef {
 
     /* SEV-specific domain */
     virDomainSEVDefPtr sev;
+    /* CVM-specific domain */
+    bool cvm;
 
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9fcea9d46a..675a624919 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7266,6 +7266,8 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 
     if (def->sev)
         virBufferAddLit(&buf, ",memory-encryption=sev0");
+    if (def->cvm)
+        virBufferAddLit(&buf, ",kvm-type=cvm");
 
     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
         if (priv->pflash0)
-- 
2.27.0

