commit 11ab77fe88d8b8ffc4f031cd2141d393cb87bf1c
Author: Brijesh Singh <brijesh.singh@amd.com>
Date:   Fri Jun 8 09:40:58 2018 -0500

    qemu: Add support to launch an SEV guest
    
    QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
    VMs on AMD platform using SEV feature. The various inputs required to
    launch SEV guest is provided through the <launch-security> tag. A typical
    SEV guest launch command line looks like this:
    
      -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
      -machine memory-encryption=sev0 \
    
    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    Reviewed-by: Erik Skultety <eskultet@redhat.com>

JWF: Backport note: I was not able to get 'launch-security-sev' test
working so I removed the hunk adding the test to tests/qemuxml2argvtest.c
Needs investigation...

Index: libvirt-4.0.0/src/qemu/qemu_command.c
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_command.c
+++ libvirt-4.0.0/src/qemu/qemu_command.c
@@ -7631,6 +7631,9 @@ qemuBuildMachineCommandLine(virCommandPt
             virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
             qemuAppendLoadparmMachineParm(&buf, def);
 
+        if (def->sev)
+            virBufferAddLit(&buf, ",memory-encryption=sev0");
+
         virCommandAddArgBuffer(cmd, &buf);
     }
 
@@ -9935,6 +9938,41 @@ qemuBuildTPMCommandLine(virCommandPtr cm
     return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+                        virDomainSevDefPtr sev)
+{
+    virBuffer obj = VIR_BUFFER_INITIALIZER;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    char *path = NULL;
+
+    if (!sev)
+        return 0;
+
+    VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+              sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+    virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+    virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+    virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+    if (sev->dh_cert) {
+        if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+            return -1;
+        virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+        VIR_FREE(path);
+    }
+
+    if (sev->session) {
+        if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+            return -1;
+        virBufferAsprintf(&obj, ",session-file=%s", path);
+        VIR_FREE(path);
+    }
+
+    virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+    return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10380,6 +10418,9 @@ qemuBuildCommandLine(virQEMUDriverPtr dr
     if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
         goto error;
 
+    if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+        goto error;
+
     if (snapshot)
         virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
Index: libvirt-4.0.0/src/qemu/qemu_process.c
===================================================================
--- libvirt-4.0.0.orig/src/qemu/qemu_process.c
+++ libvirt-4.0.0/src/qemu/qemu_process.c
@@ -5583,6 +5583,65 @@ qemuProcessPrepareDomain(virConnectPtr c
 
 
 static int
+qemuBuildSevCreateFile(const char *configDir,
+                       const char *name,
+                       const char *data)
+{
+    char *configFile;
+
+    if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+        return -1;
+
+    if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+        virReportSystemError(errno, _("failed to write data to config '%s'"),
+                             configFile);
+        goto error;
+    }
+
+    VIR_FREE(configFile);
+    return 0;
+
+ error:
+    VIR_FREE(configFile);
+    return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr def = vm->def;
+    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+    virDomainSevDefPtr sev = def->sev;
+
+    if (!sev)
+        return 0;
+
+    VIR_DEBUG("Prepare SEV guest");
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Domain %s asked for 'sev' launch but this "
+                          "QEMU does not support SEV feature"), vm->def->name);
+        return -1;
+    }
+
+    if (sev->dh_cert) {
+        if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+            return -1;
+    }
+
+    if (sev->session) {
+        if (qemuBuildSevCreateFile(priv->libDir, "session", sev->session) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+static int
 qemuProcessPrepareHostStorage(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               unsigned int flags)
@@ -5706,6 +5765,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr
     if (qemuProcessPrepareHostStorage(driver, vm, flags) < 0)
         goto cleanup;
 
+    if (qemuProcessPrepareSevGuestInput(vm) < 0)
+        goto cleanup;
+
     ret = 0;
  cleanup:
     virObjectUnref(cfg);
Index: libvirt-4.0.0/tests/qemuxml2argvdata/launch-security-sev.args
===================================================================
--- /dev/null
+++ libvirt-4.0.0/tests/qemuxml2argvdata/launch-security-sev.args
@@ -0,0 +1,29 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-machine pc-1.0,accel=kvm,usb=off,dump-guest-core=off,memory-encryption=sev0 \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1,\
+dh-cert-file=/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64,\
+session-file=/tmp/lib/domain--1-QEMUGuest1/session.base64
Index: libvirt-4.0.0/tests/qemuxml2argvdata/launch-security-sev.xml
===================================================================
--- /dev/null
+++ libvirt-4.0.0/tests/qemuxml2argvdata/launch-security-sev.xml
@@ -0,0 +1,37 @@
+<domain type='kvm'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc-1.0'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+  <launch-security type='sev'>
+    <cbitpos>47</cbitpos>
+    <reduced-phys-bits>1</reduced-phys-bits>
+    <policy>0x0001</policy>
+    <dh-cert>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</dh-cert>
+    <session>IHAVENOIDEABUTJUSTPROVIDINGASTRING</session>
+  </launch-security>
+</domain>
