All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD)
@ 2016-09-13 14:46 Brijesh Singh
  2016-09-13 14:46 ` [Qemu-devel] [RFC PATCH v1 01/22] exec: add guest RAM read/write ops Brijesh Singh
                   ` (23 more replies)
  0 siblings, 24 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:46 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

This RFC series provides support for AMD's new Secure Encrypted 
Virtualization (SEV) feature. This RFC is based KVM RFC [1].

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. The SEV feature allows
the memory contents of a virtual machine (VM) to be transparently encrypted
with a key unique to the guest VM. The memory controller contains a
high performance encryption engine which can be programmed with multiple
keys for use by a different VMs in the system. The programming and
management of these keys is handled by the AMD Secure Processor firmware
which exposes a commands for these tasks.

SEV is designed to protect guest VMs from a benign but vulnerable
(i.e. not fully malicious) hypervisor. In particular, it reduces the attack
surface of guest VMs and can prevent certain types of VM-escape bugs
(e.g. hypervisor read-anywhere) from being used to steal guest data.

The KVM RFC introduced a new ioctl (KVM_SEV_ISSUE_CMD) which can be
used by qemu to enable SEV for secure guest and assist performing common
hypervisor activities such as a launching, running, snapshooting, migration
and debugging a guests data.


The following links provide additional details:

AMD Memory Encryption whitepaper:
 
http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
    http://support.amd.com/TechDocs/24593.pdf
    SME is section 7.10
    SEV is section 15.34

Secure Encrypted Virutualization Key Management:
http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf

KVM Forum slides:
http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf

KVM RFC link:

[1] http://marc.info/?l=kvm&m=147191038624432&w=2

---

TODO:
- send seabios RFC's on seabios mailing list
- implement SEV guest migration command support
- implement SEV snapshotting command support
- virtio support in SEV guest

Brijesh Singh (22):
      exec: add guest RAM read/write ops
      cpu-common: add debug version of physical memory read/write
      monitor: use debug version of physical memory read api
      memattrs: add SEV debug attrs
      i386: add new option to enable SEV guest
      sev: add initial SEV support
      sev: add SEV launch start command
      sev: add SEV launch update command
      sev: add SEV launch finish command
      sev: add SEV debug decrypt command
      sev: add SEV debug encrypt command
      sev: add SEV guest status command
      hmp: update 'info kvm' to display SEV status
      sev: provide SEV-enabled guest RAM read/write ops
      i386: sev: register RAM read/write ops for BIOS and PC.RAM region
      i386: pc: load OS images at fixed location in SEV-enabled guest
      target-i386: add cpuid Fn8000_001f
      i386: clear C-bit in SEV guest page table walk
      exec: set debug attribute in SEV-enabled guest
      fw_cfg: sev: disable dma in real mode
      hw: add pre and post system reset callback
      loader: reload bios image on ROM reset in SEV-enabled guest


 Makefile.target           |    2 
 disas.c                   |    2 
 exec.c                    |  323 ++++++++++++++++++++-----
 hmp.c                     |   14 +
 hw/core/loader.c          |    7 -
 hw/i386/pc.c              |   99 ++++++++
 hw/i386/pc_sysfw.c        |    6 
 hw/nvram/fw_cfg.c         |    6 
 include/exec/cpu-common.h |   12 +
 include/exec/memattrs.h   |    4 
 include/exec/memory.h     |   25 ++
 include/hw/hw.h           |    2 
 include/sysemu/kvm.h      |   10 +
 include/sysemu/sev.h      |  104 ++++++++
 kvm-all.c                 |    6 
 monitor.c                 |    2 
 qapi-schema.json          |    4 
 qemu-options.hx           |    6 
 qmp.c                     |    1 
 sev.c                     |  574 +++++++++++++++++++++++++++++++++++++++++++++
 target-i386/cpu.c         |    3 
 target-i386/helper.c      |   36 ++-
 target-i386/monitor.c     |   50 +++-
 vl.c                      |   74 ++++++
 24 files changed, 1288 insertions(+), 84 deletions(-)
 create mode 100644 include/sysemu/sev.h
 create mode 100644 sev.c

-- 

Brijesh Singh

^ permalink raw reply	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 01/22] exec: add guest RAM read/write ops
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
@ 2016-09-13 14:46 ` Brijesh Singh
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 02/22] cpu-common: add debug version of physical memory read/write Brijesh Singh
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:46 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

In current implementation, read and write of the guest RAM is
performed using using memcpy(). This patch adds support to register
a callback which can override the memcpy() with something else.

This feature will be used in Secure Encrypted Virtualization (SEV)
guests in which read and write of guest memory should be performed
using the SEV commands.

a typical usage:

mem_read(uint8_t *dst, uint8_t *src, uint32_t len, MemTxAttrs *attrs);
mem_write(uint8_t *dst, uint8_t *src, uint32_t len, MemTxAttrs *attrs);

MemoryRegionRAMReadWriteOps ops;
ops.read = mem_read;
ops.write = mem_write;

memory_region_init_ram(mem, NULL, "memory", size, NULL);
memory_region_set_ram_ops(mem, ops);

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 exec.c                |  304 +++++++++++++++++++++++++++++++++++++++----------
 include/exec/memory.h |   25 ++++
 2 files changed, 266 insertions(+), 63 deletions(-)

diff --git a/exec.c b/exec.c
index 8ffde75..d0f45b4 100644
--- a/exec.c
+++ b/exec.c
@@ -2563,6 +2563,11 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
             /* RAM case */
             ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
             memcpy(ptr, buf, l);
+            if (mr->ram_ops) {
+                mr->ram_ops->write(ptr, buf, l, attrs);
+            } else {
+                memcpy(ptr, buf, l);
+            }
             invalidate_and_set_dirty(mr, addr1, l);
         }
 
@@ -2653,7 +2658,10 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
         } else {
             /* RAM case */
             ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-            memcpy(buf, ptr, l);
+            if (mr->ram_ops)
+                mr->ram_ops->read(buf, ptr, l, attrs);
+            else
+                memcpy(buf, ptr, l);
         }
 
         if (release_lock) {
@@ -2719,7 +2727,8 @@ enum write_rom_type {
 };
 
 static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
-    hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
+    hwaddr addr, const uint8_t *buf, int len, MemTxAttrs attrs,
+    enum write_rom_type type)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -2739,7 +2748,11 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
             ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
             switch (type) {
             case WRITE_DATA:
-                memcpy(ptr, buf, l);
+                if (mr->ram_ops) {
+                    mr->ram_ops->write(ptr, buf, l, attrs);
+                } else {
+                    memcpy(ptr, buf, l);
+                }
                 invalidate_and_set_dirty(mr, addr1, l);
                 break;
             case FLUSH_CACHE:
@@ -2758,7 +2771,8 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
 void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
                                    const uint8_t *buf, int len)
 {
-    cpu_physical_memory_write_rom_internal(as, addr, buf, len, WRITE_DATA);
+    cpu_physical_memory_write_rom_internal(as, addr, buf, len,
+            MEMTXATTRS_UNSPECIFIED, WRITE_DATA);
 }
 
 void cpu_flush_icache_range(hwaddr start, int len)
@@ -2774,7 +2788,9 @@ void cpu_flush_icache_range(hwaddr start, int len)
     }
 
     cpu_physical_memory_write_rom_internal(&address_space_memory,
-                                           start, NULL, len, FLUSH_CACHE);
+                                           start, NULL, len,
+                                           MEMTXATTRS_UNSPECIFIED,
+                                           FLUSH_CACHE);
 }
 
 typedef struct {
@@ -2998,6 +3014,47 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
     return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len);
 }
 
+#if defined(HOST_WORDS_BIGENDIAN)
+#define be_bswap(v, size) (v)
+#define le_bswap(v, size) glue(bswap, size)(v)
+#else
+#define le_bswap(v, size) (v)
+#define be_bswap(v, size) glue(bswap, size)(v)
+#endif
+
+static inline uint64_t rw_ops_ldq_internal(MemoryRegion *mr,
+                                           const uint8_t *ptr,
+                                           MemTxResult *ret,
+                                           MemTxAttrs attrs,
+                                           enum device_endian endian)
+{
+    uint64_t val;
+    uint64_t dst;
+
+    if (mr->ram_ops->read((uint8_t *)&dst, ptr, 8, attrs)) {
+        *ret = MEMTX_ERROR;
+        return 0;
+    }
+
+    switch (endian) {
+    case DEVICE_LITTLE_ENDIAN:
+        val = le_bswap(dst, 64);
+        break;
+    case DEVICE_BIG_ENDIAN:
+        val = be_bswap(dst, 64);
+        break;
+    default:
+#if defined(TARGET_WORDS_BIGENDIAN)
+        val = be_bswap(dst, 64);
+#else
+        val = le_bswap(dst, 64);
+#endif
+        break;
+    }
+
+    return val;
+}
+
 /* warning: addr must be aligned */
 static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
                                                   MemTxAttrs attrs,
@@ -3031,16 +3088,20 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
     } else {
         /* RAM case */
         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-        switch (endian) {
-        case DEVICE_LITTLE_ENDIAN:
-            val = ldl_le_p(ptr);
-            break;
-        case DEVICE_BIG_ENDIAN:
-            val = ldl_be_p(ptr);
-            break;
-        default:
-            val = ldl_p(ptr);
-            break;
+        if (mr->ram_ops) {
+            val = rw_ops_ldq_internal(mr, ptr, &r, attrs, endian);
+        } else {
+            switch (endian) {
+            case DEVICE_LITTLE_ENDIAN:
+                val = ldl_le_p(ptr);
+                break;
+            case DEVICE_BIG_ENDIAN:
+                val = ldl_be_p(ptr);
+                break;
+            default:
+                val = ldl_p(ptr);
+                break;
+            }
         }
         r = MEMTX_OK;
     }
@@ -3124,16 +3185,20 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
     } else {
         /* RAM case */
         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-        switch (endian) {
-        case DEVICE_LITTLE_ENDIAN:
-            val = ldq_le_p(ptr);
-            break;
-        case DEVICE_BIG_ENDIAN:
-            val = ldq_be_p(ptr);
-            break;
-        default:
-            val = ldq_p(ptr);
-            break;
+        if (mr->ram_ops) {
+            val = rw_ops_ldq_internal(mr, ptr, &r, attrs, endian);
+        } else {
+            switch (endian) {
+            case DEVICE_LITTLE_ENDIAN:
+                val = ldq_le_p(ptr);
+                break;
+            case DEVICE_BIG_ENDIAN:
+                val = ldq_be_p(ptr);
+                break;
+            default:
+                val = ldq_p(ptr);
+                break;
+            }
         }
         r = MEMTX_OK;
     }
@@ -3202,6 +3267,39 @@ uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
     return address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
+static inline uint16_t rw_ops_lduw_internal(MemoryRegion *mr,
+                                            const uint8_t *ptr,
+                                            MemTxResult *ret,
+                                            MemTxAttrs attrs,
+                                            enum device_endian endian)
+{
+    uint64_t val;
+    uint64_t dst;
+
+    if (mr->ram_ops->read((uint8_t *)&dst, ptr, 2, attrs)) {
+        *ret = MEMTX_ERROR;
+        return 0;
+    }
+
+    switch (endian) {
+    case DEVICE_LITTLE_ENDIAN:
+        val = le_bswap(dst, 16);
+        break;
+    case DEVICE_BIG_ENDIAN:
+        val = be_bswap(dst, 16);
+        break;
+    default:
+#if defined(TARGET_WORDS_BIGENDIAN)
+        val = be_bswap(dst, 16);
+#else
+        val = le_bswap(dst, 16);
+#endif
+        break;
+    }
+
+    return (uint16_t) val;
+}
+
 /* warning: addr must be aligned */
 static inline uint32_t address_space_lduw_internal(AddressSpace *as,
                                                    hwaddr addr,
@@ -3237,16 +3335,20 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as,
     } else {
         /* RAM case */
         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-        switch (endian) {
-        case DEVICE_LITTLE_ENDIAN:
-            val = lduw_le_p(ptr);
-            break;
-        case DEVICE_BIG_ENDIAN:
-            val = lduw_be_p(ptr);
-            break;
-        default:
-            val = lduw_p(ptr);
-            break;
+        if (mr->ram_ops) {
+            val = rw_ops_lduw_internal(mr, ptr, &r, attrs, endian);
+        } else {
+            switch (endian) {
+            case DEVICE_LITTLE_ENDIAN:
+                val = lduw_le_p(ptr);
+                break;
+            case DEVICE_BIG_ENDIAN:
+                val = lduw_be_p(ptr);
+                break;
+            default:
+                val = lduw_p(ptr);
+                break;
+            }
         }
         r = MEMTX_OK;
     }
@@ -3341,6 +3443,37 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
     address_space_stl_notdirty(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
+static inline void rw_ops_stl_internal(MemoryRegion *mr, MemTxResult *r,
+                                       uint8_t *ptr, uint32_t val,
+                                       MemTxAttrs attrs,
+                                       enum device_endian endian)
+{
+    uint32_t data;
+
+    switch (endian) {
+    case DEVICE_LITTLE_ENDIAN:
+        data = le_bswap(val, 32);
+        break;
+    case DEVICE_BIG_ENDIAN:
+        data = be_bswap(val, 32);
+        break;
+    default:
+#if defined(TARGET_WORDS_BIGENDIAN)
+        data = be_bswap(val, 32);
+#else
+        data = le_bswap(val, 32);
+#endif
+        break;
+    }
+
+    if (mr->ram_ops->write(ptr, (uint8_t *)&data, 4, attrs)) {
+        *r = MEMTX_ERROR;
+        return;
+    }
+
+    *r = MEMTX_OK;
+}
+
 /* warning: addr must be aligned */
 static inline void address_space_stl_internal(AddressSpace *as,
                                               hwaddr addr, uint32_t val,
@@ -3374,19 +3507,26 @@ static inline void address_space_stl_internal(AddressSpace *as,
     } else {
         /* RAM case */
         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-        switch (endian) {
-        case DEVICE_LITTLE_ENDIAN:
-            stl_le_p(ptr, val);
-            break;
-        case DEVICE_BIG_ENDIAN:
-            stl_be_p(ptr, val);
-            break;
-        default:
-            stl_p(ptr, val);
-            break;
+        if (mr->ram_ops) {
+            rw_ops_stl_internal(mr, &r, ptr, val, attrs, endian);
+            if (r == MEMTX_OK) {
+                invalidate_and_set_dirty(mr, addr1, 4);
+            }
+        } else {
+            switch (endian) {
+            case DEVICE_LITTLE_ENDIAN:
+                stl_le_p(ptr, val);
+                break;
+            case DEVICE_BIG_ENDIAN:
+                stl_be_p(ptr, val);
+                break;
+            default:
+                stl_p(ptr, val);
+                break;
+            }
+            invalidate_and_set_dirty(mr, addr1, 4);
+            r = MEMTX_OK;
         }
-        invalidate_and_set_dirty(mr, addr1, 4);
-        r = MEMTX_OK;
     }
     if (result) {
         *result = r;
@@ -3451,6 +3591,37 @@ void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
     address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
+static inline void rw_ops_stw_internal(MemoryRegion *mr, MemTxResult *r,
+                                       uint8_t *ptr, uint32_t val,
+                                       MemTxAttrs attrs,
+                                       enum device_endian endian)
+{
+    uint32_t data;
+
+    switch (endian) {
+    case DEVICE_LITTLE_ENDIAN:
+        data = le_bswap(val, 16);
+        break;
+    case DEVICE_BIG_ENDIAN:
+        data = be_bswap(val, 16);
+        break;
+    default:
+#if defined(TARGET_WORDS_BIGENDIAN)
+        data = be_bswap(val, 16);
+#else
+        data = le_bswap(val, 16);
+#endif
+        break;
+    }
+
+    if (mr->ram_ops->write(ptr, (uint8_t *)&data, 2, attrs)) {
+        *r = MEMTX_ERROR;
+        return;
+    }
+
+    *r = MEMTX_OK;
+}
+
 /* warning: addr must be aligned */
 static inline void address_space_stw_internal(AddressSpace *as,
                                               hwaddr addr, uint32_t val,
@@ -3483,19 +3654,26 @@ static inline void address_space_stw_internal(AddressSpace *as,
     } else {
         /* RAM case */
         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-        switch (endian) {
-        case DEVICE_LITTLE_ENDIAN:
-            stw_le_p(ptr, val);
-            break;
-        case DEVICE_BIG_ENDIAN:
-            stw_be_p(ptr, val);
-            break;
-        default:
-            stw_p(ptr, val);
-            break;
+        if (mr->ram_ops) {
+            rw_ops_stw_internal(mr, &r, ptr, val, attrs, endian);
+            if (r == MEMTX_OK) {
+                invalidate_and_set_dirty(mr, addr1, 2);
+            }
+        } else {
+            switch (endian) {
+            case DEVICE_LITTLE_ENDIAN:
+                stw_le_p(ptr, val);
+                break;
+            case DEVICE_BIG_ENDIAN:
+                stw_be_p(ptr, val);
+                break;
+            default:
+                stw_p(ptr, val);
+                break;
+            }
+            invalidate_and_set_dirty(mr, addr1, 2);
+            r = MEMTX_OK;
         }
-        invalidate_and_set_dirty(mr, addr1, 2);
-        r = MEMTX_OK;
     }
     if (result) {
         *result = r;
@@ -3613,12 +3791,12 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
             l = len;
         phys_addr += (addr & ~TARGET_PAGE_MASK);
         if (is_write) {
-            cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
-                                          phys_addr, buf, l);
+            cpu_physical_memory_write_rom_internal(cpu->cpu_ases[asidx].as,
+                                          phys_addr, buf, l, attrs,
+                                          WRITE_DATA);
         } else {
             address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
-                             MEMTXATTRS_UNSPECIFIED,
-                             buf, l, 0);
+                             attrs, buf, l, 0);
         }
         len -= l;
         buf += l;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 3e4d416..80af3b0 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -146,6 +146,18 @@ struct MemoryRegionOps {
     const MemoryRegionMmio old_mmio;
 };
 
+/* Memory Region RAM callback */
+typedef struct MemoryRegionRAMReadWriteOps MemoryRegionRAMReadWriteOps;
+
+struct MemoryRegionRAMReadWriteOps {
+    /* Write data into guest memory */
+    int (*write) (uint8_t *dest, const uint8_t *src,
+                  uint32_t len, MemTxAttrs attrs);
+    /* Read data from guest memory */
+    int (*read) (uint8_t *dest, const uint8_t *src,
+                 uint32_t len, MemTxAttrs attrs);
+};
+
 typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
 
 struct MemoryRegionIOMMUOps {
@@ -179,6 +191,7 @@ struct MemoryRegion {
     RAMBlock *ram_block;
     Object *owner;
     const MemoryRegionIOMMUOps *iommu_ops;
+    const MemoryRegionRAMReadWriteOps *ram_ops;
 
     const MemoryRegionOps *ops;
     void *opaque;
@@ -506,6 +519,18 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
 }
 
 /**
+ * memory_region_set_ram_ops: Set the Read/Write ops for accessing the RAM
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that will be used to read/write @target region
+ */
+static inline void memory_region_set_ram_ops(MemoryRegion *mr,
+                               const MemoryRegionRAMReadWriteOps *ops)
+{
+    mr->ram_ops = ops;
+}
+
+/**
  * memory_region_init_iommu: Initialize a memory region that translates
  * addresses
  *

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 02/22] cpu-common: add debug version of physical memory read/write
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
  2016-09-13 14:46 ` [Qemu-devel] [RFC PATCH v1 01/22] exec: add guest RAM read/write ops Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 03/22] monitor: use debug version of physical memory read api Brijesh Singh
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The patch adds the following new APIs:
- cpu_physical_memory_read_debug
- cpu_physical_memory_write_debug

These API's can be used when reading/writing guest physical memory for
debugging purposes. In next patch will update the hmp monitor memory
dump commands (xp, info mem, info tlb etc) to use this API instead of
cpu_physical_memory_read() to access the guest physical memory.

The idea behind this patch is that in case of SEV-enabled guest we
need a method to identify whether the memory access is for debug
purposes.

If all the debug access requests are done through these API's then
we can create/set special sev specific MemTxAttrs to indicate that
RAM access is for debugg purposes and use SEV debug commands to
read and write guest memory for debug purposes.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 exec.c                    |   10 ++++++++++
 include/exec/cpu-common.h |   12 ++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/exec.c b/exec.c
index d0f45b4..604bd05 100644
--- a/exec.c
+++ b/exec.c
@@ -3768,6 +3768,16 @@ void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
     address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+                                  int len, int is_write)
+{
+    MemTxAttrs attrs;
+
+    attrs = MEMTXATTRS_UNSPECIFIED;
+
+    address_space_rw(&address_space_memory, addr, attrs, buf, len, is_write);
+}
+
 /* virtual memory access for debug (includes writing to ROM) */
 int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 952bcfe..1ebd9aa 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -61,6 +61,8 @@ const char *qemu_ram_get_idstr(RAMBlock *rb);
 
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
                             int len, int is_write);
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+                                  int len, int is_write);
 static inline void cpu_physical_memory_read(hwaddr addr,
                                             void *buf, int len)
 {
@@ -71,6 +73,16 @@ static inline void cpu_physical_memory_write(hwaddr addr,
 {
     cpu_physical_memory_rw(addr, (void *)buf, len, 1);
 }
+static inline void cpu_physical_memory_read_debug(hwaddr addr,
+                                                  void *buf, int len)
+{
+    cpu_physical_memory_rw_debug(addr, buf, len, 0);
+}
+static inline void cpu_physical_memory_write_debug(hwaddr addr,
+                                                   const void *buf, int len)
+{
+    cpu_physical_memory_rw_debug(addr, (void *)buf, len, 1);
+}
 void *cpu_physical_memory_map(hwaddr addr,
                               hwaddr *plen,
                               int is_write);

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 03/22] monitor: use debug version of physical memory read api
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
  2016-09-13 14:46 ` [Qemu-devel] [RFC PATCH v1 01/22] exec: add guest RAM read/write ops Brijesh Singh
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 02/22] cpu-common: add debug version of physical memory read/write Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs Brijesh Singh
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

This patch updates hmp monitor to use cpu_physical_memory_read_debug()
when accessing the guest memory for debug dumps.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 disas.c               |    2 +-
 monitor.c             |    2 +-
 target-i386/monitor.c |   18 ++++++++++--------
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/disas.c b/disas.c
index 05a7a12..382cc2c 100644
--- a/disas.c
+++ b/disas.c
@@ -356,7 +356,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
     CPUDebug *s = container_of(info, CPUDebug, info);
 
     if (monitor_disas_is_physical) {
-        cpu_physical_memory_read(memaddr, myaddr, length);
+        cpu_physical_memory_read_debug(memaddr, myaddr, length);
     } else {
         cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
     }
diff --git a/monitor.c b/monitor.c
index 5c00373..4773ee1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1299,7 +1299,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
         if (l > line_size)
             l = line_size;
         if (is_physical) {
-            cpu_physical_memory_read(addr, buf, l);
+            cpu_physical_memory_read_debug(addr, buf, l);
         } else {
             if (cpu_memory_rw_debug(mon_get_cpu(), addr, buf, l, 0) < 0) {
                 monitor_printf(mon, " Cannot access memory\n");
diff --git a/target-i386/monitor.c b/target-i386/monitor.c
index fccfe40..47d3c2d 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -130,12 +130,12 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
 
     pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
     for (l1 = 0; l1 < 512; l1++) {
-        cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+        cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
         pml4e = le64_to_cpu(pml4e);
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+                cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
                 pdpe = le64_to_cpu(pdpe);
                 if (pdpe & PG_PRESENT_MASK) {
                     if (pdpe & PG_PSE_MASK) {
@@ -145,7 +145,8 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
                     } else {
                         pd_addr = pdpe & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+                            cpu_physical_memory_read_debug(pd_addr + l3 * 8,
+                                    &pde, 8);
                             pde = le64_to_cpu(pde);
                             if (pde & PG_PRESENT_MASK) {
                                 if (pde & PG_PSE_MASK) {
@@ -156,7 +157,7 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
                                 } else {
                                     pt_addr = pde & 0x3fffffffff000ULL;
                                     for (l4 = 0; l4 < 512; l4++) {
-                                        cpu_physical_memory_read(pt_addr
+                                        cpu_physical_memory_read_debug(pt_addr
                                                                  + l4 * 8,
                                                                  &pte, 8);
                                         pte = le64_to_cpu(pte);
@@ -335,13 +336,13 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 512; l1++) {
-        cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+        cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
         pml4e = le64_to_cpu(pml4e);
         end = l1 << 39;
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+                cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
                 pdpe = le64_to_cpu(pdpe);
                 end = (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
@@ -353,7 +354,8 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
                     } else {
                         pd_addr = pdpe & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+                            cpu_physical_memory_read_debug(pd_addr + l3 * 8,
+                                    &pde, 8);
                             pde = le64_to_cpu(pde);
                             end = (l1 << 39) + (l2 << 30) + (l3 << 21);
                             if (pde & PG_PRESENT_MASK) {
@@ -365,7 +367,7 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
                                 } else {
                                     pt_addr = pde & 0x3fffffffff000ULL;
                                     for (l4 = 0; l4 < 512; l4++) {
-                                        cpu_physical_memory_read(pt_addr
+                                        cpu_physical_memory_read_debug(pt_addr
                                                                  + l4 * 8,
                                                                  &pte, 8);
                                         pte = le64_to_cpu(pte);

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (2 preceding siblings ...)
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 03/22] monitor: use debug version of physical memory read api Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 23:00   ` Paolo Bonzini
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest Brijesh Singh
                   ` (19 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The patch adds sev_debug_mode attribute in MemTxAttrs. This attribute
will be set when debug version of memory read/write API's are used in
SEV-enabled guest.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/exec/memattrs.h |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index e601061..5aa22b5 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -37,6 +37,8 @@ typedef struct MemTxAttrs {
     unsigned int user:1;
     /* Requester ID (for MSI for example) */
     unsigned int requester_id:16;
+    /* Memory access for debug purposes */
+    unsigned int sev_debug:1;
 } MemTxAttrs;
 
 /* Bus masters which don't specify any attributes will get this,
@@ -46,4 +48,6 @@ typedef struct MemTxAttrs {
  */
 #define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
 
+/* Access the guest memory for debug purposes */
+#define MEMTXATTRS_SEV_DEBUG ((MemTxAttrs) { .sev_debug = 1 })
 #endif

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (3 preceding siblings ...)
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 22:41   ` Paolo Bonzini
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support Brijesh Singh
                   ` (18 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The patch adds '-sev' option to enable the Secure Encrypted
Virtualization (SEV) guest. If this option is specified, Qemu
assumes that user wants to launch this guest into SEV mode.

Here are example on how to launch a guest into SEV mode.

1) late launch: in this mode the images received from guest
owner are unencrypted and must be encrypted using SEV LAUNCH command
before starting the guest.

$ qemu -sev type=unencrypted config=guest_01.conf

2) pre-encrypted: in this mode the images received from guest
owners are encrypted using transport keys. It must be re-encrypted
using SEV RECEIVE commands before starting the guest.

$ qemu -sev type=encrypted config=guest_02.conf

The config file will contains various parameters (e.g key , policy)
required during guest launch process.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 qemu-options.hx |    6 ++++++
 vl.c            |   29 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index a71aaf8..1b6aa82 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -118,6 +118,12 @@ given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
 specifies the maximum number of hotpluggable CPUs.
 ETEXI
 
+DEF("sev", HAS_ARG, QEMU_OPTION_sev,
+    "-sev type=[encrypted,unencrypted] config=<file>\n"
+    "                image type (encrypted or unencrypted)\n"
+    "                set the config file for SEV guest\n",
+        QEMU_ARCH_I386)
+
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
     "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n"
     "-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index b3c80d5..22b8eba 100644
--- a/vl.c
+++ b/vl.c
@@ -178,6 +178,7 @@ bool boot_strict;
 uint8_t *boot_splash_filedata;
 size_t boot_splash_filedata_size;
 uint8_t qemu_extra_params_fw[2];
+static bool sev_allowed;
 
 int icount_align_option;
 
@@ -506,6 +507,25 @@ static QemuOptsList qemu_fw_cfg_opts = {
     },
 };
 
+static QemuOptsList qemu_sev_opts = {
+    .name = "sev",
+    .implied_opt_name = "name",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_sev_opts.head),
+    .desc = {
+        {
+            .name = "config",
+            .type = QEMU_OPT_STRING,
+            .help = "Set the SEV config file\n",
+        },
+        {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+            .help = "Set the image type (encrypted or unencrypted)\n",
+        },
+        { /* end of list */ }
+    },
+};
+
 /**
  * Get machine options
  *
@@ -3002,6 +3022,7 @@ int main(int argc, char **argv, char **envp)
     qemu_add_opts(&qemu_icount_opts);
     qemu_add_opts(&qemu_semihosting_config_opts);
     qemu_add_opts(&qemu_fw_cfg_opts);
+    qemu_add_opts(&qemu_sev_opts);
     module_call_init(MODULE_INIT_OPTS);
 
     runstate_init();
@@ -3970,6 +3991,14 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_sev:
+                olist = qemu_find_opts("sev");
+                opts = qemu_opts_parse_noisily(olist, optarg, true);
+                if (!opts) {
+                    exit(1);
+                }
+                sev_allowed = true;
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (4 preceding siblings ...)
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 15:58   ` Eduardo Habkost
  2016-09-14  8:37   ` Daniel P. Berrange
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 07/22] sev: add SEV launch start command Brijesh Singh
                   ` (17 subsequent siblings)
  23 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

This patch adds the initial support required to integrate Secure
Encrypted Virtualization feature, the patch include the following
changes:

- adds sev.c and sev.h files: the file will contain SEV APIs implemention.
- add kvm_sev_enabled(): similar to kvm_enabled() this function can be
  used to check if sev is enabled on this guest.
- implement functions to parse SEV specific configuration file.

A typical SEV config file looks like this:

[sev-launch]
	flags = "00000000"
	policy	= "000000"
	dh_pub_qx = "0123456789abcdef0123456789abcdef"
	dh_pub_qy = "0123456789abcdef0123456789abcdef"
	nonce = "0123456789abcdef"
	vcpu_count = "1"
	vcpu_length = "30"
	vcpu_mask = "00ab"


Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 Makefile.target      |    2 
 include/sysemu/kvm.h |   10 ++
 include/sysemu/sev.h |   27 +++++
 kvm-all.c            |    6 +
 sev.c                |  282 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 326 insertions(+), 1 deletion(-)
 create mode 100644 include/sysemu/sev.h
 create mode 100644 sev.c

diff --git a/Makefile.target b/Makefile.target
index a440bcb..74ad204 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -136,7 +136,7 @@ ifdef CONFIG_SOFTMMU
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
 obj-y += qtest.o bootdevice.o
 obj-y += hw/
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
 obj-y += memory.o cputlb.o
 obj-y += memory_mapping.o
 obj-y += dump.o
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index c9c2436..7f83de0 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -40,6 +40,7 @@
 #endif
 
 extern bool kvm_allowed;
+extern bool kvm_sev_allowed;
 extern bool kvm_kernel_irqchip;
 extern bool kvm_split_irqchip;
 extern bool kvm_async_interrupts_allowed;
@@ -56,6 +57,14 @@ extern bool kvm_ioeventfd_any_length_allowed;
 
 #if defined CONFIG_KVM || !defined NEED_CPU_H
 #define kvm_enabled()           (kvm_allowed)
+
+/**
+ * kvm_sev_enabled:
+ *
+ * Returns: true if guest is running into SEV-enabled mode.
+ */
+#define kvm_sev_enabled()       (kvm_sev_allowed)
+
 /**
  * kvm_irqchip_in_kernel:
  *
@@ -171,6 +180,7 @@ extern bool kvm_ioeventfd_any_length_allowed;
 
 #else
 #define kvm_enabled()           (0)
+#define kvm_sev_enabled()       (false)
 #define kvm_irqchip_in_kernel() (false)
 #define kvm_irqchip_is_split() (false)
 #define kvm_async_interrupts_enabled() (false)
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 0000000..0ee8aff
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,27 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright: Advanced Micro Devices, 2016
+ *
+ * Authors:
+ *  Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_SEV_H
+#define QEMU_SEV_H
+
+#include "sysemu/kvm.h"
+
+/**
+ * sev_init - initialize Secure Encrypted Virtualization on this guest
+ * @kvm_state - KVM handle
+ * Returns: 1 on error, 0 on success
+ */
+int sev_init(KVMState *kvm_state);
+
+#endif
+
diff --git a/kvm-all.c b/kvm-all.c
index ebf35b0..e194849 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -36,6 +36,7 @@
 #include "qemu/event_notifier.h"
 #include "trace.h"
 #include "hw/irq.h"
+#include "sysemu/sev.h"
 
 #include "hw/boards.h"
 
@@ -119,6 +120,7 @@ bool kvm_readonly_mem_allowed;
 bool kvm_vm_attributes_allowed;
 bool kvm_direct_msi_allowed;
 bool kvm_ioeventfd_any_length_allowed;
+bool kvm_sev_allowed;
 
 static const KVMCapabilityInfo kvm_required_capabilites[] = {
     KVM_CAP_INFO(USER_MEMORY),
@@ -1745,6 +1747,10 @@ static int kvm_init(MachineState *ms)
 
     kvm_state = s;
 
+    if (!sev_init(kvm_state)) {
+        kvm_sev_allowed = true;
+    }
+
     if (kvm_eventfds_allowed) {
         s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
         s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
diff --git a/sev.c b/sev.c
new file mode 100644
index 0000000..2d71ca6
--- /dev/null
+++ b/sev.c
@@ -0,0 +1,282 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016
+ *
+ * Author:
+ *      Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu/atomic.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/pci/msi.h"
+#include "hw/s390x/adapter.h"
+#include "exec/gdbstub.h"
+#include "sysemu/kvm_int.h"
+#include "sysemu/sev.h"
+#include "qemu/bswap.h"
+#include "exec/memory.h"
+#include "exec/ram_addr.h"
+#include "exec/address-spaces.h"
+#include "qemu/event_notifier.h"
+#include "trace.h"
+#include "hw/irq.h"
+
+//#define DEBUG_SEV
+
+#ifdef DEBUG_SEV
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+struct SEVInfo {
+    uint8_t state;  /* guest current state */
+    uint8_t type;   /* guest type (encrypted, unencrypted) */
+    struct kvm_sev_launch_start *launch_start;
+    struct kvm_sev_launch_update *launch_update;
+    struct kvm_sev_launch_finish *launch_finish;
+};
+
+typedef struct SEVInfo SEVInfo;
+static SEVInfo *sev_info;
+static const char *cfg_file;
+
+enum {
+    LAUNCH_OPTS = 0,
+};
+
+enum {
+    PRE_ENCRYPTED_GUEST = 0,
+    UNENCRYPTED_GUEST,
+};
+
+static QemuOptsList launch_opts = {
+    .name = "sev-launch",
+    .head = QTAILQ_HEAD_INITIALIZER(launch_opts.head),
+    .desc = {
+        {
+            .name = "flags",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "policy",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "dh_pub_qx",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "dh_pub_qy",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "nonce",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "vcpu_length",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "vcpu_count",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "vcpu_mask",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
+static QemuOptsList *config_groups[] = {
+    &launch_opts,
+    NULL
+};
+
+struct add_rule_data {
+    SEVInfo *s;
+    int action;
+};
+
+static unsigned int read_config_u32(QemuOpts *opts, const char *key)
+{
+    unsigned int val;
+
+    val = qemu_opt_get_number_del(opts, key, -1);
+    DPRINTF(" %s = %08x\n", key, val);
+
+    return val;
+}
+
+static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
+{
+    int i;
+    const char *v;
+
+    v = qemu_opt_get(opts, key);
+    if (!v) {
+        return 0;
+    }
+
+    DPRINTF(" %s = ", key);
+    i = 0;
+    while (*v) {
+        sscanf(v, "%2hhx", &val[i]);
+        DPRINTF("%02hhx", val[i]);
+        v += 2;
+        i++;
+    }
+    DPRINTF("\n");
+
+    return i;
+}
+
+static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
+{
+    struct add_rule_data *d = opaque;
+
+    switch (d->action) {
+        case LAUNCH_OPTS: {
+            struct kvm_sev_launch_start *start;
+            struct kvm_sev_launch_update *update;
+            struct kvm_sev_launch_finish *finish;
+
+            /* LAUNCH_START parameters */
+            start = g_malloc0(sizeof(*start));
+
+            DPRINTF("Parsing 'sev-launch' parameters\n");
+            start->flags = read_config_u32(opts, "flags");
+            start->policy = read_config_u32(opts, "policy");
+            read_config_u8(opts, "nonce", start->nonce);
+            read_config_u8(opts, "dh_pub_qx", start->dh_pub_qx);
+            read_config_u8(opts, "dh_pub_qy", start->dh_pub_qy);
+            sev_info->launch_start = start;
+
+            /* LAUNCH_UPDATE */
+            update = g_malloc0(sizeof(*update));
+            sev_info->launch_update = update;
+
+            /* LAUNCH_FINISH parameters */
+            finish = g_malloc0(sizeof(*finish));
+
+            finish->vcpu_count = read_config_u32(opts, "vcpu_count");
+            finish->vcpu_length = read_config_u32(opts, "vcpu_length");
+            if (qemu_opt_get(opts, "vcpu_mask")) {
+                finish->vcpu_mask_length =
+                                    strlen(qemu_opt_get(opts, "vcpu_mask")) / 2;
+                finish->vcpu_mask_addr = (unsigned long)
+                                        g_malloc0(finish->vcpu_length);
+                read_config_u8(opts, "vcpu_mask",
+                        (uint8_t *)finish->vcpu_mask_addr);
+            }
+
+            sev_info->launch_finish = finish;
+
+            break;
+        }
+    }
+
+    return 0;
+}
+
+static int parse_add_rules(QemuOptsList *list, struct add_rule_data *d)
+{
+    Error *local_err = NULL;
+
+    qemu_opts_foreach(list, add_rule, d, &local_err);
+    if (local_err) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static int parse_sev_cfg(SEVInfo *s, int type, const char *filename)
+{
+    FILE *f;
+    int ret = 0;
+    struct add_rule_data d;
+
+    if (filename) {
+        f = fopen(filename, "r");
+        if (f == NULL) {
+            return 1;
+        }
+
+        ret = qemu_config_parse(f, config_groups, filename);
+        if (ret < 0) {
+            fprintf(stderr, "SEV: could not parse config file\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    switch (type) {
+    case LAUNCH_OPTS:
+        d.s = s;
+        d.action = type;
+        ret = parse_add_rules(&launch_opts, &d);
+        break;
+    }
+
+    return ret;
+
+}
+
+int sev_init(KVMState *kvm_state)
+{
+    QemuOpts *opts;
+    const char *type;
+
+    opts = qemu_find_opts_singleton("sev");
+    cfg_file = qemu_opt_get(opts, "config");
+    if (!cfg_file) {
+        return 1;
+    }
+
+    type = qemu_opt_get(opts, "type");
+    if (!type) {
+        return 1;
+    }
+
+    sev_info = calloc(1, sizeof(*sev_info));
+    if (!sev_info) {
+        return 1;
+    }
+
+    if (!strcmp(type, "unencrypted")) {
+        sev_info->type = UNENCRYPTED_GUEST;
+    } else if (!strcmp(type, "encrypted")) {
+        sev_info->type = PRE_ENCRYPTED_GUEST;
+    } else {
+        fprintf(stderr, "SEV: unsupported type '%s'\n", type);
+        goto err;
+    }
+
+    /* call SEV launch start APIs based on guest type */
+
+    return 0;
+err:
+    free(sev_info);
+    sev_info = NULL;
+    return 1;
+}
+

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 07/22] sev: add SEV launch start command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (5 preceding siblings ...)
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support Brijesh Singh
@ 2016-09-13 14:47 ` Brijesh Singh
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 08/22] sev: add SEV launch update command Brijesh Singh
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:47 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The SEV LAUNCH_START commands is used to initiated the process to launch
a guest into SEV-enabled mode. The various parameters needed during this
command should be provided through the SEV configuration file.

For more information on command structure see [1]

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following kvm RFC patches defines and implements this command
http://marc.info/?l=kvm&m=147190852423972&w=2
http://marc.info/?l=kvm&m=147190946024236&w=2


Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |    7 ++++++
 sev.c                |   61 ++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 0ee8aff..b8a7afa 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -23,5 +23,12 @@
  */
 int sev_init(KVMState *kvm_state);
 
+/**
+ * kvm_sev_guest_start - initiate the process to launch a guest into SEV mode.
+ *
+ * Returns: 0 on success, or 1 on failure.
+ */
+int kvm_sev_guest_start(void);
+
 #endif
 
diff --git a/sev.c b/sev.c
index 2d71ca6..40a126a 100644
--- a/sev.c
+++ b/sev.c
@@ -46,6 +46,10 @@
     do { } while (0)
 #endif
 
+enum {
+    SEV_LAUNCH_START = 0x1,
+};
+
 struct SEVInfo {
     uint8_t state;  /* guest current state */
     uint8_t type;   /* guest type (encrypted, unencrypted) */
@@ -271,12 +275,63 @@ int sev_init(KVMState *kvm_state)
         goto err;
     }
 
-    /* call SEV launch start APIs based on guest type */
-
-    return 0;
+    return kvm_sev_guest_start();
 err:
     free(sev_info);
     sev_info = NULL;
     return 1;
 }
 
+static int sev_launch_start(void)
+{
+    int ret;
+    SEVInfo *s = sev_info;
+    struct kvm_sev_issue_cmd input;
+    struct kvm_sev_launch_start *start = s->launch_start;
+
+    input.cmd = KVM_SEV_LAUNCH_START;
+    input.opaque = (__u64)start;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: launch start failed ret=%d(%#010x)\n",
+                ret, input.ret_code);
+        exit(EXIT_FAILURE);
+    }
+
+    s->state = SEV_LAUNCH_START;
+
+    DPRINTF("SEV: Launch Started\n");
+    return 0;
+}
+
+int kvm_sev_guest_start(void)
+{
+    SEVInfo *s = sev_info;
+
+    if (!s) {
+        return 1;
+    }
+
+    /* Guest launch is in progress */
+    if (s->state == SEV_LAUNCH_START) {
+        return 1;
+    }
+
+    if (s->type == UNENCRYPTED_GUEST) {
+        /* If we are requested to launch the guest which need to accepts the
+         * unencrypted images then use the LAUNCH_* command.
+         */
+
+        /* parse the config file to get the parameters */
+        if (!s->launch_start &&
+                (parse_sev_cfg(s, LAUNCH_OPTS, cfg_file) || !s->launch_start)) {
+            fprintf(stderr, "SEV: failed to get SEV LAUNCH parameters\n");
+            exit(EXIT_FAILURE);
+        }
+
+        return sev_launch_start();
+    }
+
+    return 1;
+}
+

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 08/22] sev: add SEV launch update command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (6 preceding siblings ...)
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 07/22] sev: add SEV launch start command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command Brijesh Singh
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The SEV LAUNCH_UPDATE command is used to encrypt the guest memory region.

For more information see [1], section 6.2

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following KVM RFC patches defines and implements this command

http://marc.info/?l=kvm&m=147190852423972&w=2
http://marc.info/?l=kvm&m=147190859023996&w=2

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |    9 +++++++++
 sev.c                |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index b8a7afa..b58a9d7 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -30,5 +30,14 @@ int sev_init(KVMState *kvm_state);
  */
 int kvm_sev_guest_start(void);
 
+/**
+ * kvm_sev_guest_update - encrypt the memory region.
+ * @address: host virtual address of memory region (must be 16-byte aligned)
+ * @len: length of memory region (must be 16-byte aligned).
+ *
+ * Returns: 0 on success, or 1 on failure.
+ */
+int kvm_sev_guest_update(uint8_t *address, uint32_t len);
+
 #endif
 
diff --git a/sev.c b/sev.c
index 40a126a..a451dc0 100644
--- a/sev.c
+++ b/sev.c
@@ -304,6 +304,28 @@ static int sev_launch_start(void)
     return 0;
 }
 
+static int sev_launch_update(uint8_t *addr, uint32_t len)
+{
+    int ret;
+    SEVInfo *s = sev_info;
+    struct kvm_sev_issue_cmd input;
+    struct kvm_sev_launch_update *update = s->launch_update;
+
+    update->address = (uint64_t) addr;
+    update->length = len;
+    input.cmd = KVM_SEV_LAUNCH_UPDATE;
+    input.opaque = (unsigned long)update;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: launch_update failed ret=%d (%#010x)\n",
+                ret, input.ret_code);
+        exit(EXIT_FAILURE);
+    }
+
+    DPRINTF("SEV: LAUNCH update [%#lx+0x%x]\n", (uint64_t)addr, len);
+    return 0;
+}
+
 int kvm_sev_guest_start(void)
 {
     SEVInfo *s = sev_info;
@@ -335,3 +357,17 @@ int kvm_sev_guest_start(void)
     return 1;
 }
 
+int kvm_sev_guest_update(uint8_t *addr, uint32_t len)
+{
+    SEVInfo *s = sev_info;
+
+    if (!s) {
+        return 1;
+    }
+
+    if (s->state == SEV_LAUNCH_START) {
+        return sev_launch_update(addr, len);
+    }
+
+    return 1;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (7 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 08/22] sev: add SEV launch update command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-13 22:15   ` Eduardo Habkost
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
                   ` (14 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The SEV LAUNCH_FINISH command is used for finalizing the guest launch
process. The commad returned a measurement value that can be handed to
the guest owner to validate the guest before vmrun.

For more information see [1], section 6.3

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following KVM RFC patches defines and implements this command
http://marc.info/?l=kvm&m=147190852423972&w=2
http://marc.info/?l=kvm&m=147190856623987&w=2

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |   17 +++++++++++++-
 sev.c                |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index b58a9d7..ab03c5d 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -39,5 +39,20 @@ int kvm_sev_guest_start(void);
  */
 int kvm_sev_guest_update(uint8_t *address, uint32_t len);
 
-#endif
+/**
+ * kvm_sev_guest_finish - finialize launching guest into SEV mode.
+ */
+int kvm_sev_guest_finish(void);
 
+/**
+ * kvm_sev_guest_get_measurement - get measurement from launch finish command.
+ *
+ * @measurement: measurement values returned from the SEV. Its 32-byte value
+ * and buffer must be allocated by caller.
+ *
+ * Returns: 0 on success and @measurement will contain the value, or
+ *          1 on failure.
+ */
+int kvm_sev_guest_measurement(uint8_t *measurement);
+
+#endif
diff --git a/sev.c b/sev.c
index a451dc0..055ed83 100644
--- a/sev.c
+++ b/sev.c
@@ -48,6 +48,7 @@
 
 enum {
     SEV_LAUNCH_START = 0x1,
+    SEV_LAUNCH_FINISH,
 };
 
 struct SEVInfo {
@@ -326,6 +327,32 @@ static int sev_launch_update(uint8_t *addr, uint32_t len)
     return 0;
 }
 
+static int sev_launch_finish(void)
+{
+    int i, ret;
+    SEVInfo *s = sev_info;
+    struct kvm_sev_issue_cmd input;
+    struct kvm_sev_launch_finish *finish = s->launch_finish;
+
+    input.cmd = KVM_SEV_LAUNCH_FINISH;
+    input.opaque = (__u64)finish;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: launch_finish failed ret=%d(%#010x)\n",
+                ret, input.ret_code);
+        exit(EXIT_FAILURE);
+    }
+
+    DPRINTF("SEV: LAUNCH finish measurement=0x");
+    for (i = 0; i < 32; i++) {
+        DPRINTF("%02x", finish->measurement[i]);
+    }
+    DPRINTF("\n");
+
+    s->state = SEV_LAUNCH_FINISH;
+    return 0;
+}
+
 int kvm_sev_guest_start(void)
 {
     SEVInfo *s = sev_info;
@@ -371,3 +398,37 @@ int kvm_sev_guest_update(uint8_t *addr, uint32_t len)
 
     return 1;
 }
+
+int kvm_sev_guest_finish(void)
+{
+    SEVInfo *s = sev_info;
+
+    if (!s) {
+        return 1;
+    }
+
+    if (s->state == SEV_LAUNCH_START) {
+        return sev_launch_finish();
+    }
+
+    return 1;
+}
+
+int kvm_sev_guest_measurement(uint8_t *out)
+{
+    SEVInfo *s = sev_info;
+    struct kvm_sev_launch_finish *finish = s->launch_finish;
+
+    if (!s) {
+        return 1;
+    }
+
+    if (s->type == UNENCRYPTED_GUEST &&
+            s->state == SEV_LAUNCH_FINISH) {
+        memcpy(out, finish->measurement, 32);
+    } else {
+        return 1;
+    }
+
+    return 0;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (8 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-14  2:28   ` Michael S. Tsirkin
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 11/22] sev: add SEV debug encrypt command Brijesh Singh
                   ` (13 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
for the debugging purposes. Note that debugging is permitting only
when guest policy allows it.

For more information see [1], section 7.1

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following KVM RFC patches defines and implements this command

http://marc.info/?l=kvm&m=147190852423972&w=2
http://marc.info/?l=kvm&m=147191068524579&w=2

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |   10 ++++++++++
 sev.c                |   23 +++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index ab03c5d..5872c3e 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
  */
 int kvm_sev_guest_measurement(uint8_t *measurement);
 
+/**
+ * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
+ * @src - guest memory address
+ * @dest - host memory address where the decrypted data should be copied
+ * @length - length of memory region
+ *
+ * Returns: 0 on success and dest will contains the decrypted data
+ */
+int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
+
 #endif
diff --git a/sev.c b/sev.c
index 055ed83..c7031d3 100644
--- a/sev.c
+++ b/sev.c
@@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
 
     return 0;
 }
+
+int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+    int ret;
+    struct kvm_sev_dbg_decrypt decrypt;
+    struct kvm_sev_issue_cmd input;
+
+    decrypt.src_addr = (unsigned long)src;
+    decrypt.dst_addr = (unsigned long)dst;
+    decrypt.length = len;
+
+    input.cmd = KVM_SEV_DBG_DECRYPT;
+    input.opaque = (unsigned long)&decrypt;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
+                ret, input.ret_code);
+        return 1;
+    }
+
+    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
+    return 0;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 11/22] sev: add SEV debug encrypt command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (9 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 12/22] sev: add SEV guest status command Brijesh Singh
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The SEV DEBUG_ENCRYPT command is used for injecting a code into
SEV-enabled guest memory

For more information see [1], section 7.2

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following KVM RFC patches defines and implements this command

http://marc.info/?l=kvm&m=147190861124032&w=2
http://marc.info/?l=kvm&m=147190861124032&w=2

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |   10 ++++++++++
 sev.c                |   23 +++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 5872c3e..a505d75 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -65,4 +65,14 @@ int kvm_sev_guest_measurement(uint8_t *measurement);
  */
 int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
 
+/**
+ * kvm_sev_dbg_encrypt -  encrypt the guest memory in SEV mode.
+ * @src - guest memory address
+ * @dest - host memory address where the encrypted data should be copied
+ * @length - length of memory region
+ *
+ * Returns: 0 on success and dest will contains the encrypted data
+ */
+int kvm_sev_dbg_encrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
+
 #endif
diff --git a/sev.c b/sev.c
index c7031d3..4e5da84 100644
--- a/sev.c
+++ b/sev.c
@@ -455,3 +455,26 @@ int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
     DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
     return 0;
 }
+
+int kvm_sev_dbg_encrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+    int ret;
+    struct kvm_sev_dbg_encrypt encrypt;
+    struct kvm_sev_issue_cmd input;
+
+    encrypt.src_addr = (unsigned long)src;
+    encrypt.dst_addr = (unsigned long)dst;
+    encrypt.length = len;
+
+    input.cmd = KVM_SEV_DBG_ENCRYPT;
+    input.opaque = (unsigned long)&encrypt;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: dbg_encrypt failed ret=%d(%#010x)\n",
+                ret, input.ret_code);
+        return 1;
+    }
+
+    DPRINTF("SEV: DBG_ENCRYPT dst %p src %p sz %d\n", dst, src, len);
+    return 0;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 12/22] sev: add SEV guest status command
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (10 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 11/22] sev: add SEV debug encrypt command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status Brijesh Singh
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The command is used for querying SEV status for this guest.

For more information see [1], section 6.10

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

The following KVM RFC patches defines and implements this command

http://marc.info/?l=kvm&m=147190852423972&w=2
http://marc.info/?l=kvm&m=147190852423972&w=2

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |   18 ++++++++++++++++++
 sev.c                |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index a505d75..e8fa62f 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -16,6 +16,15 @@
 
 #include "sysemu/kvm.h"
 
+typedef enum SevState {
+    SEV_STATE_INVALID = 0x0,
+    SEV_STATE_LAUNCHING,
+    SEV_STATE_RECEIVING,
+    SEV_STATE_SENDING,
+    SEV_STATE_RUNNING,
+    SEV_STATE_MAX,
+} SevState;
+
 /**
  * sev_init - initialize Secure Encrypted Virtualization on this guest
  * @kvm_state - KVM handle
@@ -75,4 +84,13 @@ int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
  */
 int kvm_sev_dbg_encrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
 
+/**
+ * kvm_sev_get_status - get the guest status in SEV mode.
+ * @state - guest SEV state
+ * @str - verbatim string literal (buffer must be allocated by caller)
+ *
+ * Returns: 0 on success and @state will be contain current guest state.
+ */
+int kvm_sev_get_status(SevState *state, char *str);
+
 #endif
diff --git a/sev.c b/sev.c
index 4e5da84..508eff2 100644
--- a/sev.c
+++ b/sev.c
@@ -59,6 +59,15 @@ struct SEVInfo {
     struct kvm_sev_launch_finish *launch_finish;
 };
 
+const char *sev_state_msg[] = {
+    "error",
+    "launching",
+    "receiving",
+    "sending",
+    "running",
+    "unknown",
+};
+
 typedef struct SEVInfo SEVInfo;
 static SEVInfo *sev_info;
 static const char *cfg_file;
@@ -478,3 +487,28 @@ int kvm_sev_dbg_encrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
     DPRINTF("SEV: DBG_ENCRYPT dst %p src %p sz %d\n", dst, src, len);
     return 0;
 }
+
+int kvm_sev_get_status(SevState *state, char *msg)
+{
+    int ret;
+    struct kvm_sev_guest_status status;
+    struct kvm_sev_issue_cmd input;
+
+    input.cmd = KVM_SEV_GUEST_STATUS;
+    input.opaque = (unsigned long)&status;
+    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+    if (ret) {
+        fprintf(stderr, "SEV: guest_status failed ret=%d(%#010x)\n",
+                ret, input.ret_code);
+        return 1;
+    }
+
+    *state = status.state;
+    if (msg) {
+        strcpy(msg, sev_state_msg[*state]);
+    }
+
+    DPRINTF("SEV: GUEST_STATUS state %#x (%s)\n", *state,
+            sev_state_msg[*state]);
+    return 0;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (11 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 12/22] sev: add SEV guest status command Brijesh Singh
@ 2016-09-13 14:48 ` Brijesh Singh
  2016-09-13 16:09   ` Eric Blake
  2016-09-13 23:01   ` Paolo Bonzini
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 14/22] sev: provide SEV-enabled guest RAM read/write ops Brijesh Singh
                   ` (10 subsequent siblings)
  23 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:48 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

Update the 'info kvm' monitor command to display the SEV status.

(qemu) info kvm
kvm support: enabled
sev support: enabled (running)

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hmp.c            |   14 ++++++++++++++
 qapi-schema.json |    4 +++-
 qmp.c            |    1 +
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/hmp.c b/hmp.c
index cc2056e..068b77d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -18,6 +18,7 @@
 #include "net/net.h"
 #include "net/eth.h"
 #include "sysemu/char.h"
+#include "sysemu/sev.h"
 #include "sysemu/block-backend.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
@@ -76,11 +77,24 @@ void hmp_info_version(Monitor *mon, const QDict *qdict)
 void hmp_info_kvm(Monitor *mon, const QDict *qdict)
 {
     KvmInfo *info;
+    SevState state;
+    char msg[80] = {0};
 
     info = qmp_query_kvm(NULL);
     monitor_printf(mon, "kvm support: ");
     if (info->present) {
         monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
+        monitor_printf(mon, "sev support: %s",
+                        info->sev ? "enabled" : "disabled");
+        if (info->sev) {
+            if (kvm_sev_get_status(&state, msg)) {
+                monitor_printf(mon, " (error)\n");
+            } else {
+                monitor_printf(mon, " (%s)\n", msg);
+            }
+        } else {
+            monitor_printf(mon, "\n");
+        }
     } else {
         monitor_printf(mon, "not compiled\n");
     }
diff --git a/qapi-schema.json b/qapi-schema.json
index 5658723..86b5dc9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -99,9 +99,11 @@
 #
 # @present: true if KVM acceleration is built into this executable
 #
+# @sev: true if SEV is active
+#
 # Since: 0.14.0
 ##
-{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool', 'sev' : 'bool'} }
 
 ##
 # @query-kvm:
diff --git a/qmp.c b/qmp.c
index b6d531e..834edb8 100644
--- a/qmp.c
+++ b/qmp.c
@@ -77,6 +77,7 @@ KvmInfo *qmp_query_kvm(Error **errp)
 
     info->enabled = kvm_enabled();
     info->present = kvm_available();
+    info->sev = kvm_sev_enabled();
 
     return info;
 }

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 14/22] sev: provide SEV-enabled guest RAM read/write ops
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (12 preceding siblings ...)
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status Brijesh Singh
@ 2016-09-13 14:49 ` Brijesh Singh
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region Brijesh Singh
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:49 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

The patch implements kvm_sev_get_ram_ops() which provides guest RAM
read/write callback. Depending on the memory attributes and guest launch
state, the callback will use SEV launch update or SEV debug commands
to read/write into guest memory.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/sysemu/sev.h |    8 ++++++++
 sev.c                |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index e8fa62f..ec2dfde 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -15,6 +15,7 @@
 #define QEMU_SEV_H
 
 #include "sysemu/kvm.h"
+#include "exec/memory.h"
 
 typedef enum SevState {
     SEV_STATE_INVALID = 0x0,
@@ -93,4 +94,11 @@ int kvm_sev_dbg_encrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
  */
 int kvm_sev_get_status(SevState *state, char *str);
 
+/*
+ * kvm_sev_get_ram_ops - get MemoryRegionRW ops.
+ *
+ * Return NULL on failure.
+ */
+MemoryRegionRAMReadWriteOps *kvm_sev_get_ram_ops(void);
+
 #endif
diff --git a/sev.c b/sev.c
index 508eff2..c1135c4 100644
--- a/sev.c
+++ b/sev.c
@@ -72,6 +72,8 @@ typedef struct SEVInfo SEVInfo;
 static SEVInfo *sev_info;
 static const char *cfg_file;
 
+static MemoryRegionRAMReadWriteOps sev_ops;
+
 enum {
     LAUNCH_OPTS = 0,
 };
@@ -512,3 +514,47 @@ int kvm_sev_get_status(SevState *state, char *msg)
             sev_state_msg[*state]);
     return 0;
 }
+
+static inline int sev_read(uint8_t *dst, const uint8_t *src,
+                           uint32_t len, MemTxAttrs attrs)
+{
+    if (attrs.sev_debug) {
+        return kvm_sev_dbg_decrypt(dst, src, len);
+    }
+
+    memcpy(dst, src, len);
+    return 0;
+}
+
+static inline int sev_write(uint8_t *dst, const uint8_t *src,
+                            uint32_t len, MemTxAttrs attrs)
+{
+    SEVInfo *s = sev_info;
+
+    /* If we are in SEV launch stage then use launch_update command
+     * to copy and encrypt the data into guest memory.
+     */
+    if (s->state == SEV_LAUNCH_START) {
+        memcpy(dst, src, len);               /* copy data into guest memory */
+        return sev_launch_update(dst, len);  /* encrypt the data in-place */
+    }
+
+    if (attrs.sev_debug) {
+        return kvm_sev_dbg_encrypt(dst, src, len);
+    }
+
+    memcpy(dst, src, len);
+    return 0;
+}
+
+MemoryRegionRAMReadWriteOps *kvm_sev_get_ram_ops(void)
+{
+    if (!sev_info) {
+        return NULL;
+    }
+
+    sev_ops.read = sev_read;
+    sev_ops.write = sev_write;
+
+    return &sev_ops;
+}

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (13 preceding siblings ...)
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 14/22] sev: provide SEV-enabled guest RAM read/write ops Brijesh Singh
@ 2016-09-13 14:49 ` Brijesh Singh
  2016-09-13 23:05   ` Paolo Bonzini
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f Brijesh Singh
                   ` (8 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:49 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

If guest is launched into SEV-enabled mode then read/write to the
BIOS and RAM memory regions should be performed using the SEV commands.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc.c       |    5 +++++
 hw/i386/pc_sysfw.c |    6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 022dd1b..1471df4 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -46,6 +46,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sev.h"
 #include "sysemu/qtest.h"
 #include "kvm_i386.h"
 #include "hw/xen/xen.h"
@@ -1387,6 +1388,10 @@ void pc_memory_init(PCMachineState *pcms,
         e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
     }
 
+    /* Register SEV read/write ops for the guest RAM */
+    if (kvm_sev_enabled())
+        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());
+
     if (!pcmc->has_reserved_memory &&
         (machine->ram_slots ||
          (machine->maxram_size > machine->ram_size))) {
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index f915ad0..95b1006 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -35,6 +35,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sev.h"
 
 #define BIOS_FILENAME "bios.bin"
 
@@ -228,6 +229,11 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
     memory_region_add_subregion(rom_memory,
                                 (uint32_t)(-bios_size),
                                 bios);
+
+    /* Register SEV read/write callback */
+    if (kvm_sev_enabled()) {
+        memory_region_set_ram_ops(bios, kvm_sev_get_ram_ops());
+    }
 }
 
 void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (14 preceding siblings ...)
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region Brijesh Singh
@ 2016-09-13 14:49 ` Brijesh Singh
  2016-09-13 23:07   ` Paolo Bonzini
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 18/22] i386: clear C-bit in SEV guest page table walk Brijesh Singh
                   ` (7 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:49 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

Fn8000_001f cpuid provides the memory encryption (aka C-bit)

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target-i386/cpu.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 6a1afab..e039c08 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2625,6 +2625,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             *edx = 0;
         }
         break;
+    case 0x8000001F:
+        host_cpuid(index, 0, eax, ebx, ecx, edx);
+        break;
     case 0xC0000000:
         *eax = env->cpuid_xlevel2;
         *ebx = 0;

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 18/22] i386: clear C-bit in SEV guest page table walk
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (15 preceding siblings ...)
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f Brijesh Singh
@ 2016-09-13 14:49 ` Brijesh Singh
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest Brijesh Singh
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:49 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

In SEV-enabled guest the physical addresses in page table will
have C-bit set, we need to clear the C-bit when walking the page table.
The C-bit position should be available in cpuid Fn8000_001f[EBX]

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target-i386/helper.c  |   36 +++++++++++++++++++++++++++++-------
 target-i386/monitor.c |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1c250b8..a9d8aef 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1006,6 +1006,22 @@ do_check_protect_pse36:
     return 1;
 }
 
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /* In SEV guest page tables addresses will have memory encryption bit set,
+     * C-bit should be cleared while doing the page table walk.
+     */
+    if (kvm_sev_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << pos);
+    }
+
+    return ~me_mask;
+}
+
 hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -1014,6 +1030,12 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     uint64_t pte;
     uint32_t page_offset;
     int page_size;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
+
+    /* In SEV guest, CR3 will have memory encryption bit set, clear it */
+    env->cr[3] &= me_mask;
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
         pte = addr & env->a20_mask;
@@ -1034,13 +1056,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             }
             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
                 env->a20_mask;
-            pml4e = x86_ldq_phys(cs, pml4e_addr);
+            pml4e = x86_ldq_phys(cs, pml4e_addr) & me_mask;
             if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
             }
             pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
                          (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = x86_ldq_phys(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK)) {
                 return -1;
             }
@@ -1055,14 +1077,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         {
             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
                 env->a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = x86_ldq_phys(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
         }
 
         pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
-        pde = x86_ldq_phys(cs, pde_addr);
+        pde = x86_ldq_phys(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
         }
@@ -1075,7 +1097,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
             page_size = 4096;
-            pte = x86_ldq_phys(cs, pte_addr);
+            pte = x86_ldq_phys(cs, pte_addr) & me_mask;
         }
         if (!(pte & PG_PRESENT_MASK)) {
             return -1;
@@ -1085,7 +1107,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
         /* page directory entry */
         pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
-        pde = x86_ldl_phys(cs, pde_addr);
+        pde = x86_ldl_phys(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -1094,7 +1116,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
-            pte = x86_ldl_phys(cs, pte_addr);
+            pte = x86_ldl_phys(cs, pte_addr) & me_mask;
             if (!(pte & PG_PRESENT_MASK)) {
                 return -1;
             }
diff --git a/target-i386/monitor.c b/target-i386/monitor.c
index 47d3c2d..94e6c70 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -54,6 +54,22 @@ static void print_pte(Monitor *mon, hwaddr addr,
                    pte & PG_RW_MASK ? 'W' : '-');
 }
 
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /* In SEV guest page tables addresses will have memory encryption bit set,
+     * C-bit should be cleared while doing the page table walk.
+     */
+    if (kvm_sev_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << pos);
+    }
+
+    return ~me_mask;
+}
+
 static void tlb_info_32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2;
@@ -127,15 +143,21 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
     uint64_t l1, l2, l3, l4;
     uint64_t pml4e, pdpe, pde, pte;
     uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml4_addr &= me_mask;
     for (l1 = 0; l1 < 512; l1++) {
         cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
+        pml4e &= me_mask;
         pml4e = le64_to_cpu(pml4e);
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
+                pdpe &= me_mask;
                 pdpe = le64_to_cpu(pdpe);
                 if (pdpe & PG_PRESENT_MASK) {
                     if (pdpe & PG_PSE_MASK) {
@@ -147,6 +169,7 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pd_addr + l3 * 8,
                                     &pde, 8);
+                            pde &= me_mask;
                             pde = le64_to_cpu(pde);
                             if (pde & PG_PRESENT_MASK) {
                                 if (pde & PG_PSE_MASK) {
@@ -160,6 +183,7 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
                                         cpu_physical_memory_read_debug(pt_addr
                                                                  + l4 * 8,
                                                                  &pte, 8);
+                                        pte &= me_mask;
                                         pte = le64_to_cpu(pte);
                                         if (pte & PG_PRESENT_MASK) {
                                             print_pte(mon, (l1 << 39) +
@@ -331,18 +355,24 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
     uint64_t l1, l2, l3, l4;
     uint64_t pml4e, pdpe, pde, pte;
     uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml4_addr &= me_mask;
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 512; l1++) {
         cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
+        pml4e &= me_mask;
         pml4e = le64_to_cpu(pml4e);
         end = l1 << 39;
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
+                pdpe &= me_mask;
                 pdpe = le64_to_cpu(pdpe);
                 end = (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
@@ -356,6 +386,7 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pd_addr + l3 * 8,
                                     &pde, 8);
+                            pde &= me_mask;
                             pde = le64_to_cpu(pde);
                             end = (l1 << 39) + (l2 << 30) + (l3 << 21);
                             if (pde & PG_PRESENT_MASK) {
@@ -370,6 +401,7 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
                                         cpu_physical_memory_read_debug(pt_addr
                                                                  + l4 * 8,
                                                                  &pte, 8);
+                                        pte &= me_mask;
                                         pte = le64_to_cpu(pte);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (16 preceding siblings ...)
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 18/22] i386: clear C-bit in SEV guest page table walk Brijesh Singh
@ 2016-09-13 14:49 ` Brijesh Singh
  2016-09-13 23:06   ` Paolo Bonzini
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Brijesh Singh
                   ` (5 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:49 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

When debug version of physical memory read APIs are called on SEV guest
then set the MemTxAttrs.sev_debug attribute to indicate that memory
read/write is requested for debug purposes.

On SEV guest, the memory region read/write callback will check this
attribute and if its set then it will use SEV DEBUG DECRYPT/ENCRYPT commands
to read/write into guest memory.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 exec.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index 604bd05..b1df25d 100644
--- a/exec.c
+++ b/exec.c
@@ -3773,7 +3773,11 @@ void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
 {
     MemTxAttrs attrs;
 
-    attrs = MEMTXATTRS_UNSPECIFIED;
+    if (kvm_sev_enabled()) {
+        attrs = MEMTXATTRS_SEV_DEBUG;
+    } else {
+        attrs = MEMTXATTRS_UNSPECIFIED;
+    }
 
     address_space_rw(&address_space_memory, addr, attrs, buf, len, is_write);
 }
@@ -3793,6 +3797,11 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
         page = addr & TARGET_PAGE_MASK;
         phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, &attrs);
         asidx = cpu_asidx_from_attrs(cpu, attrs);
+
+        if (kvm_sev_enabled()) {
+            attrs = MEMTXATTRS_SEV_DEBUG;
+        }
+
         /* if no physical page mapped, return an error */
         if (phys_addr == -1)
             return -1;

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (17 preceding siblings ...)
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest Brijesh Singh
@ 2016-09-13 14:50 ` Brijesh Singh
  2016-09-13 18:39   ` Michael S. Tsirkin
  2016-09-13 22:53   ` Paolo Bonzini
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback Brijesh Singh
                   ` (4 subsequent siblings)
  23 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:50 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

In SEV-enabled guest dma should be performed on shared pages. Since
the SeaBIOS executes in non PAE mode and does not have access to C-bit
to create a shared page hence disable the dma operation when reading
from fw_cfg interface.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/nvram/fw_cfg.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 6a68e59..aca99e9 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -24,6 +24,7 @@
 #include "qemu/osdep.h"
 #include "hw/hw.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
 #include "sysemu/dma.h"
 #include "hw/boards.h"
 #include "hw/isa/isa.h"
@@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
     FWCfgIoState *s = FW_CFG_IO(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
+    /* disable dma on fw_cfg when SEV is enabled */
+    if (kvm_sev_enabled()) {
+        qdev_prop_set_bit(dev, "dma_enabled", false);
+    }
+
     /* when using port i/o, the 8-bit data register ALWAYS overlaps
      * with half of the 16-bit control register. Hence, the total size
      * of the i/o region used is FW_CFG_CTL_SIZE */

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (18 preceding siblings ...)
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Brijesh Singh
@ 2016-09-13 14:50 ` Brijesh Singh
  2016-09-13 22:47   ` Paolo Bonzini
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest Brijesh Singh
                   ` (3 subsequent siblings)
  23 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:50 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

This patch adds methods to register a callback in qemu_system_reset().

- qemu_register_pre_reset() : function will be called just after
  entering into qemu_system_reset().
- qemu_register_post_reset(): function will be called just before
  exiting from the qemu_system_reset().

A qemu_system_reset() causes loader to reload the OS images into guest
memory. In case of SEV-enabled guest we need to call the SEV launch start
command before loader copies any data into guest RAM and similarly SEV
launch finish command should be executed after we finished copying the
data into guest memory.

These callback will allow us to hook the SEV launch START and FINISH
commands into qemu_system_reset() handlder to start and finalize the SEV
guest launch process.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 include/hw/hw.h |    2 ++
 sev.c           |   14 ++++++++++++++
 vl.c            |   45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/include/hw/hw.h b/include/hw/hw.h
index 3669ebd..31dcf9f 100644
--- a/include/hw/hw.h
+++ b/include/hw/hw.h
@@ -17,6 +17,8 @@ typedef void QEMUResetHandler(void *opaque);
 
 void qemu_register_reset(QEMUResetHandler *func, void *opaque);
 void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
+void qemu_register_pre_reset(QEMUResetHandler *func, void *opaque);
+void qemu_register_post_reset(QEMUResetHandler *func, void *opaque);
 
 void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 
diff --git a/sev.c b/sev.c
index c1135c4..141f9d6 100644
--- a/sev.c
+++ b/sev.c
@@ -35,6 +35,7 @@
 #include "qemu/event_notifier.h"
 #include "trace.h"
 #include "hw/irq.h"
+#include "hw/hw.h"
 
 //#define DEBUG_SEV
 
@@ -257,6 +258,16 @@ static int parse_sev_cfg(SEVInfo *s, int type, const char *filename)
 
 }
 
+static void sev_pre_reset_handler(void *data)
+{
+    kvm_sev_guest_start();
+}
+
+static void sev_post_reset_handler(void *data)
+{
+    kvm_sev_guest_finish();
+}
+
 int sev_init(KVMState *kvm_state)
 {
     QemuOpts *opts;
@@ -287,6 +298,9 @@ int sev_init(KVMState *kvm_state)
         goto err;
     }
 
+    qemu_register_pre_reset(sev_pre_reset_handler, sev_info);
+    qemu_register_post_reset(sev_post_reset_handler, sev_info);
+
     return kvm_sev_guest_start();
 err:
     free(sev_info);
diff --git a/vl.c b/vl.c
index 22b8eba..5923c73 100644
--- a/vl.c
+++ b/vl.c
@@ -25,6 +25,7 @@
 #include "qemu-version.h"
 #include "qemu/cutils.h"
 #include "qemu/help_option.h"
+#include "sysemu/sev.h"
 
 #ifdef CONFIG_SECCOMP
 #include "sysemu/seccomp.h"
@@ -1630,6 +1631,10 @@ static NotifierList suspend_notifiers =
 static NotifierList wakeup_notifiers =
     NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
 static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
+static QTAILQ_HEAD(pre_reset_handlers, QEMUResetEntry) pre_reset_handlers =
+    QTAILQ_HEAD_INITIALIZER(pre_reset_handlers);
+static QTAILQ_HEAD(post_reset_handlers, QEMUResetEntry)
+    post_reset_handlers = QTAILQ_HEAD_INITIALIZER(post_reset_handlers);
 
 int qemu_shutdown_requested_get(void)
 {
@@ -1733,12 +1738,51 @@ void qemu_devices_reset(void)
     }
 }
 
+void qemu_register_pre_reset(QEMUResetHandler *func, void *opaque)
+{
+    QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
+
+    re->func = func;
+    re->opaque = opaque;
+    QTAILQ_INSERT_TAIL(&pre_reset_handlers, re, entry);
+}
+
+static void qemu_system_pre_reset(void)
+{
+    QEMUResetEntry *re, *nre;
+
+    /* call pre_reset handler */
+    QTAILQ_FOREACH_SAFE(re, &pre_reset_handlers, entry, nre) {
+        re->func(re->opaque);
+    }
+}
+
+void qemu_register_post_reset(QEMUResetHandler *func, void *opaque)
+{
+    QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
+
+    re->func = func;
+    re->opaque = opaque;
+    QTAILQ_INSERT_TAIL(&post_reset_handlers, re, entry);
+}
+
+static void qemu_system_post_reset(void)
+{
+    QEMUResetEntry *re, *nre;
+
+    /* call post reset handler */
+    QTAILQ_FOREACH_SAFE(re, &post_reset_handlers, entry, nre) {
+        re->func(re->opaque);
+    }
+}
+
 void qemu_system_reset(bool report)
 {
     MachineClass *mc;
 
     mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
 
+    qemu_system_pre_reset();
     cpu_synchronize_all_states();
 
     if (mc && mc->reset) {
@@ -1750,6 +1794,7 @@ void qemu_system_reset(bool report)
         qapi_event_send_reset(&error_abort);
     }
     cpu_synchronize_all_post_reset();
+    qemu_system_post_reset();
 }
 
 void qemu_system_guest_panicked(void)

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (19 preceding siblings ...)
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback Brijesh Singh
@ 2016-09-13 14:50 ` Brijesh Singh
  2016-09-13 18:47   ` Michael S. Tsirkin
  2016-09-13 22:59   ` Paolo Bonzini
  2016-09-13 15:20 ` [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Eduardo Habkost
                   ` (2 subsequent siblings)
  23 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 14:50 UTC (permalink / raw)
  To: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

In SEV-enabled mode we need to reload the BIOS image on loader reset, this
will ensure that BIOS image gets encrypted and included as part of launch
meausrement on guest reset.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/core/loader.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 53e0e41..9b03bfe 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -55,6 +55,7 @@
 #include "exec/address-spaces.h"
 #include "hw/boards.h"
 #include "qemu/cutils.h"
+#include "sysemu/kvm.h"
 
 #include <zlib.h>
 
@@ -1011,7 +1012,11 @@ static void rom_reset(void *unused)
             cpu_physical_memory_write_rom(&address_space_memory,
                                           rom->addr, rom->data, rom->datasize);
         }
-        if (rom->isrom) {
+
+        /* reload the rom on SEV-enabled guest so that it gets included into
+         * guest memory measurement on system reset.
+         */
+        if (!kvm_sev_enabled() && rom->isrom) {
             /* rom needs to be written only once */
             g_free(rom->data);
             rom->data = NULL;

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD)
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (20 preceding siblings ...)
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest Brijesh Singh
@ 2016-09-13 15:20 ` Eduardo Habkost
       [not found] ` <147377816978.11859.942423377333907417.stgit@brijesh-build-machine>
  2016-09-14  2:55 ` [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Michael S. Tsirkin
  23 siblings, 0 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-13 15:20 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: crosthwaite.peter, armbru, mst, p.fedin, qemu-devel, lcapitulino,
	pbonzini, rth

On Tue, Sep 13, 2016 at 10:46:46AM -0400, Brijesh Singh wrote:
> This RFC series provides support for AMD's new Secure Encrypted 
> Virtualization (SEV) feature. This RFC is based KVM RFC [1].
> 
> SEV is an extension to the AMD-V architecture which supports running
> multiple VMs under the control of a hypervisor. The SEV feature allows
> the memory contents of a virtual machine (VM) to be transparently encrypted
> with a key unique to the guest VM. The memory controller contains a
> high performance encryption engine which can be programmed with multiple
> keys for use by a different VMs in the system. The programming and
> management of these keys is handled by the AMD Secure Processor firmware
> which exposes a commands for these tasks.
> 
> SEV is designed to protect guest VMs from a benign but vulnerable
> (i.e. not fully malicious) hypervisor. In particular, it reduces the attack
> surface of guest VMs and can prevent certain types of VM-escape bugs
> (e.g. hypervisor read-anywhere) from being used to steal guest data.
> 
> The KVM RFC introduced a new ioctl (KVM_SEV_ISSUE_CMD) which can be
> used by qemu to enable SEV for secure guest and assist performing common
> hypervisor activities such as a launching, running, snapshooting, migration
> and debugging a guests data.
> 
> 
> The following links provide additional details:
> 
> AMD Memory Encryption whitepaper:
>  
> http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
> 
> AMD64 Architecture Programmer's Manual:
>     http://support.amd.com/TechDocs/24593.pdf
>     SME is section 7.10
>     SEV is section 15.34
> 
> Secure Encrypted Virutualization Key Management:
> http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf
> 
> KVM Forum slides:
> http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf

For reference, video of the KVM Forum Talk:
https://www.youtube.com/watch?v=RcvQ1xN55Ew

I was not present at the session and I plan to watch it to be
able to give better feedback.

> 
> KVM RFC link:
> 
> [1] http://marc.info/?l=kvm&m=147191038624432&w=2
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support Brijesh Singh
@ 2016-09-13 15:58   ` Eduardo Habkost
  2016-09-13 19:54     ` Brijesh Singh
  2016-09-14  8:37   ` Daniel P. Berrange
  1 sibling, 1 reply; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-13 15:58 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: crosthwaite.peter, armbru, mst, p.fedin, qemu-devel, lcapitulino,
	pbonzini, rth

On Tue, Sep 13, 2016 at 10:47:47AM -0400, Brijesh Singh wrote:
> This patch adds the initial support required to integrate Secure
> Encrypted Virtualization feature, the patch include the following
> changes:
> 
> - adds sev.c and sev.h files: the file will contain SEV APIs implemention.
> - add kvm_sev_enabled(): similar to kvm_enabled() this function can be
>   used to check if sev is enabled on this guest.
> - implement functions to parse SEV specific configuration file.
> 
> A typical SEV config file looks like this:
> 

Are those config options documented somewhere?

> [sev-launch]
> 	flags = "00000000"
> 	policy	= "000000"
> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> 	nonce = "0123456789abcdef"
> 	vcpu_count = "1"
> 	vcpu_length = "30"
> 	vcpu_mask = "00ab"

Why a separate config file loading mechanism? If the user really
needs to load the SEV configuration data from a separate file,
you can just use regular config sections and use -readconfig.

Now, about the format of the new config sections ("sev" and
"sev-launch"): I am not sure adding new command-line options and
config sections is necessary. Is it possible to implement it as a
combination of:
* new options to existing command-line options and/or
* new options to existing objects and/or
* new options to existing devices and/or
* new types for -object? (see how crypto secrets and net filters
  are configured, for an example)


[...]
>  extern bool kvm_allowed;
> +extern bool kvm_sev_allowed;

Can we place this inside struct KVMState?

>  extern bool kvm_kernel_irqchip;
>  extern bool kvm_split_irqchip;
>  extern bool kvm_async_interrupts_allowed;
[...]
> @@ -1745,6 +1747,10 @@ static int kvm_init(MachineState *ms)
>  
>      kvm_state = s;
>  
> +    if (!sev_init(kvm_state)) {
> +        kvm_sev_allowed = true;
> +    }

sev_init() errors are being ignored here. sev_init() could report
errors properly using Error** (and kvm_init() should not ignore
them).

> +
>      if (kvm_eventfds_allowed) {
>          s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
>          s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
[...]
> +
> +struct SEVInfo {
> +    uint8_t state;  /* guest current state */
> +    uint8_t type;   /* guest type (encrypted, unencrypted) */
> +    struct kvm_sev_launch_start *launch_start;
> +    struct kvm_sev_launch_update *launch_update;
> +    struct kvm_sev_launch_finish *launch_finish;
> +};
> +
> +typedef struct SEVInfo SEVInfo;
> +static SEVInfo *sev_info;

Can we place this pointer inside struct KVMState?

[...]
> +static unsigned int read_config_u32(QemuOpts *opts, const char *key)
> +{
> +    unsigned int val;
> +
> +    val = qemu_opt_get_number_del(opts, key, -1);
> +    DPRINTF(" %s = %08x\n", key, val);
> +
> +    return val;
> +}
> +
> +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)

Function name confused me (it seemed to read only one u8 value).

> +{
> +    int i;
> +    const char *v;
> +
> +    v = qemu_opt_get(opts, key);
> +    if (!v) {
> +        return 0;
> +    }
> +
> +    DPRINTF(" %s = ", key);
> +    i = 0;
> +    while (*v) {
> +        sscanf(v, "%2hhx", &val[i]);

Function doesn't check for array length.

> +        DPRINTF("%02hhx", val[i]);
> +        v += 2;
> +        i++;
> +    }
> +    DPRINTF("\n");
> +
> +    return i;

Do we really need to write our own parser? I wonder if we can
reuse crypto/secret.c for loading the keys.

> +}
> +
[...]

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status Brijesh Singh
@ 2016-09-13 16:09   ` Eric Blake
  2016-09-14 16:16     ` Brijesh Singh
  2016-09-13 23:01   ` Paolo Bonzini
  1 sibling, 1 reply; 125+ messages in thread
From: Eric Blake @ 2016-09-13 16:09 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

[-- Attachment #1: Type: text/plain, Size: 887 bytes --]

On 09/13/2016 09:48 AM, Brijesh Singh wrote:
> Update the 'info kvm' monitor command to display the SEV status.
> 
> (qemu) info kvm
> kvm support: enabled
> sev support: enabled (running)
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---

> +++ b/qapi-schema.json
> @@ -99,9 +99,11 @@
>  #
>  # @present: true if KVM acceleration is built into this executable
>  #
> +# @sev: true if SEV is active

Worth expanding what the acronym stands for.  Also needs a '(since 2.8)'
designator.

> +#
>  # Since: 0.14.0
>  ##
> -{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
> +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool', 'sev' : 'bool'} }

Long line; please wrap to keep it under 80 columns.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest
       [not found] ` <147377816978.11859.942423377333907417.stgit@brijesh-build-machine>
@ 2016-09-13 18:37   ` Michael S. Tsirkin
  2016-09-21 15:55     ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-13 18:37 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:49:29AM -0400, Brijesh Singh wrote:
> Typically linux kernel, initrd and cmdline are build and loaded
> into guest memory through linux optionrom. The linux optionrom is
> probed and executed by SeaBIOS. This method will not work for
> SEV-enabled guest.
> 
> In SEV-enabled guest all the code and data must be copied using SEV
> launch command prior to starting the guest (i.e before first vmrun).
> The data copied using SEV launch command will be encrypted using guest
> owner's key. This patch loads kernel, initrd and cmdline blobs at fixed
> location into guest memory and builds etc/sev_cfg config file. The cfg
> file provide the below structure
> 
> struct sev_cfg {
> 	u32 kernel_addr, initrd_addr, cmdline_addr;
> 	u32 kernel_size, initrd_size, cmdline_size;
> }
> 
> The config file can be used by SeaBIOS to locate OS images into guest
> RAM and build linux boot entry code.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

I don't think we want to give users this kind of
control over how we manage memory internally
for what is essentially a debugging feature at this point.

Isn't there a way to first launch guest, and then have it
encrypt itself once it's running?

If not, I guess it's not too bad if -kernel does not
work with sev debug feature - just load kernel from disk.


> ---
>  hw/i386/pc.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 93 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 1471df4..f2c7472 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -104,6 +104,15 @@ static struct e820_entry *e820_table;
>  static unsigned e820_entries;
>  struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
>  
> +struct sev_cfg_data {
> +    uint32_t kernel_addr;
> +    uint32_t initrd_addr;
> +    uint32_t cmdline_addr;
> +    uint32_t kernel_size;
> +    uint32_t initrd_size;
> +    uint32_t cmdline_size;
> +} QEMU_PACKED __attribute((__aligned__(4)));
> +
>  void gsi_handler(void *opaque, int n, int level)
>  {
>      GSIState *s = opaque;
> @@ -824,6 +833,86 @@ struct setup_data {
>      uint8_t data[0];
>  } __attribute__((packed));
>  
> +#define round_up(x, align) ((x + align) & ~(align - 1))
> +
> +static void sev_load_file_fixed(const char *filename, int start,
> +                                int *end, int *sz)
> +{
> +    FILE *f;
> +    int sz_aligned, ret;
> +    char *data;
> +
> +    f = fopen(filename, "rb");
> +    if (!f) {
> +        fprintf(stderr, "qemu: could not load '%s': %s\n",
> +                filename, strerror(errno));
> +        exit(1);
> +    }
> +
> +    /* SEV update commands needs 16-byte aligned length */
> +    *sz = get_file_size(f);
> +    sz_aligned = round_up(*sz, 16);
> +    data = g_malloc(sz_aligned);
> +    ret = fread(data, 1, *sz, f);
> +    if (ret != *sz) {
> +        fprintf(stderr, "qemu: failed to read %d bytes from %s\n",
> +                *sz, filename);
> +        exit(1);
> +    }
> +    rom_add_blob_fixed(filename, data, sz_aligned, start);
> +    *end = start + sz_aligned;
> +    fclose(f);
> +    g_free(data);
> +}
> +
> +/* load kernel, initrd and cmdline blobs at fixed location into guest
> + * memory and generate etc/sev config file.
> + */
> +static void sev_load_linux(PCMachineState *pcms,
> +                           FWCfgState *fw_cfg)
> +{
> +    FILE *f;
> +    int cmdline_size, kernel_size, initrd_size;
> +    int initrd_addr, kernel_addr, cmdline_addr, end;
> +    MachineState *machine = MACHINE(pcms);
> +    const char *kernel_cmdline = machine->kernel_cmdline;
> +    struct sev_cfg_data *sev_cfg;
> +    char *cmdline_string;
> +
> +    /* load kernel command line string */
> +    cmdline_addr = 0x1000000;
> +    cmdline_size = round_up(strlen(kernel_cmdline), 16);
> +    cmdline_string = g_malloc(cmdline_size);
> +    strncpy(cmdline_string, kernel_cmdline, strlen(kernel_cmdline));
> +    rom_add_blob_fixed("cmdline", cmdline_string, cmdline_size, cmdline_addr);
> +    g_free(cmdline_string);
> +
> +    /* load linux kernel */
> +    kernel_addr = cmdline_addr + cmdline_size;
> +    sev_load_file_fixed(machine->kernel_filename, kernel_addr,
> +            &initrd_addr, &kernel_size);
> +
> +    /* load initrd */
> +    f = fopen(machine->initrd_filename, "rb");
> +    if (f) {
> +        sev_load_file_fixed(machine->initrd_filename, initrd_addr,
> +                &end, &initrd_size);
> +    } else {
> +        initrd_addr = 0;
> +        initrd_size = 0;
> +    }
> +
> +    sev_cfg = g_malloc0(sizeof(*sev_cfg));
> +    sev_cfg->kernel_addr = kernel_addr;
> +    sev_cfg->initrd_addr = initrd_addr;
> +    sev_cfg->cmdline_addr = cmdline_addr;
> +    sev_cfg->kernel_size = kernel_size;
> +    sev_cfg->initrd_size = initrd_size;
> +    sev_cfg->cmdline_size = cmdline_size;
> +
> +    fw_cfg_add_file(fw_cfg, "etc/sev_cfg", sev_cfg, sizeof(*sev_cfg));
> +}
> +
>  static void load_linux(PCMachineState *pcms,
>                         FWCfgState *fw_cfg)
>  {
> @@ -1471,7 +1560,10 @@ void pc_memory_init(PCMachineState *pcms,
>      }
>  
>      if (linux_boot) {
> -        load_linux(pcms, fw_cfg);
> +        if (kvm_sev_enabled())
> +            sev_load_linux(pcms, fw_cfg);
> +        else
> +            load_linux(pcms, fw_cfg);
>      }
>  
>      for (i = 0; i < nb_option_roms; i++) {

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Brijesh Singh
@ 2016-09-13 18:39   ` Michael S. Tsirkin
  2016-09-13 20:46     ` Brijesh Singh
  2016-09-13 22:53   ` Paolo Bonzini
  1 sibling, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-13 18:39 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:50:06AM -0400, Brijesh Singh wrote:
> In SEV-enabled guest dma should be performed on shared pages. Since
> the SeaBIOS executes in non PAE mode and does not have access to C-bit
> to create a shared page hence disable the dma operation when reading
> from fw_cfg interface.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

Why do we need new interfaces for this though? Just
set dma_enabled=false on command line.

> ---
>  hw/nvram/fw_cfg.c |    6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 6a68e59..aca99e9 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -24,6 +24,7 @@
>  #include "qemu/osdep.h"
>  #include "hw/hw.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
>  #include "sysemu/dma.h"
>  #include "hw/boards.h"
>  #include "hw/isa/isa.h"
> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
>      FWCfgIoState *s = FW_CFG_IO(dev);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>  
> +    /* disable dma on fw_cfg when SEV is enabled */
> +    if (kvm_sev_enabled()) {
> +        qdev_prop_set_bit(dev, "dma_enabled", false);
> +    }
> +
>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
>       * with half of the 16-bit control register. Hence, the total size
>       * of the i/o region used is FW_CFG_CTL_SIZE */

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest Brijesh Singh
@ 2016-09-13 18:47   ` Michael S. Tsirkin
  2016-09-13 22:59   ` Paolo Bonzini
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-13 18:47 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:50:24AM -0400, Brijesh Singh wrote:
> In SEV-enabled mode we need to reload the BIOS image on loader reset, this
> will ensure that BIOS image gets encrypted and included as part of launch
> meausrement on guest reset.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

Could you pls explain what does measurement mean in this
context, and how is it helpful to reload rom on
every boot as opposed to first boot after migration?


> ---
>  hw/core/loader.c |    7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index 53e0e41..9b03bfe 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -55,6 +55,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/boards.h"
>  #include "qemu/cutils.h"
> +#include "sysemu/kvm.h"
>  
>  #include <zlib.h>
>  
> @@ -1011,7 +1012,11 @@ static void rom_reset(void *unused)
>              cpu_physical_memory_write_rom(&address_space_memory,
>                                            rom->addr, rom->data, rom->datasize);
>          }
> -        if (rom->isrom) {
> +
> +        /* reload the rom on SEV-enabled guest so that it gets included into
> +         * guest memory measurement on system reset.
> +         */
> +        if (!kvm_sev_enabled() && rom->isrom) {
>              /* rom needs to be written only once */
>              g_free(rom->data);
>              rom->data = NULL;

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 15:58   ` Eduardo Habkost
@ 2016-09-13 19:54     ` Brijesh Singh
  2016-09-13 20:10       ` Michael S. Tsirkin
  2016-09-13 22:00       ` Eduardo Habkost
  0 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 19:54 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: brijesh.singh, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

Hi Eduardo,

On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
>>
>> A typical SEV config file looks like this:
>>
>
> Are those config options documented somewhere?
>

Various commands and parameters are documented [1]

[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

>> [sev-launch]
>> 	flags = "00000000"
>> 	policy	= "000000"
>> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
>> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
>> 	nonce = "0123456789abcdef"
>> 	vcpu_count = "1"
>> 	vcpu_length = "30"
>> 	vcpu_mask = "00ab"
>
> Why a separate config file loading mechanism? If the user really
> needs to load the SEV configuration data from a separate file,
> you can just use regular config sections and use -readconfig.
>
I will look into -readconfig and see if we can use that.

> Now, about the format of the new config sections ("sev" and
> "sev-launch"): I am not sure adding new command-line options and
> config sections is necessary. Is it possible to implement it as a
> combination of:
> * new options to existing command-line options and/or
> * new options to existing objects and/or
> * new options to existing devices and/or
> * new types for -object? (see how crypto secrets and net filters
>   are configured, for an example)
>
>

All these config parameters should be provided by the guest owner before 
launching or migrating a guest. I believe we need to make changes in 
libvirt, virsh and other upper layer software stack to communicate with 
guest owner to get these input parameters. For development purposes I 
choose a simple config file to get these parameters. I am not sure if we 
will able to "add new option to a existing objects/device" but we can 
look into creating a "new type for -object" or we can simply accept a fd 
from upper layer and read the fd to get these parameters.

> [...]
>>  extern bool kvm_allowed;
>> +extern bool kvm_sev_allowed;
>
> Can we place this inside struct KVMState?
>
Yes, i will add this in v2.
>>  extern bool kvm_kernel_irqchip;
>>  extern bool kvm_split_irqchip;
>>  extern bool kvm_async_interrupts_allowed;
> [...]
>> @@ -1745,6 +1747,10 @@ static int kvm_init(MachineState *ms)
>>
>>      kvm_state = s;
>>
>> +    if (!sev_init(kvm_state)) {
>> +        kvm_sev_allowed = true;
>> +    }
>
> sev_init() errors are being ignored here. sev_init() could report
> errors properly using Error** (and kvm_init() should not ignore
> them).
Thanks, will fix in v2.
>
>> +
>>      if (kvm_eventfds_allowed) {
>>          s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
>>          s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
> [...]
>> +
>> +struct SEVInfo {
>> +    uint8_t state;  /* guest current state */
>> +    uint8_t type;   /* guest type (encrypted, unencrypted) */
>> +    struct kvm_sev_launch_start *launch_start;
>> +    struct kvm_sev_launch_update *launch_update;
>> +    struct kvm_sev_launch_finish *launch_finish;
>> +};
>> +
>> +typedef struct SEVInfo SEVInfo;
>> +static SEVInfo *sev_info;
>
> Can we place this pointer inside struct KVMState?
>
Will try to move into KVMState.
> [...]
>> +static unsigned int read_config_u32(QemuOpts *opts, const char *key)
>> +{
>> +    unsigned int val;
>> +
>> +    val = qemu_opt_get_number_del(opts, key, -1);
>> +    DPRINTF(" %s = %08x\n", key, val);
>> +
>> +    return val;
>> +}
>> +
>> +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
>
> Function name confused me (it seemed to read only one u8 value).
>
I will fix the name, the function converts string into a hex bytes 
array. e.g "12aabbccdd" is converted to val[] = {0x12,0xaa,0xbb,0xcc, 0xdd}.

>> +{
>> +    int i;
>> +    const char *v;
>> +
>> +    v = qemu_opt_get(opts, key);
>> +    if (!v) {
>> +        return 0;
>> +    }
>> +
>> +    DPRINTF(" %s = ", key);
>> +    i = 0;
>> +    while (*v) {
>> +        sscanf(v, "%2hhx", &val[i]);
>
> Function doesn't check for array length.
Thanks, i will fix this.
>
>> +        DPRINTF("%02hhx", val[i]);
>> +        v += 2;
>> +        i++;
>> +    }
>> +    DPRINTF("\n");
>> +
>> +    return i;
>
> Do we really need to write our own parser? I wonder if we can
> reuse crypto/secret.c for loading the keys.
>
I just looked at crypto/secret.c for loading the keys but not sure if 
will able to reuse the secret_load routines, this is mainly because the 
SEV inputs parameters are different compare to what we have in 
crypto/secrets.c. I will still look more closely and see if we can find 
some common code.
>> +}
>> +
> [...]
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 19:54     ` Brijesh Singh
@ 2016-09-13 20:10       ` Michael S. Tsirkin
  2016-09-13 22:00       ` Eduardo Habkost
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-13 20:10 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Eduardo Habkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 02:54:40PM -0500, Brijesh Singh wrote:
> Hi Eduardo,
> 
> On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
> > > 
> > > A typical SEV config file looks like this:
> > > 
> > 
> > Are those config options documented somewhere?
> > 
> 
> Various commands and parameters are documented [1]
> 
> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

Could you write a TL;DR summary?

IMHO it's not reasonable to ask that people read spec
documents in order to understand QEMU command line
parameters or config flags.

Some text should also go into docs/

> > > [sev-launch]
> > > 	flags = "00000000"
> > > 	policy	= "000000"
> > > 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> > > 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> > > 	nonce = "0123456789abcdef"
> > > 	vcpu_count = "1"
> > > 	vcpu_length = "30"
> > > 	vcpu_mask = "00ab"
> > 
> > Why a separate config file loading mechanism? If the user really
> > needs to load the SEV configuration data from a separate file,
> > you can just use regular config sections and use -readconfig.
> > 
> I will look into -readconfig and see if we can use that.
> 
> > Now, about the format of the new config sections ("sev" and
> > "sev-launch"): I am not sure adding new command-line options and
> > config sections is necessary. Is it possible to implement it as a
> > combination of:
> > * new options to existing command-line options and/or
> > * new options to existing objects and/or
> > * new options to existing devices and/or
> > * new types for -object? (see how crypto secrets and net filters
> >   are configured, for an example)
> > 
> > 
> 
> All these config parameters should be provided by the guest owner before
> launching or migrating a guest. I believe we need to make changes in
> libvirt, virsh and other upper layer software stack to communicate with
> guest owner to get these input parameters. For development purposes I choose
> a simple config file to get these parameters. I am not sure if we will able
> to "add new option to a existing objects/device" but we can look into
> creating a "new type for -object" or we can simply accept a fd from upper
> layer and read the fd to get these parameters.
> 
> > [...]
> > >  extern bool kvm_allowed;
> > > +extern bool kvm_sev_allowed;
> > 
> > Can we place this inside struct KVMState?
> > 
> Yes, i will add this in v2.
> > >  extern bool kvm_kernel_irqchip;
> > >  extern bool kvm_split_irqchip;
> > >  extern bool kvm_async_interrupts_allowed;
> > [...]
> > > @@ -1745,6 +1747,10 @@ static int kvm_init(MachineState *ms)
> > > 
> > >      kvm_state = s;
> > > 
> > > +    if (!sev_init(kvm_state)) {
> > > +        kvm_sev_allowed = true;
> > > +    }
> > 
> > sev_init() errors are being ignored here. sev_init() could report
> > errors properly using Error** (and kvm_init() should not ignore
> > them).
> Thanks, will fix in v2.
> > 
> > > +
> > >      if (kvm_eventfds_allowed) {
> > >          s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
> > >          s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
> > [...]
> > > +
> > > +struct SEVInfo {
> > > +    uint8_t state;  /* guest current state */
> > > +    uint8_t type;   /* guest type (encrypted, unencrypted) */
> > > +    struct kvm_sev_launch_start *launch_start;
> > > +    struct kvm_sev_launch_update *launch_update;
> > > +    struct kvm_sev_launch_finish *launch_finish;
> > > +};
> > > +
> > > +typedef struct SEVInfo SEVInfo;
> > > +static SEVInfo *sev_info;
> > 
> > Can we place this pointer inside struct KVMState?
> > 
> Will try to move into KVMState.
> > [...]
> > > +static unsigned int read_config_u32(QemuOpts *opts, const char *key)
> > > +{
> > > +    unsigned int val;
> > > +
> > > +    val = qemu_opt_get_number_del(opts, key, -1);
> > > +    DPRINTF(" %s = %08x\n", key, val);
> > > +
> > > +    return val;
> > > +}
> > > +
> > > +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
> > 
> > Function name confused me (it seemed to read only one u8 value).
> > 
> I will fix the name, the function converts string into a hex bytes array.
> e.g "12aabbccdd" is converted to val[] = {0x12,0xaa,0xbb,0xcc, 0xdd}.
> 
> > > +{
> > > +    int i;
> > > +    const char *v;
> > > +
> > > +    v = qemu_opt_get(opts, key);
> > > +    if (!v) {
> > > +        return 0;
> > > +    }
> > > +
> > > +    DPRINTF(" %s = ", key);
> > > +    i = 0;
> > > +    while (*v) {
> > > +        sscanf(v, "%2hhx", &val[i]);
> > 
> > Function doesn't check for array length.
> Thanks, i will fix this.
> > 
> > > +        DPRINTF("%02hhx", val[i]);
> > > +        v += 2;
> > > +        i++;
> > > +    }
> > > +    DPRINTF("\n");
> > > +
> > > +    return i;
> > 
> > Do we really need to write our own parser? I wonder if we can
> > reuse crypto/secret.c for loading the keys.
> > 
> I just looked at crypto/secret.c for loading the keys but not sure if will
> able to reuse the secret_load routines, this is mainly because the SEV
> inputs parameters are different compare to what we have in crypto/secrets.c.
> I will still look more closely and see if we can find some common code.
> > > +}
> > > +
> > [...]
> > 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 18:39   ` Michael S. Tsirkin
@ 2016-09-13 20:46     ` Brijesh Singh
  2016-09-13 20:55       ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-13 20:46 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: brijesh.singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

Hi Michael,

On 09/13/2016 01:39 PM, Michael S. Tsirkin wrote:
> On Tue, Sep 13, 2016 at 10:50:06AM -0400, Brijesh Singh wrote:
>> In SEV-enabled guest dma should be performed on shared pages. Since
>> the SeaBIOS executes in non PAE mode and does not have access to C-bit
>> to create a shared page hence disable the dma operation when reading
>> from fw_cfg interface.
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>
> Why do we need new interfaces for this though? Just
> set dma_enabled=false on command line.
>

Thanks, i was not aware of dma_enabled=false command line option.
Could you please tell me how to set this command line option?

I see this in 'qemu --help'

-fw_cfg [name=]<name>,file=<file>
                  add named fw_cfg entry from file
-fw_cfg [name=]<name>,string=<str>
                  add named fw_cfg entry from string


>> ---
>>  hw/nvram/fw_cfg.c |    6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
>> index 6a68e59..aca99e9 100644
>> --- a/hw/nvram/fw_cfg.c
>> +++ b/hw/nvram/fw_cfg.c
>> @@ -24,6 +24,7 @@
>>  #include "qemu/osdep.h"
>>  #include "hw/hw.h"
>>  #include "sysemu/sysemu.h"
>> +#include "sysemu/kvm.h"
>>  #include "sysemu/dma.h"
>>  #include "hw/boards.h"
>>  #include "hw/isa/isa.h"
>> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
>>      FWCfgIoState *s = FW_CFG_IO(dev);
>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>
>> +    /* disable dma on fw_cfg when SEV is enabled */
>> +    if (kvm_sev_enabled()) {
>> +        qdev_prop_set_bit(dev, "dma_enabled", false);
>> +    }
>> +
>>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
>>       * with half of the 16-bit control register. Hence, the total size
>>       * of the i/o region used is FW_CFG_CTL_SIZE */

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 20:46     ` Brijesh Singh
@ 2016-09-13 20:55       ` Michael S. Tsirkin
  0 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-13 20:55 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 03:46:15PM -0500, Brijesh Singh wrote:
> Hi Michael,
> 
> On 09/13/2016 01:39 PM, Michael S. Tsirkin wrote:
> > On Tue, Sep 13, 2016 at 10:50:06AM -0400, Brijesh Singh wrote:
> > > In SEV-enabled guest dma should be performed on shared pages. Since
> > > the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > > to create a shared page hence disable the dma operation when reading
> > > from fw_cfg interface.
> > > 
> > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > 
> > Why do we need new interfaces for this though? Just
> > set dma_enabled=false on command line.
> > 
> 
> Thanks, i was not aware of dma_enabled=false command line option.
> Could you please tell me how to set this command line option?
> 
> I see this in 'qemu --help'
> 
> -fw_cfg [name=]<name>,file=<file>
>                  add named fw_cfg entry from file
> -fw_cfg [name=]<name>,string=<str>
>                  add named fw_cfg entry from string
> 

For example, set it on all fw cfg devices:

-global fw_cfg.dma_enabled=false

should work.

> > > ---
> > >  hw/nvram/fw_cfg.c |    6 ++++++
> > >  1 file changed, 6 insertions(+)
> > > 
> > > diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > > index 6a68e59..aca99e9 100644
> > > --- a/hw/nvram/fw_cfg.c
> > > +++ b/hw/nvram/fw_cfg.c
> > > @@ -24,6 +24,7 @@
> > >  #include "qemu/osdep.h"
> > >  #include "hw/hw.h"
> > >  #include "sysemu/sysemu.h"
> > > +#include "sysemu/kvm.h"
> > >  #include "sysemu/dma.h"
> > >  #include "hw/boards.h"
> > >  #include "hw/isa/isa.h"
> > > @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> > >      FWCfgIoState *s = FW_CFG_IO(dev);
> > >      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > > 
> > > +    /* disable dma on fw_cfg when SEV is enabled */
> > > +    if (kvm_sev_enabled()) {
> > > +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > > +    }
> > > +
> > >      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> > >       * with half of the 16-bit control register. Hence, the total size
> > >       * of the i/o region used is FW_CFG_CTL_SIZE */

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 19:54     ` Brijesh Singh
  2016-09-13 20:10       ` Michael S. Tsirkin
@ 2016-09-13 22:00       ` Eduardo Habkost
  2016-09-14  8:30         ` Daniel P. Berrange
  2016-09-14 16:10         ` Brijesh Singh
  1 sibling, 2 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-13 22:00 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: crosthwaite.peter, armbru, mst, p.fedin, qemu-devel, lcapitulino,
	pbonzini, rth, Daniel P. Berrange

(CCing Daniel Berrange in case he has feedback on the
nonce/dh_pub_qx/dh_pub_qy loading/parsing at the end of this
message)

On Tue, Sep 13, 2016 at 02:54:40PM -0500, Brijesh Singh wrote:
> Hi Eduardo,
> 
> On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
> > > 
> > > A typical SEV config file looks like this:
> > > 
> > 
> > Are those config options documented somewhere?
> > 
> 
> Various commands and parameters are documented [1]
> 
> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

If I understand correctly, the docs describe the firmware
interface. The interface provided by QEMU is not the same thing,
and needs to be documented as well (even if it contains pointers
to sections or tables in the firmware interface docs).

Some of the questions I have about the fields are:
* Do we really need the user to provide all the options below?
  * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
    for example?
* Is bit 0 (KS) the only bit that can be set on flags? If so, why
  not a boolean "ks" option?
* Is "policy" the guest policy structure described at page 23? If
  so, why exposing the raw value instead of separate fields for
  each bit/field in the structure? (and only for the ones that
  are supposed to be set by the user)
* If vcpu_mask is a bitmap for each VCPU, should we represent it
  as a list of VCPU indexes?

A good way to model this data and document it more properly is
through a QAPI schema. grep for "opts_visitor_new()" in the code
for examples where QEMU options are parsed according to a QAPI
schema. The downside is that using a QAPI visitor is (AFAIK) not
possible if using -object like I suggest below.

> 
> > > [sev-launch]
> > > 	flags = "00000000"
> > > 	policy	= "000000"
> > > 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> > > 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> > > 	nonce = "0123456789abcdef"
> > > 	vcpu_count = "1"
> > > 	vcpu_length = "30"
> > > 	vcpu_mask = "00ab"
> > 
> > Why a separate config file loading mechanism? If the user really
> > needs to load the SEV configuration data from a separate file,
> > you can just use regular config sections and use -readconfig.
> > 
> I will look into -readconfig and see if we can use that.
> 
> > Now, about the format of the new config sections ("sev" and
> > "sev-launch"): I am not sure adding new command-line options and
> > config sections is necessary. Is it possible to implement it as a
> > combination of:
> > * new options to existing command-line options and/or
> > * new options to existing objects and/or
> > * new options to existing devices and/or
> > * new types for -object? (see how crypto secrets and net filters
> >   are configured, for an example)
> > 
> > 
> 
> All these config parameters should be provided by the guest owner before
> launching or migrating a guest. I believe we need to make changes in
> libvirt, virsh and other upper layer software stack to communicate with
> guest owner to get these input parameters. For development purposes I choose
> a simple config file to get these parameters. I am not sure if we will able
> to "add new option to a existing objects/device" but we can look into
> creating a "new type for -object" or we can simply accept a fd from upper
> layer and read the fd to get these parameters.

I was thinking of something like:

  -object sev-launch-rule,flags=0,policy=0,dh_pub_qx=XXXXX,dh_pub_qy=YYYYY,nonce=ZZZZ,vcpu_count=1,vcpu_length=30,vcpu_mask=00ab \
  -machine pc,accel=kvm,sev=on  # see note below[1]

With this, you won't need separate code for command-line, config
files, and QMP commands. They will all be able to use the same
mechanisms.

...but this conflicts with the idea of using QAPI. So I am not
sure which way to go. (But either way we go, we need a clearer
and better documented set of parameters).

[1] I would go even further and separate the accel object options
    from the machine options, but this would require reworking
    the accelerator configuration inside QEMU. e.g.:

  -object kvm-accel,sev=on,id=kvm0
  -machine pc,accel=kvm0

[...]
> > > +static unsigned int read_config_u32(QemuOpts *opts, const char *key)
> > > +{
> > > +    unsigned int val;
> > > +
> > > +    val = qemu_opt_get_number_del(opts, key, -1);
> > > +    DPRINTF(" %s = %08x\n", key, val);
> > > +
> > > +    return val;
> > > +}
> > > +
> > > +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
> > 
> > Function name confused me (it seemed to read only one u8 value).
> > 
> I will fix the name, the function converts string into a hex bytes array.
> e.g "12aabbccdd" is converted to val[] = {0x12,0xaa,0xbb,0xcc, 0xdd}.
> 
> > > +{
> > > +    int i;
> > > +    const char *v;
> > > +
> > > +    v = qemu_opt_get(opts, key);
> > > +    if (!v) {
> > > +        return 0;
> > > +    }
> > > +
> > > +    DPRINTF(" %s = ", key);
> > > +    i = 0;
> > > +    while (*v) {
> > > +        sscanf(v, "%2hhx", &val[i]);
> > 
> > Function doesn't check for array length.
> Thanks, i will fix this.
> > 
> > > +        DPRINTF("%02hhx", val[i]);
> > > +        v += 2;
> > > +        i++;
> > > +    }
> > > +    DPRINTF("\n");
> > > +
> > > +    return i;
> > 
> > Do we really need to write our own parser? I wonder if we can
> > reuse crypto/secret.c for loading the keys.
> > 
> I just looked at crypto/secret.c for loading the keys but not sure if will
> able to reuse the secret_load routines, this is mainly because the SEV
> inputs parameters are different compare to what we have in crypto/secrets.c.
> I will still look more closely and see if we can find some common code.

There are other parameters, sure, but maybe it would be
appropriate to just load nonce/dh_pub_qx/dh_pub_qy as
TTYPE_QCRYPTO_SECRET object(s) (-object secret,...)? I am not
sure because I don't understand the crypto part fully.

Daniel, what do you think?

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command Brijesh Singh
@ 2016-09-13 22:15   ` Eduardo Habkost
  0 siblings, 0 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-13 22:15 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: crosthwaite.peter, armbru, mst, p.fedin, qemu-devel, lcapitulino,
	pbonzini, rth

On Tue, Sep 13, 2016 at 10:48:18AM -0400, Brijesh Singh wrote:
> The SEV LAUNCH_FINISH command is used for finalizing the guest launch
> process. The commad returned a measurement value that can be handed to
> the guest owner to validate the guest before vmrun.
> 
> For more information see [1], section 6.3
> 
> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> 
> The following KVM RFC patches defines and implements this command
> http://marc.info/?l=kvm&m=147190852423972&w=2
> http://marc.info/?l=kvm&m=147190856623987&w=2
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[...]
> +int kvm_sev_guest_measurement(uint8_t *out)

I don't see any code calling this function yet. Do you have any
plans on how exactly this will be handed back to the guest owner?
A QMP command?

> +{
> +    SEVInfo *s = sev_info;
> +    struct kvm_sev_launch_finish *finish = s->launch_finish;
> +
> +    if (!s) {
> +        return 1;
> +    }
> +
> +    if (s->type == UNENCRYPTED_GUEST &&
> +            s->state == SEV_LAUNCH_FINISH) {
> +        memcpy(out, finish->measurement, 32);
> +    } else {
> +        return 1;

Probably it would be more appropriate to use Error** to report
errors in most of the code in this series.

> +    }
> +
> +    return 0;
> +}
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest Brijesh Singh
@ 2016-09-13 22:41   ` Paolo Bonzini
  2016-09-14  8:41     ` Daniel P. Berrange
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 22:41 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:47, Brijesh Singh wrote:
> The patch adds '-sev' option to enable the Secure Encrypted
> Virtualization (SEV) guest. If this option is specified, Qemu
> assumes that user wants to launch this guest into SEV mode.
> 
> Here are example on how to launch a guest into SEV mode.
> 
> 1) late launch: in this mode the images received from guest
> owner are unencrypted and must be encrypted using SEV LAUNCH command
> before starting the guest.
> 
> $ qemu -sev type=unencrypted config=guest_01.conf
> 
> 2) pre-encrypted: in this mode the images received from guest
> owners are encrypted using transport keys. It must be re-encrypted
> using SEV RECEIVE commands before starting the guest.
> 
> $ qemu -sev type=encrypted config=guest_02.conf
> 
> The config file will contains various parameters (e.g key , policy)
> required during guest launch process.

Any reason not to pass the sev options themselves through -sev?  You can
then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains

	[sev]
	type="encrypted"
	flags = "00000000"
	policy	= "000000"
	dh_pub_qx = "0123456789abcdef0123456789abcdef"
	dh_pub_qy = "0123456789abcdef0123456789abcdef"
	nonce = "0123456789abcdef"
	vcpu_count = "1"
	vcpu_length = "30"
	vcpu_mask = "00ab"

Paolo

> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  qemu-options.hx |    6 ++++++
>  vl.c            |   29 +++++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/qemu-options.hx b/qemu-options.hx
> index a71aaf8..1b6aa82 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -118,6 +118,12 @@ given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
>  specifies the maximum number of hotpluggable CPUs.
>  ETEXI
>  
> +DEF("sev", HAS_ARG, QEMU_OPTION_sev,
> +    "-sev type=[encrypted,unencrypted] config=<file>\n"
> +    "                image type (encrypted or unencrypted)\n"
> +    "                set the config file for SEV guest\n",
> +        QEMU_ARCH_I386)
> +
>  DEF("numa", HAS_ARG, QEMU_OPTION_numa,
>      "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n"
>      "-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
> diff --git a/vl.c b/vl.c
> index b3c80d5..22b8eba 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -178,6 +178,7 @@ bool boot_strict;
>  uint8_t *boot_splash_filedata;
>  size_t boot_splash_filedata_size;
>  uint8_t qemu_extra_params_fw[2];
> +static bool sev_allowed;
>  
>  int icount_align_option;
>  
> @@ -506,6 +507,25 @@ static QemuOptsList qemu_fw_cfg_opts = {
>      },
>  };
>  
> +static QemuOptsList qemu_sev_opts = {
> +    .name = "sev",
> +    .implied_opt_name = "name",
> +    .head = QTAILQ_HEAD_INITIALIZER(qemu_sev_opts.head),
> +    .desc = {
> +        {
> +            .name = "config",
> +            .type = QEMU_OPT_STRING,
> +            .help = "Set the SEV config file\n",
> +        },
> +        {
> +            .name = "type",
> +            .type = QEMU_OPT_STRING,
> +            .help = "Set the image type (encrypted or unencrypted)\n",
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
>  /**
>   * Get machine options
>   *
> @@ -3002,6 +3022,7 @@ int main(int argc, char **argv, char **envp)
>      qemu_add_opts(&qemu_icount_opts);
>      qemu_add_opts(&qemu_semihosting_config_opts);
>      qemu_add_opts(&qemu_fw_cfg_opts);
> +    qemu_add_opts(&qemu_sev_opts);
>      module_call_init(MODULE_INIT_OPTS);
>  
>      runstate_init();
> @@ -3970,6 +3991,14 @@ int main(int argc, char **argv, char **envp)
>                      exit(1);
>                  }
>                  break;
> +            case QEMU_OPTION_sev:
> +                olist = qemu_find_opts("sev");
> +                opts = qemu_opts_parse_noisily(olist, optarg, true);
> +                if (!opts) {
> +                    exit(1);
> +                }
> +                sev_allowed = true;
> +                break;
>              default:
>                  os_parse_cmd_args(popt->index, optarg);
>              }
> 
> 
> 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback Brijesh Singh
@ 2016-09-13 22:47   ` Paolo Bonzini
  2016-09-14 16:19     ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 22:47 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:50, Brijesh Singh wrote:
> This patch adds methods to register a callback in qemu_system_reset().
> 
> - qemu_register_pre_reset() : function will be called just after
>   entering into qemu_system_reset().
> - qemu_register_post_reset(): function will be called just before
>   exiting from the qemu_system_reset().
> 
> A qemu_system_reset() causes loader to reload the OS images into guest
> memory. In case of SEV-enabled guest we need to call the SEV launch start
> command before loader copies any data into guest RAM and similarly SEV
> launch finish command should be executed after we finished copying the
> data into guest memory.
> 
> These callback will allow us to hook the SEV launch START and FINISH
> commands into qemu_system_reset() handlder to start and finalize the SEV
> guest launch process.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

I would just put the SEV hook in qemu_system_reset().

You can use a new file sev-stub.c with an empty implementation of
kvm_sev_guest_start and kvm_sev_guest_finish.

Paolo

> ---
>  include/hw/hw.h |    2 ++
>  sev.c           |   14 ++++++++++++++
>  vl.c            |   45 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 61 insertions(+)
> 
> diff --git a/include/hw/hw.h b/include/hw/hw.h
> index 3669ebd..31dcf9f 100644
> --- a/include/hw/hw.h
> +++ b/include/hw/hw.h
> @@ -17,6 +17,8 @@ typedef void QEMUResetHandler(void *opaque);
>  
>  void qemu_register_reset(QEMUResetHandler *func, void *opaque);
>  void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
> +void qemu_register_pre_reset(QEMUResetHandler *func, void *opaque);
> +void qemu_register_post_reset(QEMUResetHandler *func, void *opaque);
>  
>  void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
>  
> diff --git a/sev.c b/sev.c
> index c1135c4..141f9d6 100644
> --- a/sev.c
> +++ b/sev.c
> @@ -35,6 +35,7 @@
>  #include "qemu/event_notifier.h"
>  #include "trace.h"
>  #include "hw/irq.h"
> +#include "hw/hw.h"
>  
>  //#define DEBUG_SEV
>  
> @@ -257,6 +258,16 @@ static int parse_sev_cfg(SEVInfo *s, int type, const char *filename)
>  
>  }
>  
> +static void sev_pre_reset_handler(void *data)
> +{
> +    kvm_sev_guest_start();
> +}
> +
> +static void sev_post_reset_handler(void *data)
> +{
> +    kvm_sev_guest_finish();
> +}
> +
>  int sev_init(KVMState *kvm_state)
>  {
>      QemuOpts *opts;
> @@ -287,6 +298,9 @@ int sev_init(KVMState *kvm_state)
>          goto err;
>      }
>  
> +    qemu_register_pre_reset(sev_pre_reset_handler, sev_info);
> +    qemu_register_post_reset(sev_post_reset_handler, sev_info);
> +
>      return kvm_sev_guest_start();
>  err:
>      free(sev_info);
> diff --git a/vl.c b/vl.c
> index 22b8eba..5923c73 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -25,6 +25,7 @@
>  #include "qemu-version.h"
>  #include "qemu/cutils.h"
>  #include "qemu/help_option.h"
> +#include "sysemu/sev.h"
>  
>  #ifdef CONFIG_SECCOMP
>  #include "sysemu/seccomp.h"
> @@ -1630,6 +1631,10 @@ static NotifierList suspend_notifiers =
>  static NotifierList wakeup_notifiers =
>      NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
>  static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> +static QTAILQ_HEAD(pre_reset_handlers, QEMUResetEntry) pre_reset_handlers =
> +    QTAILQ_HEAD_INITIALIZER(pre_reset_handlers);
> +static QTAILQ_HEAD(post_reset_handlers, QEMUResetEntry)
> +    post_reset_handlers = QTAILQ_HEAD_INITIALIZER(post_reset_handlers);
>  
>  int qemu_shutdown_requested_get(void)
>  {
> @@ -1733,12 +1738,51 @@ void qemu_devices_reset(void)
>      }
>  }
>  
> +void qemu_register_pre_reset(QEMUResetHandler *func, void *opaque)
> +{
> +    QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
> +
> +    re->func = func;
> +    re->opaque = opaque;
> +    QTAILQ_INSERT_TAIL(&pre_reset_handlers, re, entry);
> +}
> +
> +static void qemu_system_pre_reset(void)
> +{
> +    QEMUResetEntry *re, *nre;
> +
> +    /* call pre_reset handler */
> +    QTAILQ_FOREACH_SAFE(re, &pre_reset_handlers, entry, nre) {
> +        re->func(re->opaque);
> +    }
> +}
> +
> +void qemu_register_post_reset(QEMUResetHandler *func, void *opaque)
> +{
> +    QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
> +
> +    re->func = func;
> +    re->opaque = opaque;
> +    QTAILQ_INSERT_TAIL(&post_reset_handlers, re, entry);
> +}
> +
> +static void qemu_system_post_reset(void)
> +{
> +    QEMUResetEntry *re, *nre;
> +
> +    /* call post reset handler */
> +    QTAILQ_FOREACH_SAFE(re, &post_reset_handlers, entry, nre) {
> +        re->func(re->opaque);
> +    }
> +}
> +
>  void qemu_system_reset(bool report)
>  {
>      MachineClass *mc;
>  
>      mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
>  
> +    qemu_system_pre_reset();
>      cpu_synchronize_all_states();
>  
>      if (mc && mc->reset) {
> @@ -1750,6 +1794,7 @@ void qemu_system_reset(bool report)
>          qapi_event_send_reset(&error_abort);
>      }
>      cpu_synchronize_all_post_reset();
> +    qemu_system_post_reset();
>  }
>  
>  void qemu_system_guest_panicked(void)
> 
> 
> 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Brijesh Singh
  2016-09-13 18:39   ` Michael S. Tsirkin
@ 2016-09-13 22:53   ` Paolo Bonzini
  2016-09-14  2:33     ` Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 22:53 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:50, Brijesh Singh wrote:
> In SEV-enabled guest dma should be performed on shared pages. Since
> the SeaBIOS executes in non PAE mode and does not have access to C-bit
> to create a shared page hence disable the dma operation when reading
> from fw_cfg interface.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  hw/nvram/fw_cfg.c |    6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 6a68e59..aca99e9 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -24,6 +24,7 @@
>  #include "qemu/osdep.h"
>  #include "hw/hw.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
>  #include "sysemu/dma.h"
>  #include "hw/boards.h"
>  #include "hw/isa/isa.h"
> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
>      FWCfgIoState *s = FW_CFG_IO(dev);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>  
> +    /* disable dma on fw_cfg when SEV is enabled */
> +    if (kvm_sev_enabled()) {
> +        qdev_prop_set_bit(dev, "dma_enabled", false);
> +    }
> +
>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
>       * with half of the 16-bit control register. Hence, the total size
>       * of the i/o region used is FW_CFG_CTL_SIZE */
> 
> 
> 

As Michael said, a workaround is possible using -global.  However, I
really think that SEV should be implemented in UEFI firmware.  Because
it runs in 64-bit mode, it would be able to run in paged mode and it
would not have to encrypt everything before the SEV launch command.

For example secure boot can be used to authenticate the kernel against
keys provided by the owner in encrypted flash, or GRUB2 can be placed in
the firmware by the owner and used to boot from a LUKS-encrypted /boot
partition.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest Brijesh Singh
  2016-09-13 18:47   ` Michael S. Tsirkin
@ 2016-09-13 22:59   ` Paolo Bonzini
  2016-09-14  2:38     ` Michael S. Tsirkin
  2016-09-14 20:29     ` Brijesh Singh
  1 sibling, 2 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 22:59 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:50, Brijesh Singh wrote:
> In SEV-enabled mode we need to reload the BIOS image on loader reset, this
> will ensure that BIOS image gets encrypted and included as part of launch
> meausrement on guest reset.

Just to check if I understand correctly, the secure processor cannot
split the encryption and measuring, which is why you need to redo the
copy on every reset.

Does the guest have to check the measured data (e.g. with a hash) too,
to check that it hasn't been tampered with outside the secure
processor's control?  Of course this would result in garbage written to
the modified page, but that might be a valid attack vector.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs Brijesh Singh
@ 2016-09-13 23:00   ` Paolo Bonzini
  2016-09-14 20:30     ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 23:00 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:47, Brijesh Singh wrote:
> The patch adds sev_debug_mode attribute in MemTxAttrs. This attribute
> will be set when debug version of memory read/write API's are used in
> SEV-enabled guest.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  include/exec/memattrs.h |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> index e601061..5aa22b5 100644
> --- a/include/exec/memattrs.h
> +++ b/include/exec/memattrs.h
> @@ -37,6 +37,8 @@ typedef struct MemTxAttrs {
>      unsigned int user:1;
>      /* Requester ID (for MSI for example) */
>      unsigned int requester_id:16;
> +    /* Memory access for debug purposes */
> +    unsigned int sev_debug:1;
>  } MemTxAttrs;
>  
>  /* Bus masters which don't specify any attributes will get this,
> @@ -46,4 +48,6 @@ typedef struct MemTxAttrs {
>   */
>  #define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
>  
> +/* Access the guest memory for debug purposes */
> +#define MEMTXATTRS_SEV_DEBUG ((MemTxAttrs) { .sev_debug = 1 })
>  #endif

Just make it "debug" and MEMTXATTRS_DEBUG.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status Brijesh Singh
  2016-09-13 16:09   ` Eric Blake
@ 2016-09-13 23:01   ` Paolo Bonzini
  1 sibling, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 23:01 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:48, Brijesh Singh wrote:
>  #
> +# @sev: true if SEV is active

You should add "(Since 2.8.0)" here.

Paolo

>  # Since: 0.14.0
>  ##
> -{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
> +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool', 'sev' : 'bool'} }
>  

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region Brijesh Singh
@ 2016-09-13 23:05   ` Paolo Bonzini
  2016-09-14 20:59     ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 23:05 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:49, Brijesh Singh wrote:
>  
> +    /* Register SEV read/write ops for the guest RAM */
> +    if (kvm_sev_enabled())
> +        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());

If you don't actually need this one except for -kernel it would be very
nice, because then the hooks could be limited to cpu_memory_rw_debug.

address_space_write and address_space_read are the central entry point
for device DMA, and calling mr->ram_ops->write from there seems very
wrong.  I'd rather make those hooks *ROM* read/write ops rather than RAM
read/write ops.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest Brijesh Singh
@ 2016-09-13 23:06   ` Paolo Bonzini
  0 siblings, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 23:06 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:49, Brijesh Singh wrote:
> When debug version of physical memory read APIs are called on SEV guest
> then set the MemTxAttrs.sev_debug attribute to indicate that memory
> read/write is requested for debug purposes.
> 
> On SEV guest, the memory region read/write callback will check this
> attribute and if its set then it will use SEV DEBUG DECRYPT/ENCRYPT commands
> to read/write into guest memory.

You should set it always.

Paolo

> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  exec.c |   11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/exec.c b/exec.c
> index 604bd05..b1df25d 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -3773,7 +3773,11 @@ void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
>  {
>      MemTxAttrs attrs;
>  
> -    attrs = MEMTXATTRS_UNSPECIFIED;
> +    if (kvm_sev_enabled()) {
> +        attrs = MEMTXATTRS_SEV_DEBUG;
> +    } else {
> +        attrs = MEMTXATTRS_UNSPECIFIED;
> +    }
>  
>      address_space_rw(&address_space_memory, addr, attrs, buf, len, is_write);
>  }
> @@ -3793,6 +3797,11 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>          page = addr & TARGET_PAGE_MASK;
>          phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, &attrs);
>          asidx = cpu_asidx_from_attrs(cpu, attrs);
> +
> +        if (kvm_sev_enabled()) {
> +            attrs = MEMTXATTRS_SEV_DEBUG;
> +        }
> +
>          /* if no physical page mapped, return an error */
>          if (phys_addr == -1)
>              return -1;
> 
> 
> 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f
  2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f Brijesh Singh
@ 2016-09-13 23:07   ` Paolo Bonzini
  2016-09-21 16:20     ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-13 23:07 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 13/09/2016 16:49, Brijesh Singh wrote:
> Fn8000_001f cpuid provides the memory encryption (aka C-bit)
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  target-i386/cpu.c |    3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index 6a1afab..e039c08 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -2625,6 +2625,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>              *edx = 0;
>          }
>          break;
> +    case 0x8000001F:
> +        host_cpuid(index, 0, eax, ebx, ecx, edx);
> +        break;
>      case 0xC0000000:
>          *eax = env->cpuid_xlevel2;
>          *ebx = 0;
> 
> 
> 

This should only be visible to a SEV-enabled guest.  Also, the xlevel
should be bumped to 0x8000001F for SEV-enabled guests.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
@ 2016-09-14  2:28   ` Michael S. Tsirkin
  2016-09-14  8:57     ` Paolo Bonzini
  2016-09-14 13:36     ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
  0 siblings, 2 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14  2:28 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:48:27AM -0400, Brijesh Singh wrote:
> The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
> for the debugging purposes. Note that debugging is permitting only
> when guest policy allows it.

When wouldn't you want to allow it?
I don't see value in a "break debugging" feature.


> For more information see [1], section 7.1
> 
> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf

Please add comments documenting APIs. Spec links to figure out
implementation is one thing, but you really can't require people
to read specs just to figure out how to use an API.

> The following KVM RFC patches defines and implements this command
> 
> http://marc.info/?l=kvm&m=147190852423972&w=2
> http://marc.info/?l=kvm&m=147191068524579&w=2
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  include/sysemu/sev.h |   10 ++++++++++
>  sev.c                |   23 +++++++++++++++++++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> index ab03c5d..5872c3e 100644
> --- a/include/sysemu/sev.h
> +++ b/include/sysemu/sev.h
> @@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
>   */
>  int kvm_sev_guest_measurement(uint8_t *measurement);
>  
> +/**
> + * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
> + * @src - guest memory address
> + * @dest - host memory address where the decrypted data should be copied
> + * @length - length of memory region
> + *
> + * Returns: 0 on success and dest will contains the decrypted data
> + */
> +int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
> +
>  #endif
> diff --git a/sev.c b/sev.c
> index 055ed83..c7031d3 100644
> --- a/sev.c
> +++ b/sev.c
> @@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
>  
>      return 0;
>  }
> +
> +int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
> +{
> +    int ret;
> +    struct kvm_sev_dbg_decrypt decrypt;
> +    struct kvm_sev_issue_cmd input;
> +
> +    decrypt.src_addr = (unsigned long)src;
> +    decrypt.dst_addr = (unsigned long)dst;
> +    decrypt.length = len;
> +
> +    input.cmd = KVM_SEV_DBG_DECRYPT;
> +    input.opaque = (unsigned long)&decrypt;
> +    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
> +    if (ret) {
> +        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
> +                ret, input.ret_code);
> +        return 1;
> +    }
> +
> +    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
> +    return 0;
> +}

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-13 22:53   ` Paolo Bonzini
@ 2016-09-14  2:33     ` Michael S. Tsirkin
  2016-09-14  8:58       ` Paolo Bonzini
  2016-09-14 12:09       ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Eduardo Habkost
  0 siblings, 2 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14  2:33 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> 
> 
> On 13/09/2016 16:50, Brijesh Singh wrote:
> > In SEV-enabled guest dma should be performed on shared pages. Since
> > the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > to create a shared page hence disable the dma operation when reading
> > from fw_cfg interface.
> > 
> > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > ---
> >  hw/nvram/fw_cfg.c |    6 ++++++
> >  1 file changed, 6 insertions(+)
> > 
> > diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > index 6a68e59..aca99e9 100644
> > --- a/hw/nvram/fw_cfg.c
> > +++ b/hw/nvram/fw_cfg.c
> > @@ -24,6 +24,7 @@
> >  #include "qemu/osdep.h"
> >  #include "hw/hw.h"
> >  #include "sysemu/sysemu.h"
> > +#include "sysemu/kvm.h"
> >  #include "sysemu/dma.h"
> >  #include "hw/boards.h"
> >  #include "hw/isa/isa.h"
> > @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> >      FWCfgIoState *s = FW_CFG_IO(dev);
> >      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> >  
> > +    /* disable dma on fw_cfg when SEV is enabled */
> > +    if (kvm_sev_enabled()) {
> > +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > +    }
> > +
> >      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> >       * with half of the 16-bit control register. Hence, the total size
> >       * of the i/o region used is FW_CFG_CTL_SIZE */
> > 
> > 
> > 
> 
> As Michael said, a workaround is possible using -global.  However, I
> really think that SEV should be implemented in UEFI firmware.  Because
> it runs in 64-bit mode, it would be able to run in paged mode and it
> would not have to encrypt everything before the SEV launch command.
> 
> For example secure boot can be used to authenticate the kernel against
> keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> the firmware by the owner and used to boot from a LUKS-encrypted /boot
> partition.
> 
> Paolo

Frankly I don't understand why do you need to mess with boot at all.
Quoting the cover letter:

	SEV is designed to protect guest VMs from a benign but vulnerable
	(i.e. not fully malicious) hypervisor. In particular, it reduces the
	attack
	surface of guest VMs and can prevent certain types of VM-escape bugs
	(e.g. hypervisor read-anywhere) from being used to steal guest data.

it seems highly unlikely that any secret data is used during boot.
So just let guest boot normally, and encrypt afterwards.

Even assuming there are some guests that have secret data during boot,
I would first upstream the main part of the feature for normal guests,
then weight the extra security if any against the features and
performance lost (like slower boot times).

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-13 22:59   ` Paolo Bonzini
@ 2016-09-14  2:38     ` Michael S. Tsirkin
  2016-09-14 20:29     ` Brijesh Singh
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14  2:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 12:59:32AM +0200, Paolo Bonzini wrote:
> 
> 
> On 13/09/2016 16:50, Brijesh Singh wrote:
> > In SEV-enabled mode we need to reload the BIOS image on loader reset, this
> > will ensure that BIOS image gets encrypted and included as part of launch
> > meausrement on guest reset.
> 
> Just to check if I understand correctly, the secure processor cannot
> split the encryption and measuring, which is why you need to redo the
> copy on every reset.
> 
> Does the guest have to check the measured data (e.g. with a hash) too,
> to check that it hasn't been tampered with outside the secure
> processor's control?

I don't know what does measurement mean in this context as this
patchset was supposed to be about protecting memory so
you don't get to steal guest secrets just because you get to
steal hypervisor secrets.

Guest checking anything at all seems highly unlikely to help
in this context, as they probably already happened by the time
guest is checking things.

> Of course this would result in garbage written to
> the modified page, but that might be a valid attack vector.
> 
> Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD)
  2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (22 preceding siblings ...)
       [not found] ` <147377816978.11859.942423377333907417.stgit@brijesh-build-machine>
@ 2016-09-14  2:55 ` Michael S. Tsirkin
  23 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14  2:55 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:46:46AM -0400, Brijesh Singh wrote:
> This RFC series provides support for AMD's new Secure Encrypted 
> Virtualization (SEV) feature. This RFC is based KVM RFC [1].
> 
> SEV is an extension to the AMD-V architecture which supports running
> multiple VMs under the control of a hypervisor. The SEV feature allows
> the memory contents of a virtual machine (VM) to be transparently encrypted
> with a key unique to the guest VM. The memory controller contains a
> high performance encryption engine which can be programmed with multiple
> keys for use by a different VMs in the system. The programming and
> management of these keys is handled by the AMD Secure Processor firmware
> which exposes a commands for these tasks.
> 
> SEV is designed to protect guest VMs from a benign but vulnerable
> (i.e. not fully malicious) hypervisor.

Not fully malicious?  This sounds kind of weird. In my humble opinion,
the attack needs to be much better defined to be of any use.
I attempt to do this below.

> In particular, it reduces the attack
> surface of guest VMs and can prevent certain types of VM-escape bugs
> (e.g. hypervisor read-anywhere) from being used to steal guest data.

To rephrase this in terms I understand:

someone gets to read all hypervisor memory, we do not
want this someone to be able to read all guest memory too.
Sounds reasonable.

But I don't think you need to break features like debugging: clearly if
you decrypt memory it is readable in hypervisor memory, but I think
that's fine since it's encrypted if you do not debug.  In other words
policy should not be up to guest since fundamentally hypervisor is
benign.

> The KVM RFC introduced a new ioctl (KVM_SEV_ISSUE_CMD) which can be
> used by qemu to enable SEV for secure guest and assist performing common
> hypervisor activities such as a launching, running, snapshooting, migration
> and debugging a guests data.
> 
> 
> The following links provide additional details:
> 
> AMD Memory Encryption whitepaper:
>  
> http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
> 
> AMD64 Architecture Programmer's Manual:
>     http://support.amd.com/TechDocs/24593.pdf
>     SME is section 7.10
>     SEV is section 15.34
> 
> Secure Encrypted Virutualization Key Management:
> http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf
> 
> KVM Forum slides:
> http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
> 
> KVM RFC link:
> 
> [1] http://marc.info/?l=kvm&m=147191038624432&w=2
> 
> ---
> 
> TODO:
> - send seabios RFC's on seabios mailing list
> - implement SEV guest migration command support
> - implement SEV snapshotting command support
> - virtio support in SEV guest
> 
> Brijesh Singh (22):
>       exec: add guest RAM read/write ops
>       cpu-common: add debug version of physical memory read/write
>       monitor: use debug version of physical memory read api
>       memattrs: add SEV debug attrs
>       i386: add new option to enable SEV guest
>       sev: add initial SEV support
>       sev: add SEV launch start command
>       sev: add SEV launch update command
>       sev: add SEV launch finish command
>       sev: add SEV debug decrypt command
>       sev: add SEV debug encrypt command
>       sev: add SEV guest status command
>       hmp: update 'info kvm' to display SEV status
>       sev: provide SEV-enabled guest RAM read/write ops
>       i386: sev: register RAM read/write ops for BIOS and PC.RAM region
>       i386: pc: load OS images at fixed location in SEV-enabled guest
>       target-i386: add cpuid Fn8000_001f
>       i386: clear C-bit in SEV guest page table walk
>       exec: set debug attribute in SEV-enabled guest
>       fw_cfg: sev: disable dma in real mode
>       hw: add pre and post system reset callback
>       loader: reload bios image on ROM reset in SEV-enabled guest
> 
> 
>  Makefile.target           |    2 
>  disas.c                   |    2 
>  exec.c                    |  323 ++++++++++++++++++++-----
>  hmp.c                     |   14 +
>  hw/core/loader.c          |    7 -
>  hw/i386/pc.c              |   99 ++++++++
>  hw/i386/pc_sysfw.c        |    6 
>  hw/nvram/fw_cfg.c         |    6 
>  include/exec/cpu-common.h |   12 +
>  include/exec/memattrs.h   |    4 
>  include/exec/memory.h     |   25 ++
>  include/hw/hw.h           |    2 
>  include/sysemu/kvm.h      |   10 +
>  include/sysemu/sev.h      |  104 ++++++++
>  kvm-all.c                 |    6 
>  monitor.c                 |    2 
>  qapi-schema.json          |    4 
>  qemu-options.hx           |    6 
>  qmp.c                     |    1 
>  sev.c                     |  574 +++++++++++++++++++++++++++++++++++++++++++++
>  target-i386/cpu.c         |    3 
>  target-i386/helper.c      |   36 ++-
>  target-i386/monitor.c     |   50 +++-
>  vl.c                      |   74 ++++++
>  24 files changed, 1288 insertions(+), 84 deletions(-)
>  create mode 100644 include/sysemu/sev.h
>  create mode 100644 sev.c
> 
> -- 
> 
> Brijesh Singh

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 22:00       ` Eduardo Habkost
@ 2016-09-14  8:30         ` Daniel P. Berrange
  2016-09-14 11:54           ` Eduardo Habkost
  2016-09-14 16:10         ` Brijesh Singh
  1 sibling, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14  8:30 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Brijesh Singh, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 07:00:44PM -0300, Eduardo Habkost wrote:
> (CCing Daniel Berrange in case he has feedback on the
> nonce/dh_pub_qx/dh_pub_qy loading/parsing at the end of this
> message)
> 
> On Tue, Sep 13, 2016 at 02:54:40PM -0500, Brijesh Singh wrote:
> > Hi Eduardo,
> > 
> > On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
> > > > 
> > > > A typical SEV config file looks like this:
> > > > 
> > > 
> > > Are those config options documented somewhere?
> > > 
> > 
> > Various commands and parameters are documented [1]
> > 
> > [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> 
> If I understand correctly, the docs describe the firmware
> interface. The interface provided by QEMU is not the same thing,
> and needs to be documented as well (even if it contains pointers
> to sections or tables in the firmware interface docs).
> 
> Some of the questions I have about the fields are:
> * Do we really need the user to provide all the options below?
>   * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
>     for example?
> * Is bit 0 (KS) the only bit that can be set on flags? If so, why
>   not a boolean "ks" option?
> * Is "policy" the guest policy structure described at page 23? If
>   so, why exposing the raw value instead of separate fields for
>   each bit/field in the structure? (and only for the ones that
>   are supposed to be set by the user)
> * If vcpu_mask is a bitmap for each VCPU, should we represent it
>   as a list of VCPU indexes?
> 
> A good way to model this data and document it more properly is
> through a QAPI schema. grep for "opts_visitor_new()" in the code
> for examples where QEMU options are parsed according to a QAPI
> schema. The downside is that using a QAPI visitor is (AFAIK) not
> possible if using -object like I suggest below.

It needs to use QOM really, not QAPI, since it has to be user
creatable on the CLI and we don't want to invent new command
line arguments.

> > > > +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
> > > 
> > > Function name confused me (it seemed to read only one u8 value).
> > > 
> > I will fix the name, the function converts string into a hex bytes array.
> > e.g "12aabbccdd" is converted to val[] = {0x12,0xaa,0xbb,0xcc, 0xdd}.
> > 
> > > > +{
> > > > +    int i;
> > > > +    const char *v;
> > > > +
> > > > +    v = qemu_opt_get(opts, key);
> > > > +    if (!v) {
> > > > +        return 0;
> > > > +    }
> > > > +
> > > > +    DPRINTF(" %s = ", key);
> > > > +    i = 0;
> > > > +    while (*v) {
> > > > +        sscanf(v, "%2hhx", &val[i]);
> > > 
> > > Function doesn't check for array length.
> > Thanks, i will fix this.
> > > 
> > > > +        DPRINTF("%02hhx", val[i]);
> > > > +        v += 2;
> > > > +        i++;
> > > > +    }
> > > > +    DPRINTF("\n");
> > > > +
> > > > +    return i;
> > > 
> > > Do we really need to write our own parser? I wonder if we can
> > > reuse crypto/secret.c for loading the keys.
> > > 
> > I just looked at crypto/secret.c for loading the keys but not sure if will
> > able to reuse the secret_load routines, this is mainly because the SEV
> > inputs parameters are different compare to what we have in crypto/secrets.c.
> > I will still look more closely and see if we can find some common code.
> 
> There are other parameters, sure, but maybe it would be
> appropriate to just load nonce/dh_pub_qx/dh_pub_qy as
> TTYPE_QCRYPTO_SECRET object(s) (-object secret,...)? I am not
> sure because I don't understand the crypto part fully.

The secrets object is used for information that has to be kept
private from eavesdroppers. Based on the param names here
'dh_pub_qx' it sounds like this is non-sensitive "public"
data, so would not need to use the secrets object, but it
is hard to say for sure without close look at the technical
details.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support Brijesh Singh
  2016-09-13 15:58   ` Eduardo Habkost
@ 2016-09-14  8:37   ` Daniel P. Berrange
  1 sibling, 0 replies; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14  8:37 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, mst, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Tue, Sep 13, 2016 at 10:47:47AM -0400, Brijesh Singh wrote:
> This patch adds the initial support required to integrate Secure
> Encrypted Virtualization feature, the patch include the following
> changes:
> 
> - adds sev.c and sev.h files: the file will contain SEV APIs implemention.
> - add kvm_sev_enabled(): similar to kvm_enabled() this function can be
>   used to check if sev is enabled on this guest.
> - implement functions to parse SEV specific configuration file.
> 
> A typical SEV config file looks like this:
> 
> [sev-launch]
> 	flags = "00000000"
> 	policy	= "000000"
> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> 	nonce = "0123456789abcdef"
> 	vcpu_count = "1"
> 	vcpu_length = "30"
> 	vcpu_mask = "00ab"

We do not want to be inventing new config options for this - we should
be using QOM via -object to create this.



> diff --git a/sev.c b/sev.c
> new file mode 100644
> index 0000000..2d71ca6
> --- /dev/null
> +++ b/sev.c
> @@ -0,0 +1,282 @@
> +/*
> + * QEMU SEV support
> + *
> + * Copyright Advanced Micro Devices 2016
> + *
> + * Author:
> + *      Brijesh Singh <brijesh.singh@amd.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +
> +#include <linux/kvm.h>
> +
> +#include "qemu-common.h"
> +#include "qemu/atomic.h"
> +#include "qemu/option.h"
> +#include "qemu/config-file.h"
> +#include "qemu/error-report.h"
> +#include "hw/hw.h"
> +#include "hw/pci/msi.h"
> +#include "hw/s390x/adapter.h"
> +#include "exec/gdbstub.h"
> +#include "sysemu/kvm_int.h"
> +#include "sysemu/sev.h"
> +#include "qemu/bswap.h"
> +#include "exec/memory.h"
> +#include "exec/ram_addr.h"
> +#include "exec/address-spaces.h"
> +#include "qemu/event_notifier.h"
> +#include "trace.h"
> +#include "hw/irq.h"
> +
> +//#define DEBUG_SEV
> +
> +#ifdef DEBUG_SEV
> +#define DPRINTF(fmt, ...) \
> +    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
> +#else
> +#define DPRINTF(fmt, ...) \
> +    do { } while (0)
> +#endif
> +
> +struct SEVInfo {
> +    uint8_t state;  /* guest current state */
> +    uint8_t type;   /* guest type (encrypted, unencrypted) */
> +    struct kvm_sev_launch_start *launch_start;
> +    struct kvm_sev_launch_update *launch_update;
> +    struct kvm_sev_launch_finish *launch_finish;
> +};
> +
> +typedef struct SEVInfo SEVInfo;
> +static SEVInfo *sev_info;
> +static const char *cfg_file;
> +
> +enum {
> +    LAUNCH_OPTS = 0,
> +};
> +
> +enum {
> +    PRE_ENCRYPTED_GUEST = 0,
> +    UNENCRYPTED_GUEST,
> +};
> +
> +static QemuOptsList launch_opts = {
> +    .name = "sev-launch",
> +    .head = QTAILQ_HEAD_INITIALIZER(launch_opts.head),
> +    .desc = {
> +        {
> +            .name = "flags",
> +            .type = QEMU_OPT_NUMBER,
> +        },
> +        {
> +            .name = "policy",
> +            .type = QEMU_OPT_NUMBER,
> +        },
> +        {
> +            .name = "dh_pub_qx",
> +            .type = QEMU_OPT_STRING,
> +        },
> +        {
> +            .name = "dh_pub_qy",
> +            .type = QEMU_OPT_STRING,
> +        },
> +        {
> +            .name = "nonce",
> +            .type = QEMU_OPT_STRING,
> +        },
> +        {
> +            .name = "vcpu_length",
> +            .type = QEMU_OPT_NUMBER,
> +        },
> +        {
> +            .name = "vcpu_count",
> +            .type = QEMU_OPT_NUMBER,
> +        },
> +        {
> +            .name = "vcpu_mask",
> +            .type = QEMU_OPT_STRING,
> +        },
> +        { /* end of list */ }
> +    },
> +};



> +
> +static QemuOptsList *config_groups[] = {
> +    &launch_opts,
> +    NULL
> +};
> +
> +struct add_rule_data {
> +    SEVInfo *s;
> +    int action;
> +};
> +
> +static unsigned int read_config_u32(QemuOpts *opts, const char *key)
> +{
> +    unsigned int val;
> +
> +    val = qemu_opt_get_number_del(opts, key, -1);
> +    DPRINTF(" %s = %08x\n", key, val);
> +
> +    return val;
> +}
> +
> +static int read_config_u8(QemuOpts *opts, const char *key, uint8_t *val)
> +{
> +    int i;
> +    const char *v;
> +
> +    v = qemu_opt_get(opts, key);
> +    if (!v) {
> +        return 0;
> +    }
> +
> +    DPRINTF(" %s = ", key);
> +    i = 0;
> +    while (*v) {
> +        sscanf(v, "%2hhx", &val[i]);
> +        DPRINTF("%02hhx", val[i]);
> +        v += 2;
> +        i++;
> +    }
> +    DPRINTF("\n");
> +
> +    return i;
> +}
> +
> +static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
> +{
> +    struct add_rule_data *d = opaque;
> +
> +    switch (d->action) {
> +        case LAUNCH_OPTS: {
> +            struct kvm_sev_launch_start *start;
> +            struct kvm_sev_launch_update *update;
> +            struct kvm_sev_launch_finish *finish;
> +
> +            /* LAUNCH_START parameters */
> +            start = g_malloc0(sizeof(*start));
> +
> +            DPRINTF("Parsing 'sev-launch' parameters\n");
> +            start->flags = read_config_u32(opts, "flags");
> +            start->policy = read_config_u32(opts, "policy");
> +            read_config_u8(opts, "nonce", start->nonce);
> +            read_config_u8(opts, "dh_pub_qx", start->dh_pub_qx);
> +            read_config_u8(opts, "dh_pub_qy", start->dh_pub_qy);
> +            sev_info->launch_start = start;
> +
> +            /* LAUNCH_UPDATE */
> +            update = g_malloc0(sizeof(*update));
> +            sev_info->launch_update = update;
> +
> +            /* LAUNCH_FINISH parameters */
> +            finish = g_malloc0(sizeof(*finish));
> +
> +            finish->vcpu_count = read_config_u32(opts, "vcpu_count");
> +            finish->vcpu_length = read_config_u32(opts, "vcpu_length");
> +            if (qemu_opt_get(opts, "vcpu_mask")) {
> +                finish->vcpu_mask_length =
> +                                    strlen(qemu_opt_get(opts, "vcpu_mask")) / 2;
> +                finish->vcpu_mask_addr = (unsigned long)
> +                                        g_malloc0(finish->vcpu_length);
> +                read_config_u8(opts, "vcpu_mask",
> +                        (uint8_t *)finish->vcpu_mask_addr);
> +            }
> +
> +            sev_info->launch_finish = finish;
> +
> +            break;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static int parse_add_rules(QemuOptsList *list, struct add_rule_data *d)
> +{
> +    Error *local_err = NULL;
> +
> +    qemu_opts_foreach(list, add_rule, d, &local_err);
> +    if (local_err) {
> +        return 1;
> +    }
> +
> +    return 0;
> +}
> +
> +static int parse_sev_cfg(SEVInfo *s, int type, const char *filename)
> +{
> +    FILE *f;
> +    int ret = 0;
> +    struct add_rule_data d;
> +
> +    if (filename) {
> +        f = fopen(filename, "r");
> +        if (f == NULL) {
> +            return 1;
> +        }
> +
> +        ret = qemu_config_parse(f, config_groups, filename);
> +        if (ret < 0) {
> +            fprintf(stderr, "SEV: could not parse config file\n");
> +            exit(EXIT_FAILURE);
> +        }
> +    }
> +
> +    switch (type) {
> +    case LAUNCH_OPTS:
> +        d.s = s;
> +        d.action = type;
> +        ret = parse_add_rules(&launch_opts, &d);
> +        break;
> +    }
> +
> +    return ret;
> +
> +}
> +
> +int sev_init(KVMState *kvm_state)
> +{
> +    QemuOpts *opts;
> +    const char *type;
> +
> +    opts = qemu_find_opts_singleton("sev");
> +    cfg_file = qemu_opt_get(opts, "config");
> +    if (!cfg_file) {
> +        return 1;
> +    }
> +
> +    type = qemu_opt_get(opts, "type");
> +    if (!type) {
> +        return 1;
> +    }
> +
> +    sev_info = calloc(1, sizeof(*sev_info));
> +    if (!sev_info) {
> +        return 1;
> +    }

Use 'g_new0' for allocation and dont check the return
value since g_new0 aborts on oom.

> +
> +    if (!strcmp(type, "unencrypted")) {
> +        sev_info->type = UNENCRYPTED_GUEST;
> +    } else if (!strcmp(type, "encrypted")) {
> +        sev_info->type = PRE_ENCRYPTED_GUEST;

You should define an enum in qapi-schema.json for these
values, and use an enum property for 'type' in the QOM
object you then create. This automatically then handles
the string <-> int conversion

> +    } else {
> +        fprintf(stderr, "SEV: unsupported type '%s'\n", type);
> +        goto err;
> +    }
> +
> +    /* call SEV launch start APIs based on guest type */
> +
> +    return 0;
> +err:
> +    free(sev_info);
> +    sev_info = NULL;
> +    return 1;
> +}

All the command line argument handling in this file should be removed.
Instead you should define a user creatable object type to represent
the properties you need to have configured. If you want a simple
example of how to define a QOM object type, take a look at the code
in crypto/secret.c


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest
  2016-09-13 22:41   ` Paolo Bonzini
@ 2016-09-14  8:41     ` Daniel P. Berrange
  2016-09-14  9:11       ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14  8:41 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 12:41:59AM +0200, Paolo Bonzini wrote:
> 
> 
> On 13/09/2016 16:47, Brijesh Singh wrote:
> > The patch adds '-sev' option to enable the Secure Encrypted
> > Virtualization (SEV) guest. If this option is specified, Qemu
> > assumes that user wants to launch this guest into SEV mode.
> > 
> > Here are example on how to launch a guest into SEV mode.
> > 
> > 1) late launch: in this mode the images received from guest
> > owner are unencrypted and must be encrypted using SEV LAUNCH command
> > before starting the guest.
> > 
> > $ qemu -sev type=unencrypted config=guest_01.conf
> > 
> > 2) pre-encrypted: in this mode the images received from guest
> > owners are encrypted using transport keys. It must be re-encrypted
> > using SEV RECEIVE commands before starting the guest.
> > 
> > $ qemu -sev type=encrypted config=guest_02.conf
> > 
> > The config file will contains various parameters (e.g key , policy)
> > required during guest launch process.
> 
> Any reason not to pass the sev options themselves through -sev?  You can
> then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains
> 
> 	[sev]
> 	type="encrypted"
> 	flags = "00000000"
> 	policy	= "000000"
> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
> 	nonce = "0123456789abcdef"
> 	vcpu_count = "1"
> 	vcpu_length = "30"
> 	vcpu_mask = "00ab"

Agreed, it is really preferrable to define all the options via
one command line arg (using -object) and not re-invent external
config files when QEMU already has generic config file support


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14  2:28   ` Michael S. Tsirkin
@ 2016-09-14  8:57     ` Paolo Bonzini
  2016-09-14 13:05       ` Michael S. Tsirkin
  2016-09-14 13:36     ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
  1 sibling, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14  8:57 UTC (permalink / raw)
  To: Michael S. Tsirkin, Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, p.fedin, qemu-devel, armbru,
	lcapitulino, rth



On 14/09/2016 04:28, Michael S. Tsirkin wrote:
> On Tue, Sep 13, 2016 at 10:48:27AM -0400, Brijesh Singh wrote:
>> The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
>> for the debugging purposes. Note that debugging is permitting only
>> when guest policy allows it.
> 
> When wouldn't you want to allow it?
> I don't see value in a "break debugging" feature.

One man's "allow debugging" feature is another man's "break encryption"
feature. :)

Paolo

> 
>> For more information see [1], section 7.1
>>
>> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> 
> Please add comments documenting APIs. Spec links to figure out
> implementation is one thing, but you really can't require people
> to read specs just to figure out how to use an API.
> 
>> The following KVM RFC patches defines and implements this command
>>
>> http://marc.info/?l=kvm&m=147190852423972&w=2
>> http://marc.info/?l=kvm&m=147191068524579&w=2
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  include/sysemu/sev.h |   10 ++++++++++
>>  sev.c                |   23 +++++++++++++++++++++++
>>  2 files changed, 33 insertions(+)
>>
>> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
>> index ab03c5d..5872c3e 100644
>> --- a/include/sysemu/sev.h
>> +++ b/include/sysemu/sev.h
>> @@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
>>   */
>>  int kvm_sev_guest_measurement(uint8_t *measurement);
>>  
>> +/**
>> + * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
>> + * @src - guest memory address
>> + * @dest - host memory address where the decrypted data should be copied
>> + * @length - length of memory region
>> + *
>> + * Returns: 0 on success and dest will contains the decrypted data
>> + */
>> +int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
>> +
>>  #endif
>> diff --git a/sev.c b/sev.c
>> index 055ed83..c7031d3 100644
>> --- a/sev.c
>> +++ b/sev.c
>> @@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
>>  
>>      return 0;
>>  }
>> +
>> +int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
>> +{
>> +    int ret;
>> +    struct kvm_sev_dbg_decrypt decrypt;
>> +    struct kvm_sev_issue_cmd input;
>> +
>> +    decrypt.src_addr = (unsigned long)src;
>> +    decrypt.dst_addr = (unsigned long)dst;
>> +    decrypt.length = len;
>> +
>> +    input.cmd = KVM_SEV_DBG_DECRYPT;
>> +    input.opaque = (unsigned long)&decrypt;
>> +    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
>> +    if (ret) {
>> +        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
>> +                ret, input.ret_code);
>> +        return 1;
>> +    }
>> +
>> +    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
>> +    return 0;
>> +}
> 
> 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14  2:33     ` Michael S. Tsirkin
@ 2016-09-14  8:58       ` Paolo Bonzini
  2016-09-21 18:00         ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Message-ID: <20160921205731-mutt-send-email-mst@kernel.org> Michael S. Tsirkin
  2016-09-14 12:09       ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Eduardo Habkost
  1 sibling, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14  8:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, p.fedin, qemu-devel,
	armbru, lcapitulino, rth



On 14/09/2016 04:33, Michael S. Tsirkin wrote:
> Frankly I don't understand why do you need to mess with boot at all.
> Quoting the cover letter:
> 
> 	SEV is designed to protect guest VMs from a benign but vulnerable
> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> 	attack
> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> 
> it seems highly unlikely that any secret data is used during boot.
> So just let guest boot normally, and encrypt afterwards.
> 
> Even assuming there are some guests that have secret data during boot,
> I would first upstream the main part of the feature for normal guests,
> then weight the extra security if any against the features and
> performance lost (like slower boot times).

If you can't trust boot, any encryption done afterwards is totally
pointless.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest
  2016-09-14  8:41     ` Daniel P. Berrange
@ 2016-09-14  9:11       ` Paolo Bonzini
  0 siblings, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14  9:11 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Brijesh Singh, ehabkost, mst, crosthwaite.peter, p.fedin, armbru,
	qemu-devel, lcapitulino, rth



On 14/09/2016 10:41, Daniel P. Berrange wrote:
>> > Any reason not to pass the sev options themselves through -sev?  You can
>> > then use "-readconfig sev-guest.cfg" where sev-guest.cfg contains
>> > 
>> > 	[sev]
>> > 	type="encrypted"
>> > 	flags = "00000000"
>> > 	policy	= "000000"
>> > 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
>> > 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
>> > 	nonce = "0123456789abcdef"
>> > 	vcpu_count = "1"
>> > 	vcpu_length = "30"
>> > 	vcpu_mask = "00ab"
> Agreed, it is really preferrable to define all the options via
> one command line arg (using -object) and not re-invent external
> config files when QEMU already has generic config file support

To be fair, they _were_ reusing QEMU's config file support.  I was
ambivalent regarding using -object vs. creating a new command line,
since this is a singleton object, but indeed it's nicer if the policy is
split to its own object.

The object would be defined like this:

     [object "mypolicy"]
     qom-type = "sev-policy-encrypted"
     dh_pub_qx = "..."
     dh_pub_qy = "..."
     nonce = "..."
     ...

and then you also need to add a property to the MachineState.  The
property is accessed with -machine, and it creates a link to the policy
object---which also enables sev.  In the end you'd have this on the
command line:

    -readconfig mypolicy.cfg -machine sev-policy=mypolicy

Thanks,

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14  8:30         ` Daniel P. Berrange
@ 2016-09-14 11:54           ` Eduardo Habkost
  2016-09-14 11:58             ` Daniel P. Berrange
  0 siblings, 1 reply; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 11:54 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Brijesh Singh, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On Wed, Sep 14, 2016 at 09:30:51AM +0100, Daniel P. Berrange wrote:
> On Tue, Sep 13, 2016 at 07:00:44PM -0300, Eduardo Habkost wrote:
> > (CCing Daniel Berrange in case he has feedback on the
> > nonce/dh_pub_qx/dh_pub_qy loading/parsing at the end of this
> > message)
> > 
> > On Tue, Sep 13, 2016 at 02:54:40PM -0500, Brijesh Singh wrote:
> > > Hi Eduardo,
> > > 
> > > On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
> > > > > 
> > > > > A typical SEV config file looks like this:
> > > > > 
> > > > 
> > > > Are those config options documented somewhere?
> > > > 
> > > 
> > > Various commands and parameters are documented [1]
> > > 
> > > [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> > 
> > If I understand correctly, the docs describe the firmware
> > interface. The interface provided by QEMU is not the same thing,
> > and needs to be documented as well (even if it contains pointers
> > to sections or tables in the firmware interface docs).
> > 
> > Some of the questions I have about the fields are:
> > * Do we really need the user to provide all the options below?
> >   * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
> >     for example?
> > * Is bit 0 (KS) the only bit that can be set on flags? If so, why
> >   not a boolean "ks" option?
> > * Is "policy" the guest policy structure described at page 23? If
> >   so, why exposing the raw value instead of separate fields for
> >   each bit/field in the structure? (and only for the ones that
> >   are supposed to be set by the user)
> > * If vcpu_mask is a bitmap for each VCPU, should we represent it
> >   as a list of VCPU indexes?
> > 
> > A good way to model this data and document it more properly is
> > through a QAPI schema. grep for "opts_visitor_new()" in the code
> > for examples where QEMU options are parsed according to a QAPI
> > schema. The downside is that using a QAPI visitor is (AFAIK) not
> > possible if using -object like I suggest below.
> 
> It needs to use QOM really, not QAPI, since it has to be user
> creatable on the CLI and we don't want to invent new command
> line arguments.

As much as I don't like not being able to use the QAPI schema to
document -object, this is true.

[...]
> > > > 
> > > > Do we really need to write our own parser? I wonder if we can
> > > > reuse crypto/secret.c for loading the keys.
> > > > 
> > > I just looked at crypto/secret.c for loading the keys but not sure if will
> > > able to reuse the secret_load routines, this is mainly because the SEV
> > > inputs parameters are different compare to what we have in crypto/secrets.c.
> > > I will still look more closely and see if we can find some common code.
> > 
> > There are other parameters, sure, but maybe it would be
> > appropriate to just load nonce/dh_pub_qx/dh_pub_qy as
> > TTYPE_QCRYPTO_SECRET object(s) (-object secret,...)? I am not
> > sure because I don't understand the crypto part fully.
> 
> The secrets object is used for information that has to be kept
> private from eavesdroppers. Based on the param names here
> 'dh_pub_qx' it sounds like this is non-sensitive "public"
> data, so would not need to use the secrets object, but it
> is hard to say for sure without close look at the technical
> details.

They are a public key and nonce for ECDH key agreement, so they
are public (AFAICS).

So let's forget about "-object secret". I just want to ensure we
either reuse existing parsing code, or put the new parser in
common code that can be reused.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14 11:54           ` Eduardo Habkost
@ 2016-09-14 11:58             ` Daniel P. Berrange
  0 siblings, 0 replies; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 11:58 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Brijesh Singh, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On Wed, Sep 14, 2016 at 08:54:12AM -0300, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 09:30:51AM +0100, Daniel P. Berrange wrote:
> > On Tue, Sep 13, 2016 at 07:00:44PM -0300, Eduardo Habkost wrote:
> > > (CCing Daniel Berrange in case he has feedback on the
> > > nonce/dh_pub_qx/dh_pub_qy loading/parsing at the end of this
> > > message)
> > > 
> > > On Tue, Sep 13, 2016 at 02:54:40PM -0500, Brijesh Singh wrote:
> > > > Hi Eduardo,
> > > > 
> > > > On 09/13/2016 10:58 AM, Eduardo Habkost wrote:
> > > > > > 
> > > > > > A typical SEV config file looks like this:
> > > > > > 
> > > > > 
> > > > > Are those config options documented somewhere?
> > > > > 
> > > > 
> > > > Various commands and parameters are documented [1]
> > > > 
> > > > [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> > > 
> > > If I understand correctly, the docs describe the firmware
> > > interface. The interface provided by QEMU is not the same thing,
> > > and needs to be documented as well (even if it contains pointers
> > > to sections or tables in the firmware interface docs).
> > > 
> > > Some of the questions I have about the fields are:
> > > * Do we really need the user to provide all the options below?
> > >   * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
> > >     for example?
> > > * Is bit 0 (KS) the only bit that can be set on flags? If so, why
> > >   not a boolean "ks" option?
> > > * Is "policy" the guest policy structure described at page 23? If
> > >   so, why exposing the raw value instead of separate fields for
> > >   each bit/field in the structure? (and only for the ones that
> > >   are supposed to be set by the user)
> > > * If vcpu_mask is a bitmap for each VCPU, should we represent it
> > >   as a list of VCPU indexes?
> > > 
> > > A good way to model this data and document it more properly is
> > > through a QAPI schema. grep for "opts_visitor_new()" in the code
> > > for examples where QEMU options are parsed according to a QAPI
> > > schema. The downside is that using a QAPI visitor is (AFAIK) not
> > > possible if using -object like I suggest below.
> > 
> > It needs to use QOM really, not QAPI, since it has to be user
> > creatable on the CLI and we don't want to invent new command
> > line arguments.
> 
> As much as I don't like not being able to use the QAPI schema to
> document -object, this is true.

FWIW, in the medium-long term there is clear scope for
adding a 'object' type to the QAPI schema, that could be
used to generate the boilerplate code for QOM, so we can
reconcile these eventually.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14  2:33     ` Michael S. Tsirkin
  2016-09-14  8:58       ` Paolo Bonzini
@ 2016-09-14 12:09       ` Eduardo Habkost
  2016-09-14 13:01         ` Paolo Bonzini
  2016-09-21 18:03         ` Michael S. Tsirkin
  1 sibling, 2 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 12:09 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> > 
> > 
> > On 13/09/2016 16:50, Brijesh Singh wrote:
> > > In SEV-enabled guest dma should be performed on shared pages. Since
> > > the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > > to create a shared page hence disable the dma operation when reading
> > > from fw_cfg interface.
> > > 
> > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > > ---
> > >  hw/nvram/fw_cfg.c |    6 ++++++
> > >  1 file changed, 6 insertions(+)
> > > 
> > > diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > > index 6a68e59..aca99e9 100644
> > > --- a/hw/nvram/fw_cfg.c
> > > +++ b/hw/nvram/fw_cfg.c
> > > @@ -24,6 +24,7 @@
> > >  #include "qemu/osdep.h"
> > >  #include "hw/hw.h"
> > >  #include "sysemu/sysemu.h"
> > > +#include "sysemu/kvm.h"
> > >  #include "sysemu/dma.h"
> > >  #include "hw/boards.h"
> > >  #include "hw/isa/isa.h"
> > > @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> > >      FWCfgIoState *s = FW_CFG_IO(dev);
> > >      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > >  
> > > +    /* disable dma on fw_cfg when SEV is enabled */
> > > +    if (kvm_sev_enabled()) {
> > > +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > > +    }
> > > +
> > >      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> > >       * with half of the 16-bit control register. Hence, the total size
> > >       * of the i/o region used is FW_CFG_CTL_SIZE */
> > > 
> > > 
> > > 
> > 
> > As Michael said, a workaround is possible using -global.  However, I
> > really think that SEV should be implemented in UEFI firmware.  Because
> > it runs in 64-bit mode, it would be able to run in paged mode and it
> > would not have to encrypt everything before the SEV launch command.
> > 
> > For example secure boot can be used to authenticate the kernel against
> > keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> > the firmware by the owner and used to boot from a LUKS-encrypted /boot
> > partition.
> > 
> > Paolo
> 
> Frankly I don't understand why do you need to mess with boot at all.
> Quoting the cover letter:
> 
> 	SEV is designed to protect guest VMs from a benign but vulnerable
> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> 	attack
> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> 
> it seems highly unlikely that any secret data is used during boot.
> So just let guest boot normally, and encrypt afterwards.

After boot seems too late for the attestation part (see Section
1.3.1: Launch in the spec), unless you can ensure the memory
contents will always be exactly what the guest owner expects
after every boot.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 12:09       ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Eduardo Habkost
@ 2016-09-14 13:01         ` Paolo Bonzini
  2016-09-14 13:14           ` Michael S. Tsirkin
  2016-09-21 18:03         ` Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 13:01 UTC (permalink / raw)
  To: Eduardo Habkost, Michael S. Tsirkin
  Cc: Brijesh Singh, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, rth



On 14/09/2016 14:09, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
>> On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
>>>
>>>
>>> On 13/09/2016 16:50, Brijesh Singh wrote:
>>>> In SEV-enabled guest dma should be performed on shared pages. Since
>>>> the SeaBIOS executes in non PAE mode and does not have access to C-bit
>>>> to create a shared page hence disable the dma operation when reading
>>>> from fw_cfg interface.
>>>>
>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>> ---
>>>>  hw/nvram/fw_cfg.c |    6 ++++++
>>>>  1 file changed, 6 insertions(+)
>>>>
>>>> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
>>>> index 6a68e59..aca99e9 100644
>>>> --- a/hw/nvram/fw_cfg.c
>>>> +++ b/hw/nvram/fw_cfg.c
>>>> @@ -24,6 +24,7 @@
>>>>  #include "qemu/osdep.h"
>>>>  #include "hw/hw.h"
>>>>  #include "sysemu/sysemu.h"
>>>> +#include "sysemu/kvm.h"
>>>>  #include "sysemu/dma.h"
>>>>  #include "hw/boards.h"
>>>>  #include "hw/isa/isa.h"
>>>> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
>>>>      FWCfgIoState *s = FW_CFG_IO(dev);
>>>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>>>  
>>>> +    /* disable dma on fw_cfg when SEV is enabled */
>>>> +    if (kvm_sev_enabled()) {
>>>> +        qdev_prop_set_bit(dev, "dma_enabled", false);
>>>> +    }
>>>> +
>>>>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
>>>>       * with half of the 16-bit control register. Hence, the total size
>>>>       * of the i/o region used is FW_CFG_CTL_SIZE */
>>>>
>>>>
>>>>
>>>
>>> As Michael said, a workaround is possible using -global.  However, I
>>> really think that SEV should be implemented in UEFI firmware.  Because
>>> it runs in 64-bit mode, it would be able to run in paged mode and it
>>> would not have to encrypt everything before the SEV launch command.
>>>
>>> For example secure boot can be used to authenticate the kernel against
>>> keys provided by the owner in encrypted flash, or GRUB2 can be placed in
>>> the firmware by the owner and used to boot from a LUKS-encrypted /boot
>>> partition.
>>>
>>> Paolo
>>
>> Frankly I don't understand why do you need to mess with boot at all.
>> Quoting the cover letter:
>>
>> 	SEV is designed to protect guest VMs from a benign but vulnerable
>> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
>> 	attack
>> 	surface of guest VMs and can prevent certain types of VM-escape bugs
>> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
>>
>> it seems highly unlikely that any secret data is used during boot.
>> So just let guest boot normally, and encrypt afterwards.
> 
> After boot seems too late for the attestation part (see Section
> 1.3.1: Launch in the spec), unless you can ensure the memory
> contents will always be exactly what the guest owner expects
> after every boot.

And the attestation is what lets the guest check that the memory
contents are indeed what the guest owner expects.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14  8:57     ` Paolo Bonzini
@ 2016-09-14 13:05       ` Michael S. Tsirkin
  2016-09-14 13:07         ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:05 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, p.fedin, qemu-devel,
	armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 10:57:34AM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 04:28, Michael S. Tsirkin wrote:
> > On Tue, Sep 13, 2016 at 10:48:27AM -0400, Brijesh Singh wrote:
> >> The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
> >> for the debugging purposes. Note that debugging is permitting only
> >> when guest policy allows it.
> > 
> > When wouldn't you want to allow it?
> > I don't see value in a "break debugging" feature.
> 
> One man's "allow debugging" feature is another man's "break encryption"
> feature. :)
> 
> Paolo

Does this break anything? If so this needs better documentation.
Again, don't assume users will read specs. If the flag is called
"allow debug" then it is reasonable to assume users will use
it exactly to allow debug.

I assumed that with debug on, memory is still encrypted but the
hypervisor can break encryption, and as the cover letter states, the
hypervisor is assumed benign. If true I don't see a need to
give users more rope.


> > 
> >> For more information see [1], section 7.1
> >>
> >> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> > 
> > Please add comments documenting APIs. Spec links to figure out
> > implementation is one thing, but you really can't require people
> > to read specs just to figure out how to use an API.
> > 
> >> The following KVM RFC patches defines and implements this command
> >>
> >> http://marc.info/?l=kvm&m=147190852423972&w=2
> >> http://marc.info/?l=kvm&m=147191068524579&w=2
> >>
> >> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> >> ---
> >>  include/sysemu/sev.h |   10 ++++++++++
> >>  sev.c                |   23 +++++++++++++++++++++++
> >>  2 files changed, 33 insertions(+)
> >>
> >> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> >> index ab03c5d..5872c3e 100644
> >> --- a/include/sysemu/sev.h
> >> +++ b/include/sysemu/sev.h
> >> @@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
> >>   */
> >>  int kvm_sev_guest_measurement(uint8_t *measurement);
> >>  
> >> +/**
> >> + * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
> >> + * @src - guest memory address
> >> + * @dest - host memory address where the decrypted data should be copied
> >> + * @length - length of memory region
> >> + *
> >> + * Returns: 0 on success and dest will contains the decrypted data
> >> + */
> >> +int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
> >> +
> >>  #endif
> >> diff --git a/sev.c b/sev.c
> >> index 055ed83..c7031d3 100644
> >> --- a/sev.c
> >> +++ b/sev.c
> >> @@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
> >>  
> >>      return 0;
> >>  }
> >> +
> >> +int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
> >> +{
> >> +    int ret;
> >> +    struct kvm_sev_dbg_decrypt decrypt;
> >> +    struct kvm_sev_issue_cmd input;
> >> +
> >> +    decrypt.src_addr = (unsigned long)src;
> >> +    decrypt.dst_addr = (unsigned long)dst;
> >> +    decrypt.length = len;
> >> +
> >> +    input.cmd = KVM_SEV_DBG_DECRYPT;
> >> +    input.opaque = (unsigned long)&decrypt;
> >> +    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
> >> +    if (ret) {
> >> +        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
> >> +                ret, input.ret_code);
> >> +        return 1;
> >> +    }
> >> +
> >> +    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
> >> +    return 0;
> >> +}
> > 
> > 

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:05       ` Michael S. Tsirkin
@ 2016-09-14 13:07         ` Paolo Bonzini
  2016-09-14 13:23           ` Daniel P. Berrange
  2016-09-14 13:27           ` [Qemu-devel] [PATCH v2] virtio_pci: Limit DMA mask to 44 bits for legacy virtio devices Michael S. Tsirkin
  0 siblings, 2 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 13:07 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, p.fedin, qemu-devel,
	armbru, lcapitulino, rth



On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> I assumed that with debug on, memory is still encrypted but the
> hypervisor can break encryption, and as the cover letter states, the
> hypervisor is assumed benign. If true I don't see a need to
> give users more rope.

The hypervisor is assumed benign but vulnerable.

So, if somebody breaks the hypervisor, you would like to make it as hard
as possible for the attacker to do evil stuff to the guests.  If the
attacker can just ask the secure processor "decrypt some memory for me",
then the encryption is effectively broken.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 13:01         ` Paolo Bonzini
@ 2016-09-14 13:14           ` Michael S. Tsirkin
  2016-09-14 13:51             ` Eduardo Habkost
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:14 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Eduardo Habkost, Brijesh Singh, crosthwaite.peter, armbru,
	p.fedin, qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 03:01:51PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 14:09, Eduardo Habkost wrote:
> > On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
> >> On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> >>>
> >>>
> >>> On 13/09/2016 16:50, Brijesh Singh wrote:
> >>>> In SEV-enabled guest dma should be performed on shared pages. Since
> >>>> the SeaBIOS executes in non PAE mode and does not have access to C-bit
> >>>> to create a shared page hence disable the dma operation when reading
> >>>> from fw_cfg interface.
> >>>>
> >>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> >>>> ---
> >>>>  hw/nvram/fw_cfg.c |    6 ++++++
> >>>>  1 file changed, 6 insertions(+)
> >>>>
> >>>> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> >>>> index 6a68e59..aca99e9 100644
> >>>> --- a/hw/nvram/fw_cfg.c
> >>>> +++ b/hw/nvram/fw_cfg.c
> >>>> @@ -24,6 +24,7 @@
> >>>>  #include "qemu/osdep.h"
> >>>>  #include "hw/hw.h"
> >>>>  #include "sysemu/sysemu.h"
> >>>> +#include "sysemu/kvm.h"
> >>>>  #include "sysemu/dma.h"
> >>>>  #include "hw/boards.h"
> >>>>  #include "hw/isa/isa.h"
> >>>> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> >>>>      FWCfgIoState *s = FW_CFG_IO(dev);
> >>>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> >>>>  
> >>>> +    /* disable dma on fw_cfg when SEV is enabled */
> >>>> +    if (kvm_sev_enabled()) {
> >>>> +        qdev_prop_set_bit(dev, "dma_enabled", false);
> >>>> +    }
> >>>> +
> >>>>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> >>>>       * with half of the 16-bit control register. Hence, the total size
> >>>>       * of the i/o region used is FW_CFG_CTL_SIZE */
> >>>>
> >>>>
> >>>>
> >>>
> >>> As Michael said, a workaround is possible using -global.  However, I
> >>> really think that SEV should be implemented in UEFI firmware.  Because
> >>> it runs in 64-bit mode, it would be able to run in paged mode and it
> >>> would not have to encrypt everything before the SEV launch command.
> >>>
> >>> For example secure boot can be used to authenticate the kernel against
> >>> keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> >>> the firmware by the owner and used to boot from a LUKS-encrypted /boot
> >>> partition.
> >>>
> >>> Paolo
> >>
> >> Frankly I don't understand why do you need to mess with boot at all.
> >> Quoting the cover letter:
> >>
> >> 	SEV is designed to protect guest VMs from a benign but vulnerable
> >> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> >> 	attack
> >> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> >> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> >>
> >> it seems highly unlikely that any secret data is used during boot.
> >> So just let guest boot normally, and encrypt afterwards.
> > 
> > After boot seems too late for the attestation part (see Section
> > 1.3.1: Launch in the spec), unless you can ensure the memory
> > contents will always be exactly what the guest owner expects
> > after every boot.
> 
> And the attestation is what lets the guest check that the memory
> contents are indeed what the guest owner expects.
> 
> Paolo

So the cover letter says hypervisor is benign, and then people turn
around and start discussing guest owner checking memory as if hypervisor
is malicious and might load something unexpected there.  Makes no sense
to me.

I suggest we just drop this attestation thing in v1. Try to merge
something minimal that actually works first.

You can always extend this to add more features later:
whether there's any value in guest checking its own memory
is something that would need a separate discussion at
a higher level. I'm not saying there isn't.
Let's do one thing at a time though.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:07         ` Paolo Bonzini
@ 2016-09-14 13:23           ` Daniel P. Berrange
  2016-09-14 13:32             ` Michael S. Tsirkin
  2016-09-14 13:27           ` [Qemu-devel] [PATCH v2] virtio_pci: Limit DMA mask to 44 bits for legacy virtio devices Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 13:23 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Michael S. Tsirkin, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > I assumed that with debug on, memory is still encrypted but the
> > hypervisor can break encryption, and as the cover letter states, the
> > hypervisor is assumed benign. If true I don't see a need to
> > give users more rope.
> 
> The hypervisor is assumed benign but vulnerable.
> 
> So, if somebody breaks the hypervisor, you would like to make it as hard
> as possible for the attacker to do evil stuff to the guests.  If the
> attacker can just ask the secure processor "decrypt some memory for me",
> then the encryption is effectively broken.

So there's going to be a tradeoff here between use of SEV and use of
certain other features. eg, it seems that if you're using SEV, then
any concept of creating & analysing guest core dumps from the host
is out.

It seems that SEV on its own is insufficient - there is at least some
interaction with storage. eg merely running a guest with SEV is not
going to guarantee security if the guest OS is able to swap out to a
non-encrypted disk. You could run LUKS inside the guest but that has
a number of downsides. How to provide the decryption key for LUKS
at startup without guest admin interaction. Then there is the issue
that if you take snapshots of the guest disk in the host, this is
weakening the security of LUKS, since you're keeping around copies
of the same logical guest sector with different contents which
allows for improve crytoanalysis. These are reasons for using LUKS
on the host instead of in the guest, but then the decryption kjeys
for LUKS are in the QEMU process in memory which is (IIUC) not going
to be protected by SEV ?  Unles there's a way for QEMU to do allocations
which are SEV protected for its own purposes ?

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [PATCH v2] virtio_pci: Limit DMA mask to 44 bits for legacy virtio devices
  2016-09-14 13:07         ` Paolo Bonzini
  2016-09-14 13:23           ` Daniel P. Berrange
@ 2016-09-14 13:27           ` Michael S. Tsirkin
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:27 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, p.fedin, qemu-devel,
	armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > I assumed that with debug on, memory is still encrypted but the
> > hypervisor can break encryption, and as the cover letter states, the
> > hypervisor is assumed benign. If true I don't see a need to
> > give users more rope.
> 
> The hypervisor is assumed benign but vulnerable.

Vulnerable to information leaks, yes.

> So, if somebody breaks the hypervisor, you would like to make it as hard
> as possible

We don't just do this at random. Need some proof it's actually
making things harder.



> for the attacker to do evil stuff to the guests.

Break as in make it do things?  This is a possible model,  but this is
not what the cover letter states.

As far as I can tell, encrypting memory does not protect against an
attacker that can execute code in the hypervisor, if only for the
reason that a lot of guest info is not in memory as CPU always accesses
memory through registers.


> If the
> attacker can just ask the secure processor "decrypt some memory for me",
> then the encryption is effectively broken.
> 
> Paolo

Not at all, if all you have is hypervisor read-anywhere access,
then that is not broken. This seems to be the threat model that
the patchset targets, again based on the cover letter.



-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:23           ` Daniel P. Berrange
@ 2016-09-14 13:32             ` Michael S. Tsirkin
  2016-09-14 13:37               ` Daniel P. Berrange
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:32 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > 
> > 
> > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > I assumed that with debug on, memory is still encrypted but the
> > > hypervisor can break encryption, and as the cover letter states, the
> > > hypervisor is assumed benign. If true I don't see a need to
> > > give users more rope.
> > 
> > The hypervisor is assumed benign but vulnerable.
> > 
> > So, if somebody breaks the hypervisor, you would like to make it as hard
> > as possible for the attacker to do evil stuff to the guests.  If the
> > attacker can just ask the secure processor "decrypt some memory for me",
> > then the encryption is effectively broken.
> 
> So there's going to be a tradeoff here between use of SEV and use of
> certain other features. eg, it seems that if you're using SEV, then
> any concept of creating & analysing guest core dumps from the host
> is out.

I don't see why - as long as we don't trigger dumps, there's no leak :)

> It seems that SEV on its own is insufficient - there is at least some
> interaction with storage. eg merely running a guest with SEV is not
> going to guarantee security if the guest OS is able to swap out to a
> non-encrypted disk. You could run LUKS inside the guest but that has
> a number of downsides. How to provide the decryption key for LUKS
> at startup without guest admin interaction. Then there is the issue
> that if you take snapshots of the guest disk in the host, this is
> weakening the security of LUKS, since you're keeping around copies
> of the same logical guest sector with different contents which
> allows for improve crytoanalysis. These are reasons for using LUKS
> on the host instead of in the guest, but then the decryption kjeys
> for LUKS are in the QEMU process in memory which is (IIUC) not going
> to be protected by SEV ?  Unles there's a way for QEMU to do allocations
> which are SEV protected for its own purposes ?
> 
> Regards,
> Daniel
> -- 
> |: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
> |: http://libvirt.org              -o-             http://virt-manager.org :|
> |: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
> |: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14  2:28   ` Michael S. Tsirkin
  2016-09-14  8:57     ` Paolo Bonzini
@ 2016-09-14 13:36     ` Brijesh Singh
  2016-09-14 13:48       ` Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 13:36 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: brijesh.singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On 09/13/2016 09:28 PM, Michael S. Tsirkin wrote:
> On Tue, Sep 13, 2016 at 10:48:27AM -0400, Brijesh Singh wrote:
>> The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
>> for the debugging purposes. Note that debugging is permitting only
>> when guest policy allows it.
>
> When wouldn't you want to allow it?
> I don't see value in a "break debugging" feature.
>
A guest owner needs to provide the launch parameters before we launch a 
SEV guest, a typical input parameters looks like this.

[sev-launch]
         flags = "0"
         policy  = "0"
         dh_pub_qx = "0123456789abcdef0123456789abcdef"
         dh_pub_qy = "0123456789abcdef0123456789abcdef"
         nonce = "0123456789abcdef"
         vcpu_count = "1"
         vcpu_length = "30"
         vcpu_mask = "00ab"

One of the bit in policy field is "debugging", if this bit is set then 
hypervisor can use SEV commands to decrypt a guest memory otherwise 
hypervisor read will always get encrypted data. Also note that policy 
field is used by firmware when computing the measurement of a guest 
launch so any changes in policy by hypervisor will result in wrong 
measurement.

>
>> For more information see [1], section 7.1
>>
>> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
>
> Please add comments documenting APIs. Spec links to figure out
> implementation is one thing, but you really can't require people
> to read specs just to figure out how to use an API.
>
Sure,  i will work towards creating a simple file in doc/ directory that 
will list of commands, usage and their parameters and provide the link 
to exact section.

>> The following KVM RFC patches defines and implements this command
>>
>> http://marc.info/?l=kvm&m=147190852423972&w=2
>> http://marc.info/?l=kvm&m=147191068524579&w=2
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  include/sysemu/sev.h |   10 ++++++++++
>>  sev.c                |   23 +++++++++++++++++++++++
>>  2 files changed, 33 insertions(+)
>>
>> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
>> index ab03c5d..5872c3e 100644
>> --- a/include/sysemu/sev.h
>> +++ b/include/sysemu/sev.h
>> @@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
>>   */
>>  int kvm_sev_guest_measurement(uint8_t *measurement);
>>
>> +/**
>> + * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
>> + * @src - guest memory address
>> + * @dest - host memory address where the decrypted data should be copied
>> + * @length - length of memory region
>> + *
>> + * Returns: 0 on success and dest will contains the decrypted data
>> + */
>> +int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
>> +
>>  #endif
>> diff --git a/sev.c b/sev.c
>> index 055ed83..c7031d3 100644
>> --- a/sev.c
>> +++ b/sev.c
>> @@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
>>
>>      return 0;
>>  }
>> +
>> +int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
>> +{
>> +    int ret;
>> +    struct kvm_sev_dbg_decrypt decrypt;
>> +    struct kvm_sev_issue_cmd input;
>> +
>> +    decrypt.src_addr = (unsigned long)src;
>> +    decrypt.dst_addr = (unsigned long)dst;
>> +    decrypt.length = len;
>> +
>> +    input.cmd = KVM_SEV_DBG_DECRYPT;
>> +    input.opaque = (unsigned long)&decrypt;
>> +    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
>> +    if (ret) {
>> +        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
>> +                ret, input.ret_code);
>> +        return 1;
>> +    }
>> +
>> +    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
>> +    return 0;
>> +}

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:32             ` Michael S. Tsirkin
@ 2016-09-14 13:37               ` Daniel P. Berrange
  2016-09-14 13:50                 ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 13:37 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > 
> > > 
> > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > I assumed that with debug on, memory is still encrypted but the
> > > > hypervisor can break encryption, and as the cover letter states, the
> > > > hypervisor is assumed benign. If true I don't see a need to
> > > > give users more rope.
> > > 
> > > The hypervisor is assumed benign but vulnerable.
> > > 
> > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > as possible for the attacker to do evil stuff to the guests.  If the
> > > attacker can just ask the secure processor "decrypt some memory for me",
> > > then the encryption is effectively broken.
> > 
> > So there's going to be a tradeoff here between use of SEV and use of
> > certain other features. eg, it seems that if you're using SEV, then
> > any concept of creating & analysing guest core dumps from the host
> > is out.
> 
> I don't see why - as long as we don't trigger dumps, there's no leak :)

If the facility to trigger dumps is available, then the memory
encryption feature of SEV is as useful as a chocolate teapot,
as the would be attacker can simply trigger a dump bypassing
any kind of SEV protection to get unencrypted memory. So if
SEV is to provide any kind of useful security protection, there
must be no way for a host admin to initiate core dumps of the
guest, without first having some kind of explicit guest admin
action to enable it.

> > It seems that SEV on its own is insufficient - there is at least some
> > interaction with storage. eg merely running a guest with SEV is not
> > going to guarantee security if the guest OS is able to swap out to a
> > non-encrypted disk. You could run LUKS inside the guest but that has
> > a number of downsides. How to provide the decryption key for LUKS
> > at startup without guest admin interaction. Then there is the issue
> > that if you take snapshots of the guest disk in the host, this is
> > weakening the security of LUKS, since you're keeping around copies
> > of the same logical guest sector with different contents which
> > allows for improve crytoanalysis. These are reasons for using LUKS
> > on the host instead of in the guest, but then the decryption kjeys
> > for LUKS are in the QEMU process in memory which is (IIUC) not going
> > to be protected by SEV ?  Unles there's a way for QEMU to do allocations
> > which are SEV protected for its own purposes ?

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:36     ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
@ 2016-09-14 13:48       ` Michael S. Tsirkin
  2016-09-14 14:19         ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:48 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth

On Wed, Sep 14, 2016 at 08:36:50AM -0500, Brijesh Singh wrote:
> On 09/13/2016 09:28 PM, Michael S. Tsirkin wrote:
> > On Tue, Sep 13, 2016 at 10:48:27AM -0400, Brijesh Singh wrote:
> > > The SEV DEBUG_DECRYPT command is used for decrypting a guest memory
> > > for the debugging purposes. Note that debugging is permitting only
> > > when guest policy allows it.
> > 
> > When wouldn't you want to allow it?
> > I don't see value in a "break debugging" feature.
> > 
> A guest owner needs to provide the launch parameters before we launch a SEV
> guest, a typical input parameters looks like this.
> 
> [sev-launch]
>         flags = "0"
>         policy  = "0"
>         dh_pub_qx = "0123456789abcdef0123456789abcdef"
>         dh_pub_qy = "0123456789abcdef0123456789abcdef"
>         nonce = "0123456789abcdef"
>         vcpu_count = "1"
>         vcpu_length = "30"
>         vcpu_mask = "00ab"
> 
> One of the bit in policy field is "debugging", if this bit is set then
> hypervisor can use SEV commands to decrypt a guest memory

That is my point. Arbitrary code execution in hypervisor means game over
anyway, at least with the hardware we have today.
If qemu gains a flag disabling a feature, it needs some documentation
that explains: disabling this will break ABC but protect against XYZ.
How do you expect people to use the feature otherwise?

My suggestion is to merge the support for encrypting memory first,
then make extras like disabling debugging on top.

> otherwise
> hypervisor read will always get encrypted data. Also note that policy field
> is used by firmware when computing the measurement of a guest launch so any
> changes in policy by hypervisor will result in wrong measurement.

I can't say I understand how does guest measuring help prevent
leaks in any way. Looks like a separate feature - why not split it
out?

> > 
> > > For more information see [1], section 7.1
> > > 
> > > [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> > 
> > Please add comments documenting APIs. Spec links to figure out
> > implementation is one thing, but you really can't require people
> > to read specs just to figure out how to use an API.
> > 
> Sure,  i will work towards creating a simple file in doc/ directory that
> will list of commands, usage and their parameters and provide the link to
> exact section.
> 
> > > The following KVM RFC patches defines and implements this command
> > > 
> > > http://marc.info/?l=kvm&m=147190852423972&w=2
> > > http://marc.info/?l=kvm&m=147191068524579&w=2
> > > 
> > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > > ---
> > >  include/sysemu/sev.h |   10 ++++++++++
> > >  sev.c                |   23 +++++++++++++++++++++++
> > >  2 files changed, 33 insertions(+)
> > > 
> > > diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> > > index ab03c5d..5872c3e 100644
> > > --- a/include/sysemu/sev.h
> > > +++ b/include/sysemu/sev.h
> > > @@ -55,4 +55,14 @@ int kvm_sev_guest_finish(void);
> > >   */
> > >  int kvm_sev_guest_measurement(uint8_t *measurement);
> > > 
> > > +/**
> > > + * kvm_sev_dbg_decrypt -  decrypt the guest memory for debugging purposes
> > > + * @src - guest memory address
> > > + * @dest - host memory address where the decrypted data should be copied
> > > + * @length - length of memory region
> > > + *
> > > + * Returns: 0 on success and dest will contains the decrypted data
> > > + */
> > > +int kvm_sev_dbg_decrypt(uint8_t *dest, const uint8_t *src, uint32_t len);
> > > +
> > >  #endif
> > > diff --git a/sev.c b/sev.c
> > > index 055ed83..c7031d3 100644
> > > --- a/sev.c
> > > +++ b/sev.c
> > > @@ -432,3 +432,26 @@ int kvm_sev_guest_measurement(uint8_t *out)
> > > 
> > >      return 0;
> > >  }
> > > +
> > > +int kvm_sev_dbg_decrypt(uint8_t *dst, const uint8_t *src, uint32_t len)
> > > +{
> > > +    int ret;
> > > +    struct kvm_sev_dbg_decrypt decrypt;
> > > +    struct kvm_sev_issue_cmd input;
> > > +
> > > +    decrypt.src_addr = (unsigned long)src;
> > > +    decrypt.dst_addr = (unsigned long)dst;
> > > +    decrypt.length = len;
> > > +
> > > +    input.cmd = KVM_SEV_DBG_DECRYPT;
> > > +    input.opaque = (unsigned long)&decrypt;
> > > +    ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
> > > +    if (ret) {
> > > +        fprintf(stderr, "SEV: dbg_decrypt failed ret=%d(%#010x)\n",
> > > +                ret, input.ret_code);
> > > +        return 1;
> > > +    }
> > > +
> > > +    DPRINTF("SEV: DBG_DECRYPT dst %p src %p sz %d\n", dst, src, len);
> > > +    return 0;
> > > +}

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:37               ` Daniel P. Berrange
@ 2016-09-14 13:50                 ` Michael S. Tsirkin
  2016-09-14 14:08                   ` Eduardo Habkost
  2016-09-14 14:15                   ` Daniel P. Berrange
  0 siblings, 2 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 13:50 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > 
> > > > 
> > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > give users more rope.
> > > > 
> > > > The hypervisor is assumed benign but vulnerable.
> > > > 
> > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > then the encryption is effectively broken.
> > > 
> > > So there's going to be a tradeoff here between use of SEV and use of
> > > certain other features. eg, it seems that if you're using SEV, then
> > > any concept of creating & analysing guest core dumps from the host
> > > is out.
> > 
> > I don't see why - as long as we don't trigger dumps, there's no leak :)
> 
> If the facility to trigger dumps is available, then the memory
> encryption feature of SEV is as useful as a chocolate teapot,
> as the would be attacker can simply trigger a dump

If attacker can trigger things, IOW execute code in hypervisor,
then encrypting memory is not useful anyway.

> bypassing
> any kind of SEV protection to get unencrypted memory. So if
> SEV is to provide any kind of useful security protection, there
> must be no way for a host admin to initiate core dumps of the
> guest, without first having some kind of explicit guest admin
> action to enable it.

As stated it protects against passive adversaries with read-only
access to hypervisor memory. I don't see how dump ability breaks that.


> > > It seems that SEV on its own is insufficient - there is at least some
> > > interaction with storage. eg merely running a guest with SEV is not
> > > going to guarantee security if the guest OS is able to swap out to a
> > > non-encrypted disk. You could run LUKS inside the guest but that has
> > > a number of downsides. How to provide the decryption key for LUKS
> > > at startup without guest admin interaction. Then there is the issue
> > > that if you take snapshots of the guest disk in the host, this is
> > > weakening the security of LUKS, since you're keeping around copies
> > > of the same logical guest sector with different contents which
> > > allows for improve crytoanalysis. These are reasons for using LUKS
> > > on the host instead of in the guest, but then the decryption kjeys
> > > for LUKS are in the QEMU process in memory which is (IIUC) not going
> > > to be protected by SEV ?  Unles there's a way for QEMU to do allocations
> > > which are SEV protected for its own purposes ?
> 
> Regards,
> Daniel
> -- 
> |: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
> |: http://libvirt.org              -o-             http://virt-manager.org :|
> |: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
> |: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 13:14           ` Michael S. Tsirkin
@ 2016-09-14 13:51             ` Eduardo Habkost
  2016-09-14 16:10               ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 13:51 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:14:58PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 03:01:51PM +0200, Paolo Bonzini wrote:
> > 
> > 
> > On 14/09/2016 14:09, Eduardo Habkost wrote:
> > > On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
> > >> On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> > >>>
> > >>>
> > >>> On 13/09/2016 16:50, Brijesh Singh wrote:
> > >>>> In SEV-enabled guest dma should be performed on shared pages. Since
> > >>>> the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > >>>> to create a shared page hence disable the dma operation when reading
> > >>>> from fw_cfg interface.
> > >>>>
> > >>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > >>>> ---
> > >>>>  hw/nvram/fw_cfg.c |    6 ++++++
> > >>>>  1 file changed, 6 insertions(+)
> > >>>>
> > >>>> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > >>>> index 6a68e59..aca99e9 100644
> > >>>> --- a/hw/nvram/fw_cfg.c
> > >>>> +++ b/hw/nvram/fw_cfg.c
> > >>>> @@ -24,6 +24,7 @@
> > >>>>  #include "qemu/osdep.h"
> > >>>>  #include "hw/hw.h"
> > >>>>  #include "sysemu/sysemu.h"
> > >>>> +#include "sysemu/kvm.h"
> > >>>>  #include "sysemu/dma.h"
> > >>>>  #include "hw/boards.h"
> > >>>>  #include "hw/isa/isa.h"
> > >>>> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> > >>>>      FWCfgIoState *s = FW_CFG_IO(dev);
> > >>>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > >>>>  
> > >>>> +    /* disable dma on fw_cfg when SEV is enabled */
> > >>>> +    if (kvm_sev_enabled()) {
> > >>>> +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > >>>> +    }
> > >>>> +
> > >>>>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> > >>>>       * with half of the 16-bit control register. Hence, the total size
> > >>>>       * of the i/o region used is FW_CFG_CTL_SIZE */
> > >>>>
> > >>>>
> > >>>>
> > >>>
> > >>> As Michael said, a workaround is possible using -global.  However, I
> > >>> really think that SEV should be implemented in UEFI firmware.  Because
> > >>> it runs in 64-bit mode, it would be able to run in paged mode and it
> > >>> would not have to encrypt everything before the SEV launch command.
> > >>>
> > >>> For example secure boot can be used to authenticate the kernel against
> > >>> keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> > >>> the firmware by the owner and used to boot from a LUKS-encrypted /boot
> > >>> partition.
> > >>>
> > >>> Paolo
> > >>
> > >> Frankly I don't understand why do you need to mess with boot at all.
> > >> Quoting the cover letter:
> > >>
> > >> 	SEV is designed to protect guest VMs from a benign but vulnerable
> > >> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> > >> 	attack
> > >> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> > >> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> > >>
> > >> it seems highly unlikely that any secret data is used during boot.
> > >> So just let guest boot normally, and encrypt afterwards.
> > > 
> > > After boot seems too late for the attestation part (see Section
> > > 1.3.1: Launch in the spec), unless you can ensure the memory
> > > contents will always be exactly what the guest owner expects
> > > after every boot.
> > 
> > And the attestation is what lets the guest check that the memory
> > contents are indeed what the guest owner expects.
> > 
> > Paolo
> 
> So the cover letter says hypervisor is benign, and then people turn
> around and start discussing guest owner checking memory as if hypervisor
> is malicious and might load something unexpected there.  Makes no sense
> to me.

Cover letter says "a benign but vulnerable (i.e. not fully
malicious) hypervisor". The hypervisor might be compromised from
the very beginning, but even a compromised hypervisor shouldn't
be able to provide an attestation that it has encrypted the
memory.

> 
> I suggest we just drop this attestation thing in v1. Try to merge
> something minimal that actually works first.

As far as I can see from the spec, attestation is part of the
encryption process (the Launch event). I don't see how this could
be even dropped.

One may argue to drop the usefulness of the attestation by doing
it very late. But I don't really see the point of doing it: are
there any users that would want to use SEV with a useless
attestation process? It sounds like adding dead code that nobody
would use until attestation is done properly.

> 
> You can always extend this to add more features later:
> whether there's any value in guest checking its own memory
> is something that would need a separate discussion at
> a higher level. I'm not saying there isn't.
> Let's do one thing at a time though.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:50                 ` Michael S. Tsirkin
@ 2016-09-14 14:08                   ` Eduardo Habkost
  2016-09-14 14:14                     ` Paolo Bonzini
  2016-09-14 15:17                     ` Michael S. Tsirkin
  2016-09-14 14:15                   ` Daniel P. Berrange
  1 sibling, 2 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 14:08 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Daniel P. Berrange, Paolo Bonzini, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > 
> > > > > 
> > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > give users more rope.
> > > > > 
> > > > > The hypervisor is assumed benign but vulnerable.
> > > > > 
> > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > then the encryption is effectively broken.
> > > > 
> > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > certain other features. eg, it seems that if you're using SEV, then
> > > > any concept of creating & analysing guest core dumps from the host
> > > > is out.
> > > 
> > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > 
> > If the facility to trigger dumps is available, then the memory
> > encryption feature of SEV is as useful as a chocolate teapot,
> > as the would be attacker can simply trigger a dump
> 
> If attacker can trigger things, IOW execute code in hypervisor,
> then encrypting memory is not useful anyway.

I believe the whole point of SEV attestation and key management
is to make "if attacker can executed code in hypervisor,
encrypting memory is not useful" _not_ true, isn't it?

Or are there known vulnerabilities that would allow a compromised
hypervisor to decrypt memory even after successful
encryption+attestation?

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:08                   ` Eduardo Habkost
@ 2016-09-14 14:14                     ` Paolo Bonzini
  2016-09-14 14:38                       ` Michael S. Tsirkin
  2016-09-14 15:17                     ` Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 14:14 UTC (permalink / raw)
  To: Eduardo Habkost, Michael S. Tsirkin
  Cc: Daniel P. Berrange, Brijesh Singh, crosthwaite.peter, p.fedin,
	qemu-devel, armbru, lcapitulino, rth



On 14/09/2016 16:08, Eduardo Habkost wrote:
>> > If attacker can trigger things, IOW execute code in hypervisor,
>> > then encrypting memory is not useful anyway.
> I believe the whole point of SEV attestation and key management
> is to make "if attacker can executed code in hypervisor,
> encrypting memory is not useful" _not_ true, isn't it?
> 
> Or are there known vulnerabilities that would allow a compromised
> hypervisor to decrypt memory even after successful
> encryption+attestation?

There are countless side channels that you can use but you have to start
somewhere, and anyway a side channel attack is way way more complex than
just "trigger a debug dump and read it".

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:50                 ` Michael S. Tsirkin
  2016-09-14 14:08                   ` Eduardo Habkost
@ 2016-09-14 14:15                   ` Daniel P. Berrange
  2016-09-14 14:48                     ` Michael S. Tsirkin
  1 sibling, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 14:15 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > 
> > > > > 
> > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > give users more rope.
> > > > > 
> > > > > The hypervisor is assumed benign but vulnerable.
> > > > > 
> > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > then the encryption is effectively broken.
> > > > 
> > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > certain other features. eg, it seems that if you're using SEV, then
> > > > any concept of creating & analysing guest core dumps from the host
> > > > is out.
> > > 
> > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > 
> > If the facility to trigger dumps is available, then the memory
> > encryption feature of SEV is as useful as a chocolate teapot,
> > as the would be attacker can simply trigger a dump
> 
> If attacker can trigger things, IOW execute code in hypervisor,
> then encrypting memory is not useful anyway.

The presentation at KVM forum claimed it *would* protect against
this, and that things like core dump of unencrypted memory would
not be permitted, so there's a disconnect between that preso and
what you're saying.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 13:48       ` Michael S. Tsirkin
@ 2016-09-14 14:19         ` Paolo Bonzini
  2016-09-14 15:02           ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 14:19 UTC (permalink / raw)
  To: Michael S. Tsirkin, Brijesh Singh
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, rth



On 14/09/2016 15:48, Michael S. Tsirkin wrote:
>> One of the bit in policy field is "debugging", if this bit is set then
>> hypervisor can use SEV commands to decrypt a guest memory
> 
> That is my point. Arbitrary code execution in hypervisor means game over
> anyway, at least with the hardware we have today.

Game is over if you assume the attacker has infinite power.  In practice
the attacker may be limited by other security features (SELinux,
seccomp, external firewalls, whatever), by the money and time they can
spend on the attack.  So anything that makes things harder for the
attacker is a security improvement.

> My suggestion is to merge the support for encrypting memory first,
> then make extras like disabling debugging on top.

Sorry but I concur with others that this makes no sense at all.  If
anything, it's *enabling* debugging that can be done on top.  That said...

> I can't say I understand how does guest measuring help prevent
> leaks in any way. Looks like a separate feature - why not split it
> out?

... the patch series seems to be pretty small and self contained.  I
don't see any point in splitting it further.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:14                     ` Paolo Bonzini
@ 2016-09-14 14:38                       ` Michael S. Tsirkin
  0 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 14:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Eduardo Habkost, Daniel P. Berrange, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:14:04PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 16:08, Eduardo Habkost wrote:
> >> > If attacker can trigger things, IOW execute code in hypervisor,
> >> > then encrypting memory is not useful anyway.
> > I believe the whole point of SEV attestation and key management
> > is to make "if attacker can executed code in hypervisor,
> > encrypting memory is not useful" _not_ true, isn't it?
> > 
> > Or are there known vulnerabilities that would allow a compromised
> > hypervisor to decrypt memory even after successful
> > encryption+attestation?
> 
> There are countless side channels that you can use but you have to start
> somewhere,

Absolutely, so let's start with a feature that is orthogonal, has a
defined threat model and does not conflict with valid uses please.

I was very happy to see an actual threat documented (passive adversary
with read only capabilities) as opposed to a vague makes some
attacks harder. Why don't we merge a patchset with that,
and then add stuff on top, documenting the benefits at each step?

> and anyway a side channel attack is way way more complex

More complex, sure, but in the age of libraries of exploits, I'm not
convinced it is measureably *harder* even if you add a third "way"
in this sentence. 0 multiplied by 1000 is still 0.

> than
> just "trigger a debug dump and read it".
> 
> Paolo

Really, my point isn't that ability to disable debugging is useless.
My point is that the feature is not really related to memory
encryption except by the vague "both are security things" notion.

If you consider adversary that has access to the monitor
and nothing else, then apparently disabling dumps and
debugging might be useful. So don't tie it all in to SEV please.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:15                   ` Daniel P. Berrange
@ 2016-09-14 14:48                     ` Michael S. Tsirkin
  2016-09-14 15:06                       ` Daniel P. Berrange
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 14:48 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 03:15:07PM +0100, Daniel P. Berrange wrote:
> On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > 
> > > > > > 
> > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > give users more rope.
> > > > > > 
> > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > 
> > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > then the encryption is effectively broken.
> > > > > 
> > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > any concept of creating & analysing guest core dumps from the host
> > > > > is out.
> > > > 
> > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > 
> > > If the facility to trigger dumps is available, then the memory
> > > encryption feature of SEV is as useful as a chocolate teapot,
> > > as the would be attacker can simply trigger a dump
> > 
> > If attacker can trigger things, IOW execute code in hypervisor,
> > then encrypting memory is not useful anyway.
> 
> The presentation at KVM forum claimed it *would* protect against
> this, and that things like core dump of unencrypted memory would
> not be permitted, so there's a disconnect between that preso and
> what you're saying.
> 
> Regards,
> Daniel

You mean presentation claimed protection against leaks to a malicious
active attacker within a hypervisor?  I guess the presentation covers
more than this patchset does then.  And the disconnect would be with
what the patchset cover letter says, not just with what I say.  Clearly
encrypting memory is not enough to protect against a malicious
hypervisor. E.g. just running info cpus is enough to leak information
from guest.


> -- 
> |: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
> |: http://libvirt.org              -o-             http://virt-manager.org :|
> |: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
> |: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:19         ` Paolo Bonzini
@ 2016-09-14 15:02           ` Michael S. Tsirkin
  2016-09-14 16:53             ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 15:02 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:19:38PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 15:48, Michael S. Tsirkin wrote:
> >> One of the bit in policy field is "debugging", if this bit is set then
> >> hypervisor can use SEV commands to decrypt a guest memory
> > 
> > That is my point. Arbitrary code execution in hypervisor means game over
> > anyway, at least with the hardware we have today.
> 
> Game is over if you assume the attacker has infinite power.  In practice
> the attacker may be limited by other security features (SELinux,
> seccomp, external firewalls, whatever), by the money and time they can
> spend on the attack.  So anything that makes things harder for the
> attacker is a security improvement.

Why don't we add assert(i == X) after each i = X in code?
This will make things harder for attackers that can skip
a single instruction only.

I think that the answer is that's because we do not believe there are
such attackers.  So defining a threat model is important.
The one that this patchset cover letter defined does not
include active attackers.

> > My suggestion is to merge the support for encrypting memory first,
> > then make extras like disabling debugging on top.
> 
> Sorry but I concur with others that this makes no sense at all.  If
> anything, it's *enabling* debugging that can be done on top.  That said...
> 
> > I can't say I understand how does guest measuring help prevent
> > leaks in any way. Looks like a separate feature - why not split it
> > out?
> 
> ... the patch series seems to be pretty small and self contained.  I
> don't see any point in splitting it further.
> 
> Paolo

One point is so we can discuss features and generalize them.

If you believe there are attackers that have access to the
monitor and nothing else, then a feature to disable debugging
is a generally useful one. But once we merge sev patchset then of course
sev people disappear and it will be up to others to make it
work on non-amd CPUs.

Another is to help merge other parts faster.  E.g.  looking at what
Daniel writes, the feature might have been over-sold so people will
disable debugging thinking this will prevent all active attacks. Thus we
now need to add good documentation so people know what they can actually
expect to get from QEMU in return for disabling debugging. Why not merge
the simple "encrypt memory part" while this documentation work is going
on?


-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:48                     ` Michael S. Tsirkin
@ 2016-09-14 15:06                       ` Daniel P. Berrange
  2016-09-14 15:46                         ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 15:06 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 05:48:17PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 03:15:07PM +0100, Daniel P. Berrange wrote:
> > On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > > give users more rope.
> > > > > > > 
> > > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > > 
> > > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > > then the encryption is effectively broken.
> > > > > > 
> > > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > > any concept of creating & analysing guest core dumps from the host
> > > > > > is out.
> > > > > 
> > > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > > 
> > > > If the facility to trigger dumps is available, then the memory
> > > > encryption feature of SEV is as useful as a chocolate teapot,
> > > > as the would be attacker can simply trigger a dump
> > > 
> > > If attacker can trigger things, IOW execute code in hypervisor,
> > > then encrypting memory is not useful anyway.
> > 
> > The presentation at KVM forum claimed it *would* protect against
> > this, and that things like core dump of unencrypted memory would
> > not be permitted, so there's a disconnect between that preso and
> > what you're saying.
> > 
> > Regards,
> > Daniel
> 
> You mean presentation claimed protection against leaks to a malicious
> active attacker within a hypervisor?  I guess the presentation covers
> more than this patchset does then.  And the disconnect would be with
> what the patchset cover letter says, not just with what I say.  Clearly
> encrypting memory is not enough to protect against a malicious
> hypervisor. E.g. just running info cpus is enough to leak information
> from guest.

It was explicit about the fact that the host admin would not have any
way to get access to the full contents of guest memory, without the
guest admin granting it. Only those non-encrypted pages used for I/O
transfer between host & guest would be accessible.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 14:08                   ` Eduardo Habkost
  2016-09-14 14:14                     ` Paolo Bonzini
@ 2016-09-14 15:17                     ` Michael S. Tsirkin
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 15:17 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Daniel P. Berrange, Paolo Bonzini, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 11:08:45AM -0300, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > 
> > > > > > 
> > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > give users more rope.
> > > > > > 
> > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > 
> > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > then the encryption is effectively broken.
> > > > > 
> > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > any concept of creating & analysing guest core dumps from the host
> > > > > is out.
> > > > 
> > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > 
> > > If the facility to trigger dumps is available, then the memory
> > > encryption feature of SEV is as useful as a chocolate teapot,
> > > as the would be attacker can simply trigger a dump
> > 
> > If attacker can trigger things, IOW execute code in hypervisor,
> > then encrypting memory is not useful anyway.
> 
> I believe the whole point of SEV attestation and key management
> is to make "if attacker can executed code in hypervisor,
> encrypting memory is not useful" _not_ true, isn't it?

That would be an aggressive claim. Not the one the cover letter is making.

> Or are there known vulnerabilities that would allow a compromised
> hypervisor to decrypt memory even after successful
> encryption+attestation?

> -- 
> Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 15:06                       ` Daniel P. Berrange
@ 2016-09-14 15:46                         ` Michael S. Tsirkin
  2016-09-14 17:35                           ` Eduardo Habkost
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 15:46 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Paolo Bonzini, Brijesh Singh, ehabkost, crosthwaite.peter,
	p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 04:06:33PM +0100, Daniel P. Berrange wrote:
> On Wed, Sep 14, 2016 at 05:48:17PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 03:15:07PM +0100, Daniel P. Berrange wrote:
> > > On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > > > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > > > 
> > > > > > > > 
> > > > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > > > give users more rope.
> > > > > > > > 
> > > > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > > > 
> > > > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > > > then the encryption is effectively broken.
> > > > > > > 
> > > > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > > > any concept of creating & analysing guest core dumps from the host
> > > > > > > is out.
> > > > > > 
> > > > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > > > 
> > > > > If the facility to trigger dumps is available, then the memory
> > > > > encryption feature of SEV is as useful as a chocolate teapot,
> > > > > as the would be attacker can simply trigger a dump
> > > > 
> > > > If attacker can trigger things, IOW execute code in hypervisor,
> > > > then encrypting memory is not useful anyway.
> > > 
> > > The presentation at KVM forum claimed it *would* protect against
> > > this, and that things like core dump of unencrypted memory would
> > > not be permitted, so there's a disconnect between that preso and
> > > what you're saying.
> > > 
> > > Regards,
> > > Daniel
> > 
> > You mean presentation claimed protection against leaks to a malicious
> > active attacker within a hypervisor?  I guess the presentation covers
> > more than this patchset does then.  And the disconnect would be with
> > what the patchset cover letter says, not just with what I say.  Clearly
> > encrypting memory is not enough to protect against a malicious
> > hypervisor. E.g. just running info cpus is enough to leak information
> > from guest.
> 
> It was explicit about the fact that the host admin would not have any
> way to get access to the full contents of guest memory, without the
> guest admin granting it. Only those non-encrypted pages used for I/O
> transfer between host & guest would be accessible.
> 
> Regards,
> Daniel

If you like, that's the vision. I'd rather discuss the patchset in
question though. It encrypts all memory but this does not protect against
all attackers, only passive ones. If you disable debugging,
it seems to additionally reduce the amount of information that can be
leaked to an active attacker in the hypervisor at one go.

Paolo seems to think it's useful, but it's a far cry from a deal
breaker, and your email just makes me worry that it has been oversold to
the point where everyone will start disabling debugging everywhere in
production and claim that otherwise it's a security problem.  IMO a much
better in-tree documentation is needed so people know what they are
getting in return.

Attestation seems mostly unrelated. The whitepaper says
	With this attestation, a guest owner can ensure that the hypervisor did
	not interfere with the initialization of SEV before transmitting
	confidential information to the guest.
which seems to imply an active attacker that is able to interfere
with the hypervisor during guest initialization but not afterwards.
So I have no idea why that's useful at the moment - I suspect
it's part of the future vision when there are protections
against all active attackers in place, but for now it seems to extend the
firmware/software interface unnecessarily.

> -- 
> |: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
> |: http://libvirt.org              -o-             http://virt-manager.org :|
> |: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
> |: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 13:51             ` Eduardo Habkost
@ 2016-09-14 16:10               ` Michael S. Tsirkin
  2016-09-14 17:25                 ` Eduardo Habkost
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 16:10 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paolo Bonzini, Brijesh Singh, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 10:51:59AM -0300, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 04:14:58PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 03:01:51PM +0200, Paolo Bonzini wrote:
> > > 
> > > 
> > > On 14/09/2016 14:09, Eduardo Habkost wrote:
> > > > On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
> > > >> On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> > > >>>
> > > >>>
> > > >>> On 13/09/2016 16:50, Brijesh Singh wrote:
> > > >>>> In SEV-enabled guest dma should be performed on shared pages. Since
> > > >>>> the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > > >>>> to create a shared page hence disable the dma operation when reading
> > > >>>> from fw_cfg interface.
> > > >>>>
> > > >>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > > >>>> ---
> > > >>>>  hw/nvram/fw_cfg.c |    6 ++++++
> > > >>>>  1 file changed, 6 insertions(+)
> > > >>>>
> > > >>>> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > > >>>> index 6a68e59..aca99e9 100644
> > > >>>> --- a/hw/nvram/fw_cfg.c
> > > >>>> +++ b/hw/nvram/fw_cfg.c
> > > >>>> @@ -24,6 +24,7 @@
> > > >>>>  #include "qemu/osdep.h"
> > > >>>>  #include "hw/hw.h"
> > > >>>>  #include "sysemu/sysemu.h"
> > > >>>> +#include "sysemu/kvm.h"
> > > >>>>  #include "sysemu/dma.h"
> > > >>>>  #include "hw/boards.h"
> > > >>>>  #include "hw/isa/isa.h"
> > > >>>> @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> > > >>>>      FWCfgIoState *s = FW_CFG_IO(dev);
> > > >>>>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > > >>>>  
> > > >>>> +    /* disable dma on fw_cfg when SEV is enabled */
> > > >>>> +    if (kvm_sev_enabled()) {
> > > >>>> +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > > >>>> +    }
> > > >>>> +
> > > >>>>      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> > > >>>>       * with half of the 16-bit control register. Hence, the total size
> > > >>>>       * of the i/o region used is FW_CFG_CTL_SIZE */
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>
> > > >>> As Michael said, a workaround is possible using -global.  However, I
> > > >>> really think that SEV should be implemented in UEFI firmware.  Because
> > > >>> it runs in 64-bit mode, it would be able to run in paged mode and it
> > > >>> would not have to encrypt everything before the SEV launch command.
> > > >>>
> > > >>> For example secure boot can be used to authenticate the kernel against
> > > >>> keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> > > >>> the firmware by the owner and used to boot from a LUKS-encrypted /boot
> > > >>> partition.
> > > >>>
> > > >>> Paolo
> > > >>
> > > >> Frankly I don't understand why do you need to mess with boot at all.
> > > >> Quoting the cover letter:
> > > >>
> > > >> 	SEV is designed to protect guest VMs from a benign but vulnerable
> > > >> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> > > >> 	attack
> > > >> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> > > >> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> > > >>
> > > >> it seems highly unlikely that any secret data is used during boot.
> > > >> So just let guest boot normally, and encrypt afterwards.
> > > > 
> > > > After boot seems too late for the attestation part (see Section
> > > > 1.3.1: Launch in the spec), unless you can ensure the memory
> > > > contents will always be exactly what the guest owner expects
> > > > after every boot.
> > > 
> > > And the attestation is what lets the guest check that the memory
> > > contents are indeed what the guest owner expects.
> > > 
> > > Paolo
> > 
> > So the cover letter says hypervisor is benign, and then people turn
> > around and start discussing guest owner checking memory as if hypervisor
> > is malicious and might load something unexpected there.  Makes no sense
> > to me.
> 
> Cover letter says "a benign but vulnerable (i.e. not fully
> malicious) hypervisor". The hypervisor might be compromised from
> the very beginning, but even a compromised hypervisor shouldn't
> be able to provide an attestation that it has encrypted the
> memory.

You seem to argue that this patch does protect against malicious
hypervisors. Is this so?

> > 
> > I suggest we just drop this attestation thing in v1. Try to merge
> > something minimal that actually works first.
> 
> As far as I can see from the spec, attestation is part of the
> encryption process (the Launch event). I don't see how this could
> be even dropped.
> 
> One may argue to drop the usefulness of the attestation by doing
> it very late. But I don't really see the point of doing it: are
> there any users that would want to use SEV with a useless
> attestation process?

This is what the cover letter says: protecting against passive
adversaries: if the adversary can read all hypervisor memory but nothing
else, you can stop some information leaks to that adversary.


> It sounds like adding dead code that nobody
> would use until attestation is done properly.

All I am saying is let's assume guests will ignore the measurement
result for now.  Judging by e.g. the whitepaper that I read,
attestation is designed to protect against a malicious hypervisor, so
it's part of a future vision, not the current patchset.



> > 
> > You can always extend this to add more features later:
> > whether there's any value in guest checking its own memory
> > is something that would need a separate discussion at
> > a higher level. I'm not saying there isn't.
> > Let's do one thing at a time though.
> 
> -- 
> Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-13 22:00       ` Eduardo Habkost
  2016-09-14  8:30         ` Daniel P. Berrange
@ 2016-09-14 16:10         ` Brijesh Singh
  2016-09-14 16:13           ` Daniel P. Berrange
  2016-09-14 16:20           ` Michael S. Tsirkin
  1 sibling, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 16:10 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: brijesh.singh, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth, Daniel P. Berrange


>> Various commands and parameters are documented [1]
>>
>> [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
>
> If I understand correctly, the docs describe the firmware
> interface. The interface provided by QEMU is not the same thing,
> and needs to be documented as well (even if it contains pointers
> to sections or tables in the firmware interface docs).
>
> Some of the questions I have about the fields are:
> * Do we really need the user to provide all the options below?
>   * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
>     for example?

Good question, I don't think we need to get this information from guest 
owner and it can be calculated from KVM. I will check with security 
folks on how this information is used in measurement generation and make 
the changes accordingly.

> * Is bit 0 (KS) the only bit that can be set on flags? If so, why
>   not a boolean "ks" option?
Agreed. I will fix in v2.

> * Is "policy" the guest policy structure described at page 23? If
>   so, why exposing the raw value instead of separate fields for
>   each bit/field in the structure? (and only for the ones that
>   are supposed to be set by the user)

Yes policy is described in chapter 3, page 23. I am open to separate the 
fields.
Let me know if something like this works

sev-launch-rule,flags.ks=0,policy.dbg=0,policy.ks=0,policy.nosend=0,...


> * If vcpu_mask is a bitmap for each VCPU, should we represent it
>   as a list of VCPU indexes?
>
I will check on this one.

> A good way to model this data and document it more properly is
> through a QAPI schema. grep for "opts_visitor_new()" in the code
> for examples where QEMU options are parsed according to a QAPI
> schema. The downside is that using a QAPI visitor is (AFAIK) not
> possible if using -object like I suggest below.
>
>>
>>>> [sev-launch]
>>>> 	flags = "00000000"
>>>> 	policy	= "000000"
>>>> 	dh_pub_qx = "0123456789abcdef0123456789abcdef"
>>>> 	dh_pub_qy = "0123456789abcdef0123456789abcdef"
>>>> 	nonce = "0123456789abcdef"
>>>> 	vcpu_count = "1"
>>>> 	vcpu_length = "30"
>>>> 	vcpu_mask = "00ab"
>>>
>>
>> All these config parameters should be provided by the guest owner before
>> launching or migrating a guest. I believe we need to make changes in
>> libvirt, virsh and other upper layer software stack to communicate with
>> guest owner to get these input parameters. For development purposes I choose
>> a simple config file to get these parameters. I am not sure if we will able
>> to "add new option to a existing objects/device" but we can look into
>> creating a "new type for -object" or we can simply accept a fd from upper
>> layer and read the fd to get these parameters.
>
> I was thinking of something like:
>
>   -object sev-launch-rule,flags=0,policy=0,dh_pub_qx=XXXXX,dh_pub_qy=YYYYY,nonce=ZZZZ,vcpu_count=1,vcpu_length=30,vcpu_mask=00ab \
>   -machine pc,accel=kvm,sev=on  # see note below[1]
>
> With this, you won't need separate code for command-line, config
> files, and QMP commands. They will all be able to use the same
> mechanisms.
>
> ...but this conflicts with the idea of using QAPI. So I am not
> sure which way to go. (But either way we go, we need a clearer
> and better documented set of parameters).
>

I am open to idea and need direction on which way to go. I will  work on 
documenting the parameters and usages. Should I consider implementing 
your below approach in v2 ?

-object 
sev-launch-rule,flags=0,policy=0,dh_pub_qx=XXXXX,dh_pub_qy=YYYYY,nonce=ZZZZ,vcpu_count=1,vcpu_length=30,vcpu_mask=00ab 
\ -machine pc,accel=kvm,sev=on

Any tips on which qemu file i can use as reference during 
implementation. Thanks.

> [1] I would go even further and separate the accel object options
>     from the machine options, but this would require reworking
>     the accelerator configuration inside QEMU. e.g.:
>
>   -object kvm-accel,sev=on,id=kvm0
>   -machine pc,accel=kvm0
>
> [...]
>>> Do we really need to write our own parser? I wonder if we can
>>> reuse crypto/secret.c for loading the keys.
>>>
>> I just looked at crypto/secret.c for loading the keys but not sure if will
>> able to reuse the secret_load routines, this is mainly because the SEV
>> inputs parameters are different compare to what we have in crypto/secrets.c.
>> I will still look more closely and see if we can find some common code.
>
> There are other parameters, sure, but maybe it would be
> appropriate to just load nonce/dh_pub_qx/dh_pub_qy as
> TTYPE_QCRYPTO_SECRET object(s) (-object secret,...)? I am not
> sure because I don't understand the crypto part fully.
>
> Daniel, what do you think?
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14 16:10         ` Brijesh Singh
@ 2016-09-14 16:13           ` Daniel P. Berrange
  2016-09-14 16:20           ` Michael S. Tsirkin
  1 sibling, 0 replies; 125+ messages in thread
From: Daniel P. Berrange @ 2016-09-14 16:13 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Eduardo Habkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On Wed, Sep 14, 2016 at 11:10:54AM -0500, Brijesh Singh wrote:
> 
> I am open to idea and need direction on which way to go. I will  work on
> documenting the parameters and usages. Should I consider implementing your
> below approach in v2 ?
> 
> -object sev-launch-rule,flags=0,policy=0,dh_pub_qx=XXXXX,dh_pub_qy=YYYYY,nonce=ZZZZ,vcpu_count=1,vcpu_length=30,vcpu_mask=00ab
> \ -machine pc,accel=kvm,sev=on
> 
> Any tips on which qemu file i can use as reference during implementation.

Take a look at crypto/secret.c for an example of how to create a QOM
object that can be loaded with '-object'. There are more examples
in backends/{hostmem,rng}*.c too.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status
  2016-09-13 16:09   ` Eric Blake
@ 2016-09-14 16:16     ` Brijesh Singh
  2016-09-15  4:13       ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 16:16 UTC (permalink / raw)
  To: Eric Blake, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth
  Cc: brijesh.singh

Hi Eric,

Thanks for feedback.

>>  # @present: true if KVM acceleration is built into this executable
>>  #
>> +# @sev: true if SEV is active
>
> Worth expanding what the acronym stands for.  Also needs a '(since 2.8)'
> designator.
>
will fix in v2.

>> +#
>>  # Since: 0.14.0
>>  ##
>> -{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
>> +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool', 'sev' : 'bool'} }
>
> Long line; please wrap to keep it under 80 columns.
>
will fix in v2.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback
  2016-09-13 22:47   ` Paolo Bonzini
@ 2016-09-14 16:19     ` Brijesh Singh
  0 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 16:19 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh

Hi Paolo,


On 09/13/2016 05:47 PM, Paolo Bonzini wrote:
>
>
> On 13/09/2016 16:50, Brijesh Singh wrote:
>> This patch adds methods to register a callback in qemu_system_reset().
>>
>> - qemu_register_pre_reset() : function will be called just after
>>   entering into qemu_system_reset().
>> - qemu_register_post_reset(): function will be called just before
>>   exiting from the qemu_system_reset().
>>
>> A qemu_system_reset() causes loader to reload the OS images into guest
>> memory. In case of SEV-enabled guest we need to call the SEV launch start
>> command before loader copies any data into guest RAM and similarly SEV
>> launch finish command should be executed after we finished copying the
>> data into guest memory.
>>
>> These callback will allow us to hook the SEV launch START and FINISH
>> commands into qemu_system_reset() handlder to start and finalize the SEV
>> guest launch process.
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>
> I would just put the SEV hook in qemu_system_reset().
>
> You can use a new file sev-stub.c with an empty implementation of
> kvm_sev_guest_start and kvm_sev_guest_finish.
>

Thanks for review, I will implement this in v2.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14 16:10         ` Brijesh Singh
  2016-09-14 16:13           ` Daniel P. Berrange
@ 2016-09-14 16:20           ` Michael S. Tsirkin
  2016-09-14 18:46             ` Brijesh Singh
  1 sibling, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 16:20 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Eduardo Habkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth, Daniel P. Berrange

On Wed, Sep 14, 2016 at 11:10:54AM -0500, Brijesh Singh wrote:
> 
> > > Various commands and parameters are documented [1]
> > > 
> > > [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
> > 
> > If I understand correctly, the docs describe the firmware
> > interface. The interface provided by QEMU is not the same thing,
> > and needs to be documented as well (even if it contains pointers
> > to sections or tables in the firmware interface docs).
> > 
> > Some of the questions I have about the fields are:
> > * Do we really need the user to provide all the options below?
> >   * Can't QEMU or KVM calculate vcpu_count/vcpu_length/vcpu_mask,
> >     for example?
> 
> Good question, I don't think we need to get this information from guest
> owner and it can be calculated from KVM. I will check with security folks on
> how this information is used in measurement generation and make the changes
> accordingly.
> 
> > * Is bit 0 (KS) the only bit that can be set on flags? If so, why
> >   not a boolean "ks" option?
> Agreed. I will fix in v2.
> 
> > * Is "policy" the guest policy structure described at page 23? If
> >   so, why exposing the raw value instead of separate fields for
> >   each bit/field in the structure? (and only for the ones that
> >   are supposed to be set by the user)
> 
> Yes policy is described in chapter 3, page 23. I am open to separate the
> fields.
> Let me know if something like this works
> 
> sev-launch-rule,flags.ks=0,policy.dbg=0,policy.ks=0,policy.nosend=0,...

My question is, does all of it have to be sev specific?
For example, add a generic flag to block debug commands from monitor.
When blocked, and if sev happens to be enabled, you can run guest with
debug disabled.


-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 15:02           ` Michael S. Tsirkin
@ 2016-09-14 16:53             ` Paolo Bonzini
  2016-09-14 18:15               ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 16:53 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 17:02, Michael S. Tsirkin wrote:
> If you believe there are attackers that have access to the
> monitor and nothing else, then a feature to disable debugging
> is a generally useful one. But once we merge sev patchset then of course
> sev people disappear and it will be up to others to make it
> work on non-amd CPUs.
> 
> Another is to help merge other parts faster.  E.g.  looking at what
> Daniel writes, the feature might have been over-sold so people will
> disable debugging thinking this will prevent all active attacks. Thus we
> now need to add good documentation so people know what they can actually
> expect to get from QEMU in return for disabling debugging. Why not merge
> the simple "encrypt memory part" while this documentation work is going
> on?

Encrypting memory makes no sense if anyone can ask to decrypt it.  And
I'm not even sure how force-enabling debug r/w, which is literally a
single bit set in the feature register, would make the patchset simpler.

If anything, as I said already, it would make the patchset simpler to
force-*disable* it, since you don't need to introduce debug hooks that
go through the secure processor.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 16:10               ` Michael S. Tsirkin
@ 2016-09-14 17:25                 ` Eduardo Habkost
  0 siblings, 0 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 17:25 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Paolo Bonzini, Brijesh Singh, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 07:10:50PM +0300, Michael S. Tsirkin wrote:
[...]
> > > > >> Frankly I don't understand why do you need to mess with boot at all.
> > > > >> Quoting the cover letter:
> > > > >>
> > > > >> 	SEV is designed to protect guest VMs from a benign but vulnerable
> > > > >> 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> > > > >> 	attack
> > > > >> 	surface of guest VMs and can prevent certain types of VM-escape bugs
> > > > >> 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> > > > >>
> > > > >> it seems highly unlikely that any secret data is used during boot.
> > > > >> So just let guest boot normally, and encrypt afterwards.
> > > > > 
> > > > > After boot seems too late for the attestation part (see Section
> > > > > 1.3.1: Launch in the spec), unless you can ensure the memory
> > > > > contents will always be exactly what the guest owner expects
> > > > > after every boot.
> > > > 
> > > > And the attestation is what lets the guest check that the memory
> > > > contents are indeed what the guest owner expects.
> > > > 
> > > > Paolo
> > > 
> > > So the cover letter says hypervisor is benign, and then people turn
> > > around and start discussing guest owner checking memory as if hypervisor
> > > is malicious and might load something unexpected there.  Makes no sense
> > > to me.
> > 
> > Cover letter says "a benign but vulnerable (i.e. not fully
> > malicious) hypervisor". The hypervisor might be compromised from
> > the very beginning, but even a compromised hypervisor shouldn't
> > be able to provide an attestation that it has encrypted the
> > memory.
> 
> You seem to argue that this patch does protect against malicious
> hypervisors. Is this so?

I am just assuming that the whole attestation system is there to
protect against compromised hypervisors.

> 
> > > 
> > > I suggest we just drop this attestation thing in v1. Try to merge
> > > something minimal that actually works first.
> > 
> > As far as I can see from the spec, attestation is part of the
> > encryption process (the Launch event). I don't see how this could
> > be even dropped.
> > 
> > One may argue to drop the usefulness of the attestation by doing
> > it very late. But I don't really see the point of doing it: are
> > there any users that would want to use SEV with a useless
> > attestation process?
> 
> This is what the cover letter says: protecting against passive
> adversaries: if the adversary can read all hypervisor memory but nothing
> else, you can stop some information leaks to that adversary.

I believe it tries to protect against additional attacks. To be
sure about it, I need to see the talk and read the specs more
carefully. (Maybe it's easier to simply wait for the patchset
author describe their thread model.)

> > It sounds like adding dead code that nobody
> > would use until attestation is done properly.
> 
> All I am saying is let's assume guests will ignore the measurement
> result for now.  Judging by e.g. the whitepaper that I read,
> attestation is designed to protect against a malicious hypervisor, so
> it's part of a future vision, not the current patchset.

I'm not sure about "future vision, not the current patchset"
part. I expect the current patchset to be effective against
additional attacks, but I agree this need to be more clearly
described in the patchset description/justification.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 15:46                         ` Michael S. Tsirkin
@ 2016-09-14 17:35                           ` Eduardo Habkost
  2016-09-14 22:05                             ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-14 17:35 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Daniel P. Berrange, Paolo Bonzini, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 06:46:20PM +0300, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 04:06:33PM +0100, Daniel P. Berrange wrote:
> > On Wed, Sep 14, 2016 at 05:48:17PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Sep 14, 2016 at 03:15:07PM +0100, Daniel P. Berrange wrote:
> > > > On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > > > > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > > > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > > > > give users more rope.
> > > > > > > > > 
> > > > > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > > > > 
> > > > > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > > > > then the encryption is effectively broken.
> > > > > > > > 
> > > > > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > > > > any concept of creating & analysing guest core dumps from the host
> > > > > > > > is out.
> > > > > > > 
> > > > > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > > > > 
> > > > > > If the facility to trigger dumps is available, then the memory
> > > > > > encryption feature of SEV is as useful as a chocolate teapot,
> > > > > > as the would be attacker can simply trigger a dump
> > > > > 
> > > > > If attacker can trigger things, IOW execute code in hypervisor,
> > > > > then encrypting memory is not useful anyway.
> > > > 
> > > > The presentation at KVM forum claimed it *would* protect against
> > > > this, and that things like core dump of unencrypted memory would
> > > > not be permitted, so there's a disconnect between that preso and
> > > > what you're saying.
> > > > 
> > > > Regards,
> > > > Daniel
> > > 
> > > You mean presentation claimed protection against leaks to a malicious
> > > active attacker within a hypervisor?  I guess the presentation covers
> > > more than this patchset does then.  And the disconnect would be with
> > > what the patchset cover letter says, not just with what I say.  Clearly
> > > encrypting memory is not enough to protect against a malicious
> > > hypervisor. E.g. just running info cpus is enough to leak information
> > > from guest.
> > 
> > It was explicit about the fact that the host admin would not have any
> > way to get access to the full contents of guest memory, without the
> > guest admin granting it. Only those non-encrypted pages used for I/O
> > transfer between host & guest would be accessible.
> > 
> > Regards,
> > Daniel
> 
> If you like, that's the vision. I'd rather discuss the patchset in
> question though. It encrypts all memory but this does not protect against
> all attackers, only passive ones. If you disable debugging,
> it seems to additionally reduce the amount of information that can be
> leaked to an active attacker in the hypervisor at one go.
> 
> Paolo seems to think it's useful, but it's a far cry from a deal
> breaker, and your email just makes me worry that it has been oversold to
> the point where everyone will start disabling debugging everywhere in
> production and claim that otherwise it's a security problem.  IMO a much
> better in-tree documentation is needed so people know what they are
> getting in return.
> 
> Attestation seems mostly unrelated. The whitepaper says
> 	With this attestation, a guest owner can ensure that the hypervisor did
> 	not interfere with the initialization of SEV before transmitting
> 	confidential information to the guest.
> which seems to imply an active attacker that is able to interfere
> with the hypervisor during guest initialization but not afterwards.

I believe this assumes a compromised hypervisor both before and
after guest launch, but this assumes the hypervisor:
1) Won't be able to change guest memory before attestation
   without being detected.
2) Won't be able to attack the guest after memory is encrypted.

> So I have no idea why that's useful at the moment - I suspect
> it's part of the future vision when there are protections
> against all active attackers in place, but for now it seems to extend the
> firmware/software interface unnecessarily.

"Protection against all active attackers" is a very broad
requirement. Effective protection against a given subset of
attacks would be reasonable enough to me.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 16:53             ` Paolo Bonzini
@ 2016-09-14 18:15               ` Michael S. Tsirkin
  2016-09-14 18:45                 ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 18:15 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 06:53:22PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 17:02, Michael S. Tsirkin wrote:
> > If you believe there are attackers that have access to the
> > monitor and nothing else, then a feature to disable debugging
> > is a generally useful one. But once we merge sev patchset then of course
> > sev people disappear and it will be up to others to make it
> > work on non-amd CPUs.
> > 
> > Another is to help merge other parts faster.  E.g.  looking at what
> > Daniel writes, the feature might have been over-sold so people will
> > disable debugging thinking this will prevent all active attacks. Thus we
> > now need to add good documentation so people know what they can actually
> > expect to get from QEMU in return for disabling debugging. Why not merge
> > the simple "encrypt memory part" while this documentation work is going
> > on?
> 
> Encrypting memory makes no sense if anyone can ask to decrypt it.

It's not useless since the attack model here is a passive adversary
that can not ask anything.

>  And
> I'm not even sure how force-enabling debug r/w, which is literally a
> single bit set in the feature register, would make the patchset simpler.

It will make the *interface* simpler.

> If anything, as I said already, it would make the patchset simpler to
> force-*disable* it, since you don't need to introduce debug hooks that
> go through the secure processor.
> 
> Paolo

My suggestion is to add a processor independent hook that disables
debugging.  Arguably this improves security in case attacker only has
access to the monitor.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 18:15               ` Michael S. Tsirkin
@ 2016-09-14 18:45                 ` Paolo Bonzini
  2016-09-14 19:24                   ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 18:45 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 20:15, Michael S. Tsirkin wrote:
> On Wed, Sep 14, 2016 at 06:53:22PM +0200, Paolo Bonzini wrote:
>>
>>
>> On 14/09/2016 17:02, Michael S. Tsirkin wrote:
>>> If you believe there are attackers that have access to the
>>> monitor and nothing else, then a feature to disable debugging
>>> is a generally useful one. But once we merge sev patchset then of course
>>> sev people disappear and it will be up to others to make it
>>> work on non-amd CPUs.
>>>
>>> Another is to help merge other parts faster.  E.g.  looking at what
>>> Daniel writes, the feature might have been over-sold so people will
>>> disable debugging thinking this will prevent all active attacks. Thus we
>>> now need to add good documentation so people know what they can actually
>>> expect to get from QEMU in return for disabling debugging. Why not merge
>>> the simple "encrypt memory part" while this documentation work is going
>>> on?
>>
>> Encrypting memory makes no sense if anyone can ask to decrypt it.
> 
> It's not useless since the attack model here is a passive adversary
> that can not ask anything.

Does _that attack model_ make sense then?  Also, I don't think this is
the attack model; limited protection against a compromised hypervisor is
included.

If the adversary is passive and cannot ask anything is it even an
adversary?  Why do you need encryption at all if you can't even ptrace QEMU?

>>  And
>> I'm not even sure how force-enabling debug r/w, which is literally a
>> single bit set in the feature register, would make the patchset simpler.
> 
> It will make the *interface* simpler.

If we made debug r/w force-disabled, the interface would be just as
simple, and the outcome more secure and more sensible.

>> If anything, as I said already, it would make the patchset simpler to
>> force-*disable* it, since you don't need to introduce debug hooks that
>> go through the secure processor.
> 
> My suggestion is to add a processor independent hook that disables
> debugging.  Arguably this improves security in case attacker only has
> access to the monitor.

The default is the wrong direction though for encrypted guests...

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14 16:20           ` Michael S. Tsirkin
@ 2016-09-14 18:46             ` Brijesh Singh
  2016-09-14 20:23               ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 18:46 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: brijesh.singh, Eduardo Habkost, crosthwaite.peter, armbru,
	p.fedin, qemu-devel, lcapitulino, pbonzini, rth,
	Daniel P. Berrange

Hi Michael,

>>
>> Yes policy is described in chapter 3, page 23. I am open to separate the
>> fields.
>> Let me know if something like this works
>>
>> sev-launch-rule,flags.ks=0,policy.dbg=0,policy.ks=0,policy.nosend=0,...
>
> My question is, does all of it have to be sev specific?
> For example, add a generic flag to block debug commands from monitor.
> When blocked, and if sev happens to be enabled, you can run guest with
> debug disabled.
>
>
All the sev option should be specified during guest creation.

A typical SEV flow look like this:

1) Guest owner requests cloud provider to launch a SEV quest.

2) Cloud provides requests the guest owner to provide the SEV launch 
parameter. These parameters includes: flags, policy, nonce, public 
diffie-hellman keys.

3) cloud provider launches qemu with '-sev' option.
    The code path looks like this:

    kvm_sev_guest_start()   [qemu]
       kvm_vm_ioctl(SEV_ISSUE_CMD)                 [kvm]
         asid = allocates a new SEV aid.           [kvm]
         psp_issue_cmd(LAUNCH_START)               [kvm]
          // the will call the firmware to create
          // new cryptographic context
         psp_issue_cmd(ACTIVATE, asid)             [kvm]
         // the command will bind asid to this crypto
         // context and loads the encryption key into
         // memory controller

4) As part of guest creation qemu loader copies data/code into guest 
memory (e.g BIOS). We need to encrypt the data/code copied into guest 
memory using LAUNCH_UPDATE command.
       sev_launch_update()
         kvm_vm_ioctl(SEV_ISSUE_CMD)
           psp_issue_cmd(LAUNCH_UPDATE, buffer)
            // the command will encrypt in-place

5) After qemu is done copying data into guest memory we call 
LAUNCH_FINISH, this command generate a measurement (basically hash of 
the data encrypted through LAUNCH_UPDATE).

6) Cloud provider sends the measurement to guest owner.

7) Guest owner validates the measurement. If measurement matches then we 
are good to launch the guest. This should ensure that bootcode was not 
compromised by hypervisor.

Once the guest is running then memory content of VM is transparently 
encrypted with key loaded into memory controller. SEV guest have the 
concept of private and shared memory. Private memory is encrypted with 
the guest-specific keys, while share memory may be encrypted with 
hypervisor key. Certain type of memory (namely instruction pages and 
guest page tables) are always considered as private. The guest OS can
mark individual pages of memory as encrypted using the standard x86 page 
table. I call it C-bit in PTE, if C-bit (bit 47) is set then page is 
private and if C-bit is 0 then page is shared. A page that is marked 
private will be automatically decrypted when read from the DRAM and 
encrypted when written to DRAM. Note that since C-bit is only 
controllable by the guest OS when it in operating in 64-bit or 32-bit 
PAE mode, in all other modes the SEV hardware forces the C-bit to a 1.

One of field in launch_start struct is 'policy', if policy allows the 
debugging then hypervisor can use SEV commands 
(kvm_sev_debug_decrypt/kvm_sev_debug_encrypt) to read and write into 
guest memory. If policy does not allow the debugging then any read of 
guest memory from hypervisor will get encrypted data and similarly 
writes to guest memory from hypervisor will result guest reading the 
garbage.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 18:45                 ` Paolo Bonzini
@ 2016-09-14 19:24                   ` Michael S. Tsirkin
  2016-09-14 19:58                     ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 19:24 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 08:45:25PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 20:15, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 06:53:22PM +0200, Paolo Bonzini wrote:
> >>
> >>
> >> On 14/09/2016 17:02, Michael S. Tsirkin wrote:
> >>> If you believe there are attackers that have access to the
> >>> monitor and nothing else, then a feature to disable debugging
> >>> is a generally useful one. But once we merge sev patchset then of course
> >>> sev people disappear and it will be up to others to make it
> >>> work on non-amd CPUs.
> >>>
> >>> Another is to help merge other parts faster.  E.g.  looking at what
> >>> Daniel writes, the feature might have been over-sold so people will
> >>> disable debugging thinking this will prevent all active attacks. Thus we
> >>> now need to add good documentation so people know what they can actually
> >>> expect to get from QEMU in return for disabling debugging. Why not merge
> >>> the simple "encrypt memory part" while this documentation work is going
> >>> on?
> >>
> >> Encrypting memory makes no sense if anyone can ask to decrypt it.
> > 
> > It's not useless since the attack model here is a passive adversary
> > that can not ask anything.
> 
> Does _that attack model_ make sense then?

It seems to make sense superficially.

> Also, I don't think this is
> the attack model; limited protection against a compromised hypervisor is
> included.

Well limited protection is of a limited use :) Seriously, the point of
mitigation should be blocking classes of vulenrabilities not making
things more complex.

> If the adversary is passive and cannot ask anything is it even an
> adversary?  Why do you need encryption at all if you can't even ptrace QEMU?

The cover letter mentioned a read everything adversary.
How do you read everything? Well, you probably don't but
there could be attacks that cause kernel to leak
contents of random memory to an attacker.


> >>  And
> >> I'm not even sure how force-enabling debug r/w, which is literally a
> >> single bit set in the feature register, would make the patchset simpler.
> > 
> > It will make the *interface* simpler.
> 
> If we made debug r/w force-disabled, the interface would be just as
> simple, and the outcome more secure and more sensible.

If you don't think debugging is useful (maybe it isn't) do it for
everyone then :)

> >> If anything, as I said already, it would make the patchset simpler to
> >> force-*disable* it, since you don't need to introduce debug hooks that
> >> go through the secure processor.
> > 
> > My suggestion is to add a processor independent hook that disables
> > debugging.  Arguably this improves security in case attacker only has
> > access to the monitor.
> 
> The default is the wrong direction though for encrypted guests...
> 
> Paolo

I think this is just tying unrelated features together. Hardware vendors
always do this - they want to sell their hardware that
solves all the problems. On the software side, we should try to
push for enabling features independently, this way more
hardware can benefit.

People that do not need debugging can disable it and maybe some exploit
will be prevented. Not at all different for encryption.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 19:24                   ` Michael S. Tsirkin
@ 2016-09-14 19:58                     ` Paolo Bonzini
  2016-09-14 20:36                       ` Michael S. Tsirkin
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 19:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 21:24, Michael S. Tsirkin wrote:
> Well limited protection is of a limited use :) Seriously, the point of
> mitigation should be blocking classes of vulenrabilities not making
> things more complex.

No, not at all.  The point of _mitigation_ is to _mitigate_ the danger
from classes of vulnerabilities, i.e. make the attack harder though
perhaps not ultimately impossible.

>> If the adversary is passive and cannot ask anything is it even an
>> adversary?  Why do you need encryption at all if you can't even ptrace QEMU?
> 
> The cover letter mentioned a read everything adversary.
> How do you read everything? Well, you probably don't but
> there could be attacks that cause kernel to leak
> contents of random memory to an attacker.

Ok, it doesn't seem too useful.

> On the software side, we should try to
> push for enabling features independently, this way more
> hardware can benefit.

We can have an "unencrypted" sev-policy that only has limited
functionality such as disabling debug.  So you could disable debug with

 -object sev-policy-unencrypted,debug=false,id=mypolicy \
 -machine ...,sev-policy=mypolicy

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support
  2016-09-14 18:46             ` Brijesh Singh
@ 2016-09-14 20:23               ` Michael S. Tsirkin
  0 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 20:23 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Eduardo Habkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, pbonzini, rth, Daniel P. Berrange

On Wed, Sep 14, 2016 at 01:46:09PM -0500, Brijesh Singh wrote:
> 7) Guest owner validates the measurement. If measurement matches then we are
> good to launch the guest. This should ensure that bootcode was not
> compromised by hypervisor.

As hypervisor can e.g. execute said code in any order (without touching
protected memory) this seems rather like adding asserts in code at
random points. Frankly if one is so worried about the boot sequence,
just send an already booted guest to the cloud provider.


But anyway, that's beside the point. My point is that all this
measurement dance is orthogonal to memory encryption.
It happens to be part of the same AMD CPU, but it
might not be on other CPUs, and I don't see why
should command line/QOM APIs tie us to what AMD did.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-13 22:59   ` Paolo Bonzini
  2016-09-14  2:38     ` Michael S. Tsirkin
@ 2016-09-14 20:29     ` Brijesh Singh
  2016-09-14 20:38       ` Paolo Bonzini
  1 sibling, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 20:29 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh



On 09/13/2016 05:59 PM, Paolo Bonzini wrote:
>
>
> On 13/09/2016 16:50, Brijesh Singh wrote:
>> In SEV-enabled mode we need to reload the BIOS image on loader reset, this
>> will ensure that BIOS image gets encrypted and included as part of launch
>> meausrement on guest reset.
>
> Just to check if I understand correctly, the secure processor cannot
> split the encryption and measuring, which is why you need to redo the
> copy on every reset.
>

That is right, after LAUNCH_FINISH is called the secure processor 
cleanup the LAUNCH_START context so that hypervisor can not call 
LAUNCH_UPDATE to inject a new data into guest memory. After 
LAUNCH_FINISH only thing we can call is SEV_DEBUG_* or SEV_RECEIVE_* 
commands.

> Does the guest have to check the measured data (e.g. with a hash) too,
> to check that it hasn't been tampered with outside the secure
> processor's control?  Of course this would result in garbage written to
> the modified page, but that might be a valid attack vector.
>

Guest does not need to check the measurement.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs
  2016-09-13 23:00   ` Paolo Bonzini
@ 2016-09-14 20:30     ` Brijesh Singh
  0 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 20:30 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh



>>   */
>>  #define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
>>
>> +/* Access the guest memory for debug purposes */
>> +#define MEMTXATTRS_SEV_DEBUG ((MemTxAttrs) { .sev_debug = 1 })
>>  #endif
>
> Just make it "debug" and MEMTXATTRS_DEBUG.
>

Thanks, will fix in v2.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 19:58                     ` Paolo Bonzini
@ 2016-09-14 20:36                       ` Michael S. Tsirkin
  2016-09-14 20:44                         ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 20:36 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 09:58:25PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 21:24, Michael S. Tsirkin wrote:
> > Well limited protection is of a limited use :) Seriously, the point of
> > mitigation should be blocking classes of vulenrabilities not making
> > things more complex.
> 
> No, not at all.  The point of _mitigation_ is to _mitigate_ the danger
> from classes of vulnerabilities, i.e. make the attack harder though
> perhaps not ultimately impossible.

Right. And features generally reduce security. Does not mean we don't
need to add any features.  The tradeoffs need to be weighted and
documented, this is missing here.

Specifically with debug, if you have debug then clearly you
can dump guest memory. This is what this feature is about.
If we want a hypervisor that can not dump guest memory, let's
add a flag like that. Does everyone have to disable debugging
by default? I don't see why. Does everyone using encryption
have to do this? I don't see why either.

> >> If the adversary is passive and cannot ask anything is it even an
> >> adversary?  Why do you need encryption at all if you can't even ptrace QEMU?
> > 
> > The cover letter mentioned a read everything adversary.
> > How do you read everything? Well, you probably don't but
> > there could be attacks that cause kernel to leak
> > contents of random memory to an attacker.
> 
> Ok, it doesn't seem too useful.
> 
> > On the software side, we should try to
> > push for enabling features independently, this way more
> > hardware can benefit.
> 
> We can have an "unencrypted" sev-policy that only has limited
> functionality such as disabling debug.  So you could disable debug with
> 
>  -object sev-policy-unencrypted,debug=false,id=mypolicy \
>  -machine ...,sev-policy=mypolicy
> 
> Paolo

I wouldn't say sev on the command line. SEV seems to be
a group of AMD technologies implemening memory encryption,
measurement etc.

Let's have flags for individual components:

-machine ...,debug=false,memory-encryption=on,...

E.g. I can imagine tcg implementing encrypted at rest memory.

If you are on AMD and memory=encrypted then you would enable
SEV. If debug=false then disable debug. As I mentioned,
if monitor is a socket this might be genuinely increasing
guest security.

I'm fine with e.g. memory-encryption=on being an AMD-only
feature for now.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-14 20:29     ` Brijesh Singh
@ 2016-09-14 20:38       ` Paolo Bonzini
  2016-09-14 21:09         ` Michael S. Tsirkin
  2016-09-14 21:24         ` Brijesh Singh
  0 siblings, 2 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 20:38 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 22:29, Brijesh Singh wrote:
>> Does the guest have to check the measured data (e.g. with a hash) too,
>> to check that it hasn't been tampered with outside the secure
>> processor's control?  Of course this would result in garbage written to
>> the modified page, but that might be a valid attack vector.
> 
> Guest does not need to check the measurement.

Can you explain why not?

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 20:36                       ` Michael S. Tsirkin
@ 2016-09-14 20:44                         ` Paolo Bonzini
  2016-09-14 21:25                           ` Brijesh Singh
  2016-09-14 21:38                           ` Michael S. Tsirkin
  0 siblings, 2 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 20:44 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 22:36, Michael S. Tsirkin wrote:
> Specifically with debug, if you have debug then clearly you
> can dump guest memory. This is what this feature is about.
> If we want a hypervisor that can not dump guest memory, let's
> add a flag like that. Does everyone have to disable debugging
> by default? I don't see why. Does everyone using encryption
> have to do this? I don't see why either.

If you can explain what's the point in doing encryption that can be
defeated with a single ioctl, perhaps I'll agree with you.  It's okay
that we leave out features.  But every feature left out is an
anti-feature baked in.  Force-enable debug?  You've provided a loophole
for everyone.  Force-disable debug?  Well, of course you've blocked
debug for everyone.

I agree that they are distinct features on the command line, but I think
you're underestimating the importance of choosing a sane default, that's it.

>>  -object sev-policy-unencrypted,debug=false,id=mypolicy \
>>  -machine ...,sev-policy=mypolicy
> 
> I wouldn't say sev on the command line. SEV seems to be
> a group of AMD technologies implemening memory encryption,
> measurement etc.
> 
> Let's have flags for individual components:
> 
> -machine ...,debug=false,memory-encryption=on,...

I think it makes sense to have a separate -object for the policy.  Let's
just make it security-policy instead of sev-policy.  Brijesh, is that okay?

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-13 23:05   ` Paolo Bonzini
@ 2016-09-14 20:59     ` Brijesh Singh
  2016-09-14 21:00       ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 20:59 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh

Hi Paolo,

On 09/13/2016 06:05 PM, Paolo Bonzini wrote:
>
>
> On 13/09/2016 16:49, Brijesh Singh wrote:
>>
>> +    /* Register SEV read/write ops for the guest RAM */
>> +    if (kvm_sev_enabled())
>> +        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());
>
> If you don't actually need this one except for -kernel it would be very
> nice, because then the hooks could be limited to cpu_memory_rw_debug.
>

Yes so far i see that we needing this only for -kernel option.

> address_space_write and address_space_read are the central entry point
> for device DMA, and calling mr->ram_ops->write from there seems very
> wrong.  I'd rather make those hooks *ROM* read/write ops rather than RAM
> read/write ops.
>

I will look into hooking up the callback into ROM read/write ops. I was 
thinking about adding a new argument in 
cpu_physical_memory_write_rom_internal()

void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
                                    const uint8_t *buf, int len,
                                    WriteCB *cb)
{
    ....
    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);

    if (cb)
      cb(ptr, buf, len)
    else
      memcpy(ptr, buf, len)
....

}

In case of SEV, we pass a CB function pointer which calls SEV API's to 
encrypt memory. Does this make sense?

-Brijesh

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 20:59     ` Brijesh Singh
@ 2016-09-14 21:00       ` Paolo Bonzini
  2016-09-14 21:47         ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 21:00 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 22:59, Brijesh Singh wrote:
> I will look into hooking up the callback into ROM read/write ops. I was
> thinking about adding a new argument in
> cpu_physical_memory_write_rom_internal()
> 
> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>                                    const uint8_t *buf, int len,
>                                    WriteCB *cb)
> {
>    ....
>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> 
>    if (cb)
>      cb(ptr, buf, len)
>    else
>      memcpy(ptr, buf, len)
> ....
> 
> }
> 
> In case of SEV, we pass a CB function pointer which calls SEV API's to
> encrypt memory. Does this make sense?

I think a global as you have it in this series is just fine---just don't
hook it into address_space_read and address_space_write.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-14 20:38       ` Paolo Bonzini
@ 2016-09-14 21:09         ` Michael S. Tsirkin
  2016-09-14 21:11           ` Paolo Bonzini
  2016-09-14 21:24         ` Brijesh Singh
  1 sibling, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 21:09 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 10:38:58PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 22:29, Brijesh Singh wrote:
> >> Does the guest have to check the measured data (e.g. with a hash) too,
> >> to check that it hasn't been tampered with outside the secure
> >> processor's control?  Of course this would result in garbage written to
> >> the modified page, but that might be a valid attack vector.
> > 
> > Guest does not need to check the measurement.
> 
> Can you explain why not?
> 
> Paolo

For example, guest can boot in a secure environment and then be migrated
to cloud. In fact that seems much easier to manage than all the hash
based stuff.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-14 21:09         ` Michael S. Tsirkin
@ 2016-09-14 21:11           ` Paolo Bonzini
  0 siblings, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 21:11 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 23:09, Michael S. Tsirkin wrote:
> > > > Does the guest have to check the measured data (e.g. with a hash) too,
> > > > to check that it hasn't been tampered with outside the secure
> > > > processor's control?  Of course this would result in garbage written to
> > > > the modified page, but that might be a valid attack vector.
> > > 
> > > Guest does not need to check the measurement.
> > 
> > Can you explain why not?
> 
> For example, guest can boot in a secure environment and then be migrated
> to cloud. In fact that seems much easier to manage than all the hash
> based stuff.

This is not what I was asking.  My question was: assuming that the guest
is interested in checking the measurement, does it also have to
recompute it independently, and if not why?

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest
  2016-09-14 20:38       ` Paolo Bonzini
  2016-09-14 21:09         ` Michael S. Tsirkin
@ 2016-09-14 21:24         ` Brijesh Singh
  1 sibling, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 21:24 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh



On 09/14/2016 03:38 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 22:29, Brijesh Singh wrote:
>>> Does the guest have to check the measured data (e.g. with a hash) too,
>>> to check that it hasn't been tampered with outside the secure
>>> processor's control?  Of course this would result in garbage written to
>>> the modified page, but that might be a valid attack vector.
>>
>> Guest does not need to check the measurement.
>
> Can you explain why not?
>
Paolo, this is good question, I will check this internally and come back 
to you.

> Paolo
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 20:44                         ` Paolo Bonzini
@ 2016-09-14 21:25                           ` Brijesh Singh
  2016-09-14 21:38                           ` Michael S. Tsirkin
  1 sibling, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 21:25 UTC (permalink / raw)
  To: Paolo Bonzini, Michael S. Tsirkin
  Cc: brijesh.singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth



On 09/14/2016 03:44 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 22:36, Michael S. Tsirkin wrote:
>> Specifically with debug, if you have debug then clearly you
>> can dump guest memory. This is what this feature is about.
>> If we want a hypervisor that can not dump guest memory, let's
>> add a flag like that. Does everyone have to disable debugging
>> by default? I don't see why. Does everyone using encryption
>> have to do this? I don't see why either.
>
> If you can explain what's the point in doing encryption that can be
> defeated with a single ioctl, perhaps I'll agree with you.  It's okay
> that we leave out features.  But every feature left out is an
> anti-feature baked in.  Force-enable debug?  You've provided a loophole
> for everyone.  Force-disable debug?  Well, of course you've blocked
> debug for everyone.
>
> I agree that they are distinct features on the command line, but I think
> you're underestimating the importance of choosing a sane default, that's it.
>
>>>  -object sev-policy-unencrypted,debug=false,id=mypolicy \
>>>  -machine ...,sev-policy=mypolicy
>>
>> I wouldn't say sev on the command line. SEV seems to be
>> a group of AMD technologies implemening memory encryption,
>> measurement etc.
>>
>> Let's have flags for individual components:
>>
>> -machine ...,debug=false,memory-encryption=on,...
>
> I think it makes sense to have a separate -object for the policy.  Let's
> just make it security-policy instead of sev-policy.  Brijesh, is that okay?
>

Yes, fine with me.

-Brijesh

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 20:44                         ` Paolo Bonzini
  2016-09-14 21:25                           ` Brijesh Singh
@ 2016-09-14 21:38                           ` Michael S. Tsirkin
  1 sibling, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 21:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 10:44:58PM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 22:36, Michael S. Tsirkin wrote:
> > Specifically with debug, if you have debug then clearly you
> > can dump guest memory. This is what this feature is about.
> > If we want a hypervisor that can not dump guest memory, let's
> > add a flag like that. Does everyone have to disable debugging
> > by default? I don't see why. Does everyone using encryption
> > have to do this? I don't see why either.
> 
> If you can explain what's the point in doing encryption that can be
> defeated with a single ioctl, perhaps I'll agree with you.

Discussed offline, I hope I clarified things.  Hypervisor (host kernel)
can decrypt but it is already possible for it to cause guest info leaks.
But no one else on the host can.

> It's okay
> that we leave out features.  But every feature left out is an
> anti-feature baked in.  Force-enable debug?  You've provided a loophole
> for everyone.

It's already baked in by default. Let's switch it to off by default for
everyone if we are worried about using monitor to leak guest secrets?
Btw with a TCP socket monitor, this seems like a legitimate worry.

We can do it when the new security policy object is created.

> Force-disable debug?  Well, of course you've blocked
> debug for everyone.
> 
> I agree that they are distinct features on the command line, but I think
> you're underestimating the importance of choosing a sane default, that's it.

We can safely leave that for management, but I won't object
to switching the default too, let's just do it for everyone,
consistently.

> >>  -object sev-policy-unencrypted,debug=false,id=mypolicy \
> >>  -machine ...,sev-policy=mypolicy
> > 
> > I wouldn't say sev on the command line. SEV seems to be
> > a group of AMD technologies implemening memory encryption,
> > measurement etc.
> > 
> > Let's have flags for individual components:
> > 
> > -machine ...,debug=false,memory-encryption=on,...
> 
> I think it makes sense to have a separate -object for the policy.  Let's
> just make it security-policy instead of sev-policy.  Brijesh, is that okay?
> 
> Paolo

OK. And some parts like blocking debug are easy enough to implement for everyone.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 21:00       ` Paolo Bonzini
@ 2016-09-14 21:47         ` Brijesh Singh
  2016-09-14 21:52           ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 21:47 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh



On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 22:59, Brijesh Singh wrote:
>> I will look into hooking up the callback into ROM read/write ops. I was
>> thinking about adding a new argument in
>> cpu_physical_memory_write_rom_internal()
>>
>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>                                    const uint8_t *buf, int len,
>>                                    WriteCB *cb)
>> {
>>    ....
>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>
>>    if (cb)
>>      cb(ptr, buf, len)
>>    else
>>      memcpy(ptr, buf, len)
>> ....
>>
>> }
>>
>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>> encrypt memory. Does this make sense?
>
> I think a global as you have it in this series is just fine---just don't
> hook it into address_space_read and address_space_write.
>

Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag 
set then use SEV debug command otherwise default to memcpy so that DMA 
and everything else works. I guest the main reason why i choose to hook 
this up in address_space_read/write was that I found that 
address_space_write and address_space_read is used in debug path. e.g

cpu_memory_rw_debug
   address_space_rw
     address_space_write/read

cpu_physical_memory_rw
  address_space_rw
    address_space_write/read

How do you want me to handle these cases? Having SEV RAM callback taking 
care this internally was my simplest solution,  I am certainly open to 
new ideas.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 21:47         ` Brijesh Singh
@ 2016-09-14 21:52           ` Paolo Bonzini
  2016-09-14 22:06             ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 21:52 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 14/09/2016 23:47, Brijesh Singh wrote:
> 
> 
> On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>>
>>
>> On 14/09/2016 22:59, Brijesh Singh wrote:
>>> I will look into hooking up the callback into ROM read/write ops. I was
>>> thinking about adding a new argument in
>>> cpu_physical_memory_write_rom_internal()
>>>
>>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>>                                    const uint8_t *buf, int len,
>>>                                    WriteCB *cb)
>>> {
>>>    ....
>>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>>
>>>    if (cb)
>>>      cb(ptr, buf, len)
>>>    else
>>>      memcpy(ptr, buf, len)
>>> ....
>>>
>>> }
>>>
>>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>>> encrypt memory. Does this make sense?
>>
>> I think a global as you have it in this series is just fine---just don't
>> hook it into address_space_read and address_space_write.
>>
> 
> Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag
> set then use SEV debug command otherwise default to memcpy so that DMA
> and everything else works. I guest the main reason why i choose to hook
> this up in address_space_read/write was that I found that
> address_space_write and address_space_read is used in debug path. e.g
> 
> cpu_memory_rw_debug
>   address_space_rw
>     address_space_write/read

Right, but if you change this to a ROM hook only, cpu_memory_rw_debug
will go through cpu_physical_memory_write_rom instead.  This will invoke
the hook properly, won't it?  It will break -kernel unless fw_cfg DMA is
disabled, of course.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 17:35                           ` Eduardo Habkost
@ 2016-09-14 22:05                             ` Michael S. Tsirkin
  2016-09-15 14:58                               ` Eduardo Habkost
  0 siblings, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-14 22:05 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Daniel P. Berrange, Paolo Bonzini, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 02:35:41PM -0300, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 06:46:20PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 04:06:33PM +0100, Daniel P. Berrange wrote:
> > > On Wed, Sep 14, 2016 at 05:48:17PM +0300, Michael S. Tsirkin wrote:
> > > > On Wed, Sep 14, 2016 at 03:15:07PM +0100, Daniel P. Berrange wrote:
> > > > > On Wed, Sep 14, 2016 at 04:50:51PM +0300, Michael S. Tsirkin wrote:
> > > > > > On Wed, Sep 14, 2016 at 02:37:49PM +0100, Daniel P. Berrange wrote:
> > > > > > > On Wed, Sep 14, 2016 at 04:32:44PM +0300, Michael S. Tsirkin wrote:
> > > > > > > > On Wed, Sep 14, 2016 at 02:23:14PM +0100, Daniel P. Berrange wrote:
> > > > > > > > > On Wed, Sep 14, 2016 at 03:07:58PM +0200, Paolo Bonzini wrote:
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > On 14/09/2016 15:05, Michael S. Tsirkin wrote:
> > > > > > > > > > > I assumed that with debug on, memory is still encrypted but the
> > > > > > > > > > > hypervisor can break encryption, and as the cover letter states, the
> > > > > > > > > > > hypervisor is assumed benign. If true I don't see a need to
> > > > > > > > > > > give users more rope.
> > > > > > > > > > 
> > > > > > > > > > The hypervisor is assumed benign but vulnerable.
> > > > > > > > > > 
> > > > > > > > > > So, if somebody breaks the hypervisor, you would like to make it as hard
> > > > > > > > > > as possible for the attacker to do evil stuff to the guests.  If the
> > > > > > > > > > attacker can just ask the secure processor "decrypt some memory for me",
> > > > > > > > > > then the encryption is effectively broken.
> > > > > > > > > 
> > > > > > > > > So there's going to be a tradeoff here between use of SEV and use of
> > > > > > > > > certain other features. eg, it seems that if you're using SEV, then
> > > > > > > > > any concept of creating & analysing guest core dumps from the host
> > > > > > > > > is out.
> > > > > > > > 
> > > > > > > > I don't see why - as long as we don't trigger dumps, there's no leak :)
> > > > > > > 
> > > > > > > If the facility to trigger dumps is available, then the memory
> > > > > > > encryption feature of SEV is as useful as a chocolate teapot,
> > > > > > > as the would be attacker can simply trigger a dump
> > > > > > 
> > > > > > If attacker can trigger things, IOW execute code in hypervisor,
> > > > > > then encrypting memory is not useful anyway.
> > > > > 
> > > > > The presentation at KVM forum claimed it *would* protect against
> > > > > this, and that things like core dump of unencrypted memory would
> > > > > not be permitted, so there's a disconnect between that preso and
> > > > > what you're saying.
> > > > > 
> > > > > Regards,
> > > > > Daniel
> > > > 
> > > > You mean presentation claimed protection against leaks to a malicious
> > > > active attacker within a hypervisor?  I guess the presentation covers
> > > > more than this patchset does then.  And the disconnect would be with
> > > > what the patchset cover letter says, not just with what I say.  Clearly
> > > > encrypting memory is not enough to protect against a malicious
> > > > hypervisor. E.g. just running info cpus is enough to leak information
> > > > from guest.
> > > 
> > > It was explicit about the fact that the host admin would not have any
> > > way to get access to the full contents of guest memory, without the
> > > guest admin granting it. Only those non-encrypted pages used for I/O
> > > transfer between host & guest would be accessible.
> > > 
> > > Regards,
> > > Daniel
> > 
> > If you like, that's the vision. I'd rather discuss the patchset in
> > question though. It encrypts all memory but this does not protect against
> > all attackers, only passive ones. If you disable debugging,
> > it seems to additionally reduce the amount of information that can be
> > leaked to an active attacker in the hypervisor at one go.
> > 
> > Paolo seems to think it's useful, but it's a far cry from a deal
> > breaker, and your email just makes me worry that it has been oversold to
> > the point where everyone will start disabling debugging everywhere in
> > production and claim that otherwise it's a security problem.  IMO a much
> > better in-tree documentation is needed so people know what they are
> > getting in return.
> > 
> > Attestation seems mostly unrelated. The whitepaper says
> > 	With this attestation, a guest owner can ensure that the hypervisor did
> > 	not interfere with the initialization of SEV before transmitting
> > 	confidential information to the guest.
> > which seems to imply an active attacker that is able to interfere
> > with the hypervisor during guest initialization but not afterwards.
> 
> I believe this assumes a compromised hypervisor both before and
> after guest launch, but this assumes the hypervisor:
> 1) Won't be able to change guest memory before attestation
>    without being detected.
> 2) Won't be able to attack the guest after memory is encrypted.

Why would you need to measure things then?  If you assume this, at what
point *can* attacker change memory?

> > So I have no idea why that's useful at the moment - I suspect
> > it's part of the future vision when there are protections
> > against all active attackers in place, but for now it seems to extend the
> > firmware/software interface unnecessarily.
> 
> "Protection against all active attackers" is a very broad
> requirement. Effective protection against a given subset of
> attacks would be reasonable enough to me.

Well selecting a random point in time and saying "I protect against
attacks at this point only" would be a very weak protection, akin to
just adding an assert statement at a random place in code - even though
yes, if you hit that assert you are protected.

This is not to say this is what this patchset does, merely
that it should include a bit more information about the
motivation for the measurement part than
"this is what we can easily implement".


> -- 
> Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 21:52           ` Paolo Bonzini
@ 2016-09-14 22:06             ` Brijesh Singh
  2016-09-14 22:17               ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 22:06 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh



On 09/14/2016 04:52 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 23:47, Brijesh Singh wrote:
>>
>>
>> On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>>>
>>>
>>> On 14/09/2016 22:59, Brijesh Singh wrote:
>>>> I will look into hooking up the callback into ROM read/write ops. I was
>>>> thinking about adding a new argument in
>>>> cpu_physical_memory_write_rom_internal()
>>>>
>>>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>>>                                    const uint8_t *buf, int len,
>>>>                                    WriteCB *cb)
>>>> {
>>>>    ....
>>>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>>>
>>>>    if (cb)
>>>>      cb(ptr, buf, len)
>>>>    else
>>>>      memcpy(ptr, buf, len)
>>>> ....
>>>>
>>>> }
>>>>
>>>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>>>> encrypt memory. Does this make sense?
>>>
>>> I think a global as you have it in this series is just fine---just don't
>>> hook it into address_space_read and address_space_write.
>>>
>>
>> Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag
>> set then use SEV debug command otherwise default to memcpy so that DMA
>> and everything else works. I guest the main reason why i choose to hook
>> this up in address_space_read/write was that I found that
>> address_space_write and address_space_read is used in debug path. e.g
>>
>> cpu_memory_rw_debug
>>   address_space_rw
>>     address_space_write/read
>
> Right, but if you change this to a ROM hook only, cpu_memory_rw_debug
> will go through cpu_physical_memory_write_rom instead.  This will invoke
> the hook properly, won't it?  It will break -kernel unless fw_cfg DMA is
> disabled, of course.
>

maybe I am missing something.

here is what I see:

int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
{
   ............

    if (is_write)
        cpu_physical_memory_write_rom_internal()
     else
        address_space_rw()

    .....

}

So looking at code, i have impression that write will go through the 
cpu_physical_memory_write_rom but the read will still go through 
address_space_rw which will eventually invoke address_space_read.

Also when user tries to read or write to a physical address through qemu 
monitor then it will invoke cpu_physical_memory_rw which will eventually 
use address_space_write and address_space_read to read/write the guest 
memory.

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 22:06             ` Brijesh Singh
@ 2016-09-14 22:17               ` Paolo Bonzini
  2016-09-14 22:26                 ` Brijesh Singh
  2016-09-15 14:13                 ` Brijesh Singh
  0 siblings, 2 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-14 22:17 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 15/09/2016 00:06, Brijesh Singh wrote:
> 
> here is what I see:
> 
> int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>                         uint8_t *buf, int len, int is_write)
> {
>   ............
> 
>    if (is_write)
>        cpu_physical_memory_write_rom_internal()
>     else
>        address_space_rw()
> 
>    .....
> 
> }
> 
> So looking at code, i have impression that write will go through the
> cpu_physical_memory_write_rom but the read will still go through
> address_space_rw which will eventually invoke address_space_read.

Yes, you'd have to modify it a bit.  Something like

diff --git a/exec.c b/exec.c
index c8389f9..9fc9cef 100644
--- a/exec.c
+++ b/exec.c
@@ -2689,7 +2689,7 @@ enum write_rom_type {
     FLUSH_CACHE,
 };
 
-static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
+static inline void cpu_physical_memory_rw_debug_internal(AddressSpace *as,
     hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
 {
     hwaddr l;
@@ -2705,12 +2705,24 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
         if (!(memory_region_is_ram(mr) ||
               memory_region_is_romd(mr))) {
             l = memory_access_size(mr, l, addr1);
+            /* Pass MMIO down to address_space_rw.  */
+            switch (type) {
+            case READ_DATA:
+            case WRITE_DATA:
+                /* ... set debug in attrs (not necessary anymore perhaps?) */
+                address_space_rw(as, addr, attrs, buf, l, type == WRITE_DATA);
+                break;
+            case FLUSH_CACHE:
+                break;
+            }
         } else {
             /* ROM/RAM case */
             ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
             switch (type) {
+            case READ_DATA:
+                /* ... call hook ... */
             case WRITE_DATA:
-                memcpy(ptr, buf, l);
+                /* ... call hook ... */
                 invalidate_and_set_dirty(mr, addr1, l);
                 break;
             case FLUSH_CACHE:
@@ -2729,7 +2739,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
 void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
                                    const uint8_t *buf, int len)
 {
-    cpu_physical_memory_write_rom_internal(as, addr, buf, len, WRITE_DATA);
+    cpu_physical_memory_rw_debug_internal(as, addr, buf, len, WRITE_DATA);
 }
 
 void cpu_flush_icache_range(hwaddr start, int len)
@@ -2744,8 +2754,8 @@ void cpu_flush_icache_range(hwaddr start, int len)
         return;
     }
 
-    cpu_physical_memory_write_rom_internal(&address_space_memory,
-                                           start, NULL, len, FLUSH_CACHE);
+    cpu_physical_memory_rw_debug_internal(&address_space_memory,
+                                          start, NULL, len, FLUSH_CACHE);
 }
 
 typedef struct {
@@ -3568,6 +3578,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
     int l;
     hwaddr phys_addr;
     target_ulong page;
+    int mode = is_write ? WRITE_DATA : READ_DATA;
 
     while (len > 0) {
         int asidx;
@@ -3583,14 +3594,9 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
         if (l > len)
             l = len;
         phys_addr += (addr & ~TARGET_PAGE_MASK);
-        if (is_write) {
-            cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
-                                          phys_addr, buf, l);
-        } else {
-            address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
-                             MEMTXATTRS_UNSPECIFIED,
-                             buf, l, 0);
-        }
+        cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
+                                              phys_addr, buf, l,
+                                              mode);
         len -= l;
         buf += l;
         addr += l;

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 22:17               ` Paolo Bonzini
@ 2016-09-14 22:26                 ` Brijesh Singh
  2016-09-15 14:13                 ` Brijesh Singh
  1 sibling, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-14 22:26 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh

>> So looking at code, i have impression that write will go through the
>> cpu_physical_memory_write_rom but the read will still go through
>> address_space_rw which will eventually invoke address_space_read.
>
> Yes, you'd have to modify it a bit.  Something like
>

Sure this will works, thanks for the snippet.

> diff --git a/exec.c b/exec.c
> index c8389f9..9fc9cef 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2689,7 +2689,7 @@ enum write_rom_type {
>      FLUSH_CACHE,
>  };
>
> -static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
> +static inline void cpu_physical_memory_rw_debug_internal(AddressSpace *as,
>      hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
>  {
>      hwaddr l;
> @@ -2705,12 +2705,24 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
>          if (!(memory_region_is_ram(mr) ||
>                memory_region_is_romd(mr))) {
>              l = memory_access_size(mr, l, addr1);
> +            /* Pass MMIO down to address_space_rw.  */
> +            switch (type) {
> +            case READ_DATA:
> +            case WRITE_DATA:
> +                /* ... set debug in attrs (not necessary anymore perhaps?) */
> +                address_space_rw(as, addr, attrs, buf, l, type == WRITE_DATA);
> +                break;
> +            case FLUSH_CACHE:
> +                break;
> +            }
>          } else {
>              /* ROM/RAM case */
>              ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>              switch (type) {
> +            case READ_DATA:
> +                /* ... call hook ... */
>              case WRITE_DATA:
> -                memcpy(ptr, buf, l);
> +                /* ... call hook ... */
>                  invalidate_and_set_dirty(mr, addr1, l);
>                  break;
>              case FLUSH_CACHE:
> @@ -2729,7 +2739,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
>  void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>                                     const uint8_t *buf, int len)
>  {
> -    cpu_physical_memory_write_rom_internal(as, addr, buf, len, WRITE_DATA);
> +    cpu_physical_memory_rw_debug_internal(as, addr, buf, len, WRITE_DATA);
>  }
>
>  void cpu_flush_icache_range(hwaddr start, int len)
> @@ -2744,8 +2754,8 @@ void cpu_flush_icache_range(hwaddr start, int len)
>          return;
>      }
>
> -    cpu_physical_memory_write_rom_internal(&address_space_memory,
> -                                           start, NULL, len, FLUSH_CACHE);
> +    cpu_physical_memory_rw_debug_internal(&address_space_memory,
> +                                          start, NULL, len, FLUSH_CACHE);
>  }
>
>  typedef struct {
> @@ -3568,6 +3578,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>      int l;
>      hwaddr phys_addr;
>      target_ulong page;
> +    int mode = is_write ? WRITE_DATA : READ_DATA;
>
>      while (len > 0) {
>          int asidx;
> @@ -3583,14 +3594,9 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>          if (l > len)
>              l = len;
>          phys_addr += (addr & ~TARGET_PAGE_MASK);
> -        if (is_write) {
> -            cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
> -                                          phys_addr, buf, l);
> -        } else {
> -            address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
> -                             MEMTXATTRS_UNSPECIFIED,
> -                             buf, l, 0);
> -        }
> +        cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
> +                                              phys_addr, buf, l,
> +                                              mode);
>          len -= l;
>          buf += l;
>          addr += l;
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status
  2016-09-14 16:16     ` Brijesh Singh
@ 2016-09-15  4:13       ` Michael S. Tsirkin
  0 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-15  4:13 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Eric Blake, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

On Wed, Sep 14, 2016 at 11:16:12AM -0500, Brijesh Singh wrote:
> Hi Eric,
> 
> Thanks for feedback.
> 
> > >  # @present: true if KVM acceleration is built into this executable
> > >  #
> > > +# @sev: true if SEV is active
> > 
> > Worth expanding what the acronym stands for.  Also needs a '(since 2.8)'
> > designator.
> > 
> will fix in v2.
> 
> > > +#
> > >  # Since: 0.14.0
> > >  ##
> > > -{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
> > > +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool', 'sev' : 'bool'} }
> > 
> > Long line; please wrap to keep it under 80 columns.
> > 
> will fix in v2.

So memory-encryption : bool
Etc everywhere.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-14 22:17               ` Paolo Bonzini
  2016-09-14 22:26                 ` Brijesh Singh
@ 2016-09-15 14:13                 ` Brijesh Singh
  2016-09-15 15:19                   ` Paolo Bonzini
  1 sibling, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-15 14:13 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh

Hi Paolo,


>  typedef struct {
> @@ -3568,6 +3578,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>      int l;
>      hwaddr phys_addr;
>      target_ulong page;
> +    int mode = is_write ? WRITE_DATA : READ_DATA;
>
>      while (len > 0) {
>          int asidx;
> @@ -3583,14 +3594,9 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>          if (l > len)
>              l = len;
>          phys_addr += (addr & ~TARGET_PAGE_MASK);
> -        if (is_write) {
> -            cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
> -                                          phys_addr, buf, l);
> -        } else {
> -            address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
> -                             MEMTXATTRS_UNSPECIFIED,
> -                             buf, l, 0);
> -        }
> +        cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
> +                                              phys_addr, buf, l,
> +                                              mode);
>          len -= l;
>          buf += l;
>          addr += l;
>

How do you want me to handle passing debug attrs (MEMTXATTRS_DEBUG) when 
doing a page walk to locate the physical page for a given virtual address.

I see something like this happen when we read virtual address from gdb 
or monitor commands.

cpu_memory_rw_debug
   cpu_get_phys_page_attrs_debug
       x86_cpu_get_phys_page_debug
         x86_ldq_phys
           attr = get_mem_debug_attrs
           address_space_ldq

get_mem_debug_attrs, does not set the MAXATTRS_DEBUG so we end up doing 
a memcpy instead of SEV debug read's. I was thinking about these two 
simple solution

1) something like this

diff --git a/target-i386/helper.c b/target-i386/helper.c
index a9d8aef..6322265 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1379,13 +1379,22 @@ void x86_cpu_exec_exit(CPUState *cs)
  }

  #ifndef CONFIG_USER_ONLY
+static inline MemTxAttrs get_mem_debug_attrs(CPUX86State *env)
+{
+    MemTxAttrs attrs = cpu_get_mem_attrs(env);
+
+    attrs.debug = MEMTXATTRS_DEBUG;
+
+    return attrs;
+}
+
  uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
  {
      X86CPU *cpu = X86_CPU(cs);
      CPUX86State *env = &cpu->env;

      return address_space_ldub(cs->as, addr,
-                              cpu_get_mem_attrs(env),
+                              get_mem_debug_attrs(env),
                                NULL);
  }

@@ -1395,7 +1404,7 @@ uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
      CPUX86State *env = &cpu->env;

      return address_space_lduw(cs->as, addr,
-                              cpu_get_mem_attrs(env),
+                              get_mem_debug_attrs(env),
                                NULL);
  }



2) or implement and register a x86_cpu_get_phys_page_attrs_debug which 
takes care of setting the debug attribute before calling into 
address_space_ldq.

Please let me know your thought.

- Brijesh

^ permalink raw reply related	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command
  2016-09-14 22:05                             ` Michael S. Tsirkin
@ 2016-09-15 14:58                               ` Eduardo Habkost
  0 siblings, 0 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-15 14:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Daniel P. Berrange, Paolo Bonzini, Brijesh Singh,
	crosthwaite.peter, p.fedin, qemu-devel, armbru, lcapitulino, rth

On Thu, Sep 15, 2016 at 01:05:12AM +0300, Michael S. Tsirkin wrote:
[...]
> > > Attestation seems mostly unrelated. The whitepaper says
> > > 	With this attestation, a guest owner can ensure that the hypervisor did
> > > 	not interfere with the initialization of SEV before transmitting
> > > 	confidential information to the guest.
> > > which seems to imply an active attacker that is able to interfere
> > > with the hypervisor during guest initialization but not afterwards.
> > 
> > I believe this assumes a compromised hypervisor both before and
> > after guest launch, but this assumes the hypervisor:
> > 1) Won't be able to change guest memory before attestation
> >    without being detected.
> > 2) Won't be able to attack the guest after memory is encrypted.
> 
> Why would you need to measure things then?  If you assume this, at what
> point *can* attacker change memory?

I am assuming an attacker that can change memory at any moment.
If memory is changed before encryption, measurement/attestation
would detect it. And I assume that memory changes after
encryption won't cause much damage except crashing the guest.

> 
> > > So I have no idea why that's useful at the moment - I suspect
> > > it's part of the future vision when there are protections
> > > against all active attackers in place, but for now it seems to extend the
> > > firmware/software interface unnecessarily.
> > 
> > "Protection against all active attackers" is a very broad
> > requirement. Effective protection against a given subset of
> > attacks would be reasonable enough to me.
> 
> Well selecting a random point in time and saying "I protect against
> attacks at this point only" would be a very weak protection, akin to
> just adding an assert statement at a random place in code - even though
> yes, if you hit that assert you are protected.
> 
> This is not to say this is what this patchset does, merely
> that it should include a bit more information about the
> motivation for the measurement part than
> "this is what we can easily implement".

Agreed that we need more information about the attacks they have
in mind.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region
  2016-09-15 14:13                 ` Brijesh Singh
@ 2016-09-15 15:19                   ` Paolo Bonzini
  0 siblings, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-15 15:19 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 15/09/2016 16:13, Brijesh Singh wrote:
> 1) something like this
> 
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index a9d8aef..6322265 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -1379,13 +1379,22 @@ void x86_cpu_exec_exit(CPUState *cs)
>  }
> 
>  #ifndef CONFIG_USER_ONLY
> +static inline MemTxAttrs get_mem_debug_attrs(CPUX86State *env)
> +{
> +    MemTxAttrs attrs = cpu_get_mem_attrs(env);
> +
> +    attrs.debug = MEMTXATTRS_DEBUG;
> +
> +    return attrs;
> +}
> +
>  uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
>  {
>      X86CPU *cpu = X86_CPU(cs);
>      CPUX86State *env = &cpu->env;
> 
>      return address_space_ldub(cs->as, addr,
> -                              cpu_get_mem_attrs(env),
> +                              get_mem_debug_attrs(env),
>                                NULL);
>  }

This changes the semantics of x86_ld*_phys so it's not acceptable.

You need new exec.c functions that wrap
cpu_physical_memory_rw_debug_internal so that they end up calling your
hooks.  Like this:

x86_cpu_get_phys_page_debug
  -> calls ldl_phys_debug
      -> calls cpu_physical_memory_rw_debug_internal

uint32_t ldl_phys_debug(CPUState *cs, hwaddr addr)
{
    /* This really should be a little more complex to support
     * SMRAM, but this is enough for now.  I'll provide you with a
     * diff when you post v2.
     */
    MemTxAttrs attrs = { .debug = 1 };
    int asidx = cpu_asidx_from_attrs(cpu, attrs);
    uint32_t val;

    cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
                                          addr, (void *) &val,
                                          4, READ_DATA);
    return tswap32(val);
}

/* and the same for ldq_phys_debug */

These two new functions can replace x86_ld*_phys in
x86_cpu_get_phys_page_debug.

Technically I'm not even sure you need the new .debug attribute now that
the hooks are never called by the device emulation DMA path.  Still,
asserting something like assert(attrs->debug || sev_info.state ==
SEV_LAUNCH_START) in your hooks is probably a good idea.  Even if you
only need the new attribute for that assertion, keep it.  It's just a
couple lines of code.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest
  2016-09-13 18:37   ` [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest Michael S. Tsirkin
@ 2016-09-21 15:55     ` Brijesh Singh
  2016-09-21 15:58       ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-21 15:55 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: brijesh.singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, pbonzini, rth

Hi Michael and Paolo,

On 09/13/2016 01:37 PM, Michael S. Tsirkin wrote:
> On Tue, Sep 13, 2016 at 10:49:29AM -0400, Brijesh Singh wrote:
>> Typically linux kernel, initrd and cmdline are build and loaded
>> into guest memory through linux optionrom. The linux optionrom is
>> probed and executed by SeaBIOS. This method will not work for
>> SEV-enabled guest.
>>
>> In SEV-enabled guest all the code and data must be copied using SEV
>> launch command prior to starting the guest (i.e before first vmrun).
>> The data copied using SEV launch command will be encrypted using guest
>> owner's key. This patch loads kernel, initrd and cmdline blobs at fixed
>> location into guest memory and builds etc/sev_cfg config file. The cfg
>> file provide the below structure
>>
>> struct sev_cfg {
>> 	u32 kernel_addr, initrd_addr, cmdline_addr;
>> 	u32 kernel_size, initrd_size, cmdline_size;
>> }
>>
>> The config file can be used by SeaBIOS to locate OS images into guest
>> RAM and build linux boot entry code.
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>
> I don't think we want to give users this kind of
> control over how we manage memory internally
> for what is essentially a debugging feature at this point.
>
> Isn't there a way to first launch guest, and then have it
> encrypt itself once it's running?
>
> If not, I guess it's not too bad if -kernel does not
> work with sev debug feature - just load kernel from disk.
>

I'm working on v2 and getting ready for another review but not sure how 
to address this feedback. For now, I can drop this patch from the series 
and get other patches reviewed. But I would like to get some direction 
on how do I go about adding -kernel support for SEV guest.

Looking through -kernel option code, I see that qemu uses optionrom 
(linuxboot.bin or linuxboot_dma.bin) to load kernel specified through 
-kernel option.

- linuxboot optionrom uses "rep ins" instruction to fetch the kernel and 
initrd images into guest memory. SEV does not support string I/O, so 
this method will not work for SEV. But we can consider unrolling the 
string I/O operation into a loop, something similar to this KVM patch [1].

- linuxboot_dma - as name suggests it uses DMA. On SEV guest DMA should 
to be done on shared pages and since SeaBIOS runs into non-PAE mode 
hence it will not able to create a shared pages for this to work.

please let me know your thoughts on the following approaches:

- update linuxboot.S to unroll the string I/O instruction into a loop 
for SEV guest. This may work but the boot will be very slow, fetching 
kernel and initrd via 'inb' will increase the boot time significantly.

or

- Create a SEV specific linuxboot rom. The ROM will use a special port 
to communicate kernel and initrd load address to qemu. In qemu when we 
see the request on special port we map the pre-encrypted kernel and 
initrd at the requested location. This maybe similar to linuxboot_dma 
with exception that instead of copying the data into guest memory we 
somehow map the pre-encrypted image. I have not looked into much detail 
and not sure if we can do something like this. If possible then this 
seems like a bit better approach.


[1] http://marc.info/?l=kvm&m=147191048324519&w=2

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest
  2016-09-21 15:55     ` Brijesh Singh
@ 2016-09-21 15:58       ` Paolo Bonzini
  2016-09-21 16:08         ` Brijesh Singh
  0 siblings, 1 reply; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-21 15:58 UTC (permalink / raw)
  To: Brijesh Singh, Michael S. Tsirkin
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, rth



On 21/09/2016 17:55, Brijesh Singh wrote:
> I'm working on v2 and getting ready for another review but not sure how
> to address this feedback. For now, I can drop this patch from the series
> and get other patches reviewed. But I would like to get some direction
> on how do I go about adding -kernel support for SEV guest.

Don't.  The solution is to use UEFI, which runs in 64-bit mode and can
do DMA to shared pages.

Paolo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest
  2016-09-21 15:58       ` Paolo Bonzini
@ 2016-09-21 16:08         ` Brijesh Singh
  2016-09-21 16:17           ` Paolo Bonzini
  0 siblings, 1 reply; 125+ messages in thread
From: Brijesh Singh @ 2016-09-21 16:08 UTC (permalink / raw)
  To: Paolo Bonzini, Michael S. Tsirkin
  Cc: brijesh.singh, ehabkost, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

Hi Paolo,

On 09/21/2016 10:58 AM, Paolo Bonzini wrote:
>
>
> On 21/09/2016 17:55, Brijesh Singh wrote:
>> I'm working on v2 and getting ready for another review but not sure how
>> to address this feedback. For now, I can drop this patch from the series
>> and get other patches reviewed. But I would like to get some direction
>> on how do I go about adding -kernel support for SEV guest.
>
> Don't.  The solution is to use UEFI, which runs in 64-bit mode and can
> do DMA to shared pages.
>

Thanks.

I will explore UEFI BIOS path. Just for confirmation you mean the OVMF 
project [1] right ?

[1] http://www.linux-kvm.org/page/OVMF
https://github.com/tianocore/tianocore.github.io/wiki/How-to-run-OVMF


> Paolo
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest
  2016-09-21 16:08         ` Brijesh Singh
@ 2016-09-21 16:17           ` Paolo Bonzini
  0 siblings, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-21 16:17 UTC (permalink / raw)
  To: Brijesh Singh, Michael S. Tsirkin
  Cc: ehabkost, crosthwaite.peter, armbru, p.fedin, qemu-devel,
	lcapitulino, rth



On 21/09/2016 18:08, Brijesh Singh wrote:
> Hi Paolo,
> 
> On 09/21/2016 10:58 AM, Paolo Bonzini wrote:
>>
>>
>> On 21/09/2016 17:55, Brijesh Singh wrote:
>>> I'm working on v2 and getting ready for another review but not sure how
>>> to address this feedback. For now, I can drop this patch from the series
>>> and get other patches reviewed. But I would like to get some direction
>>> on how do I go about adding -kernel support for SEV guest.
>>
>> Don't.  The solution is to use UEFI, which runs in 64-bit mode and can
>> do DMA to shared pages.
>>
> 
> Thanks.
> 
> I will explore UEFI BIOS path. Just for confirmation you mean the OVMF
> project [1] right ?

Yes.

Paolo

> [1] http://www.linux-kvm.org/page/OVMF
> https://github.com/tianocore/tianocore.github.io/wiki/How-to-run-OVMF
> 
> 
>> Paolo
>>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f
  2016-09-13 23:07   ` Paolo Bonzini
@ 2016-09-21 16:20     ` Brijesh Singh
  2016-09-21 16:24       ` Paolo Bonzini
  2016-09-21 18:21       ` Eduardo Habkost
  0 siblings, 2 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-21 16:20 UTC (permalink / raw)
  To: Paolo Bonzini, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth
  Cc: brijesh.singh

Hi Paolo,

On 09/13/2016 06:07 PM, Paolo Bonzini wrote:
>
>
> On 13/09/2016 16:49, Brijesh Singh wrote:
>> Fn8000_001f cpuid provides the memory encryption (aka C-bit)
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  target-i386/cpu.c |    3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
>> index 6a1afab..e039c08 100644
>> --- a/target-i386/cpu.c
>> +++ b/target-i386/cpu.c
>> @@ -2625,6 +2625,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>>              *edx = 0;
>>          }
>>          break;
>> +    case 0x8000001F:
>> +        host_cpuid(index, 0, eax, ebx, ecx, edx);
>> +        break;
>>      case 0xC0000000:
>>          *eax = env->cpuid_xlevel2;
>>          *ebx = 0;
>>
>>
>>
>
> This should only be visible to a SEV-enabled guest.  Also, the xlevel
> should be bumped to 0x8000001F for SEV-enabled guests.
>

Okay I will add sev_enabled() check before getting the cpuid.

Regarding xlevel, I am not able to locate qemu code which bumped the 
xelevel for KVM enabled guests. Maybe I am missing something, looking at 
code gave me impression that xlevel is obtained using CPUID_80000000. 
One of the KVM RFC patch [1] updates the min level. Do I need to do 
something more into qemu to bumped the xlevel?

http://marc.info/?l=linux-mm&m=147190934724195&w=2

> Paolo
>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f
  2016-09-21 16:20     ` Brijesh Singh
@ 2016-09-21 16:24       ` Paolo Bonzini
  2016-09-21 18:21       ` Eduardo Habkost
  1 sibling, 0 replies; 125+ messages in thread
From: Paolo Bonzini @ 2016-09-21 16:24 UTC (permalink / raw)
  To: Brijesh Singh, ehabkost, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth



On 21/09/2016 18:20, Brijesh Singh wrote:
> Hi Paolo,
> 
> On 09/13/2016 06:07 PM, Paolo Bonzini wrote:
>>
>>
>> On 13/09/2016 16:49, Brijesh Singh wrote:
>>> Fn8000_001f cpuid provides the memory encryption (aka C-bit)
>>>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>>  target-i386/cpu.c |    3 +++
>>>  1 file changed, 3 insertions(+)
>>>
>>> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
>>> index 6a1afab..e039c08 100644
>>> --- a/target-i386/cpu.c
>>> +++ b/target-i386/cpu.c
>>> @@ -2625,6 +2625,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t
>>> index, uint32_t count,
>>>              *edx = 0;
>>>          }
>>>          break;
>>> +    case 0x8000001F:
>>> +        host_cpuid(index, 0, eax, ebx, ecx, edx);
>>> +        break;
>>>      case 0xC0000000:
>>>          *eax = env->cpuid_xlevel2;
>>>          *ebx = 0;
>>>
>>>
>>>
>>
>> This should only be visible to a SEV-enabled guest.  Also, the xlevel
>> should be bumped to 0x8000001F for SEV-enabled guests.
>>
> 
> Okay I will add sev_enabled() check before getting the cpuid.
> 
> Regarding xlevel, I am not able to locate qemu code which bumped the
> xelevel for KVM enabled guests. Maybe I am missing something, looking at
> code gave me impression that xlevel is obtained using CPUID_80000000.
> One of the KVM RFC patch [1] updates the min level.

That patch makes sure that entry->eax is _at most_ 0x8000001f.  Here you
want to make sure that CPUID[0x80000000].EAX == 0x8000001f for SEV guests.

I think you need to change x86_cpu_load_def:

    object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);

if SEV is enabled, use max(0x8000001f, def->xlevel) instead of def->xlevel.

Paolo
 Do I need to do
> something more into qemu to bumped the xlevel?
> 
> http://marc.info/?l=linux-mm&m=147190934724195&w=2
> 
>> Paolo
>>

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Message-ID: <20160921205731-mutt-send-email-mst@kernel.org>
  2016-09-14  8:58       ` Paolo Bonzini
@ 2016-09-21 18:00         ` Michael S. Tsirkin
  0 siblings, 0 replies; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-21 18:00 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Brijesh Singh, ehabkost, crosthwaite.peter, p.fedin, qemu-devel,
	armbru, lcapitulino, rth

On Wed, Sep 14, 2016 at 10:58:08AM +0200, Paolo Bonzini wrote:
> 
> 
> On 14/09/2016 04:33, Michael S. Tsirkin wrote:
> > Frankly I don't understand why do you need to mess with boot at all.
> > Quoting the cover letter:
> > 
> > 	SEV is designed to protect guest VMs from a benign but vulnerable
> > 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> > 	attack
> > 	surface of guest VMs and can prevent certain types of VM-escape bugs
> > 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> > 
> > it seems highly unlikely that any secret data is used during boot.
> > So just let guest boot normally, and encrypt afterwards.
> > 
> > Even assuming there are some guests that have secret data during boot,
> > I would first upstream the main part of the feature for normal guests,
> > then weight the extra security if any against the features and
> > performance lost (like slower boot times).
> 
> If you can't trust boot, any encryption done afterwards is totally
> pointless.
> 
> Paolo

You trust hypervisor anyway, it's all mitigation, being about making
attacks harder, isn't it?  So if the attack has to happen in the window
when guest boots within BIOS, that might be good enough.  Or just don't
boot in the cloud, move guest there after boot.

-- 
MST

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-14 12:09       ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Eduardo Habkost
  2016-09-14 13:01         ` Paolo Bonzini
@ 2016-09-21 18:03         ` Michael S. Tsirkin
  2016-09-21 18:19           ` Brijesh Singh
  1 sibling, 1 reply; 125+ messages in thread
From: Michael S. Tsirkin @ 2016-09-21 18:03 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paolo Bonzini, Brijesh Singh, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 14, 2016 at 09:09:43AM -0300, Eduardo Habkost wrote:
> On Wed, Sep 14, 2016 at 05:33:09AM +0300, Michael S. Tsirkin wrote:
> > On Wed, Sep 14, 2016 at 12:53:36AM +0200, Paolo Bonzini wrote:
> > > 
> > > 
> > > On 13/09/2016 16:50, Brijesh Singh wrote:
> > > > In SEV-enabled guest dma should be performed on shared pages. Since
> > > > the SeaBIOS executes in non PAE mode and does not have access to C-bit
> > > > to create a shared page hence disable the dma operation when reading
> > > > from fw_cfg interface.
> > > > 
> > > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > > > ---
> > > >  hw/nvram/fw_cfg.c |    6 ++++++
> > > >  1 file changed, 6 insertions(+)
> > > > 
> > > > diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> > > > index 6a68e59..aca99e9 100644
> > > > --- a/hw/nvram/fw_cfg.c
> > > > +++ b/hw/nvram/fw_cfg.c
> > > > @@ -24,6 +24,7 @@
> > > >  #include "qemu/osdep.h"
> > > >  #include "hw/hw.h"
> > > >  #include "sysemu/sysemu.h"
> > > > +#include "sysemu/kvm.h"
> > > >  #include "sysemu/dma.h"
> > > >  #include "hw/boards.h"
> > > >  #include "hw/isa/isa.h"
> > > > @@ -1009,6 +1010,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> > > >      FWCfgIoState *s = FW_CFG_IO(dev);
> > > >      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > > >  
> > > > +    /* disable dma on fw_cfg when SEV is enabled */
> > > > +    if (kvm_sev_enabled()) {
> > > > +        qdev_prop_set_bit(dev, "dma_enabled", false);
> > > > +    }
> > > > +
> > > >      /* when using port i/o, the 8-bit data register ALWAYS overlaps
> > > >       * with half of the 16-bit control register. Hence, the total size
> > > >       * of the i/o region used is FW_CFG_CTL_SIZE */
> > > > 
> > > > 
> > > > 
> > > 
> > > As Michael said, a workaround is possible using -global.  However, I
> > > really think that SEV should be implemented in UEFI firmware.  Because
> > > it runs in 64-bit mode, it would be able to run in paged mode and it
> > > would not have to encrypt everything before the SEV launch command.
> > > 
> > > For example secure boot can be used to authenticate the kernel against
> > > keys provided by the owner in encrypted flash, or GRUB2 can be placed in
> > > the firmware by the owner and used to boot from a LUKS-encrypted /boot
> > > partition.
> > > 
> > > Paolo
> > 
> > Frankly I don't understand why do you need to mess with boot at all.
> > Quoting the cover letter:
> > 
> > 	SEV is designed to protect guest VMs from a benign but vulnerable
> > 	(i.e. not fully malicious) hypervisor. In particular, it reduces the
> > 	attack
> > 	surface of guest VMs and can prevent certain types of VM-escape bugs
> > 	(e.g. hypervisor read-anywhere) from being used to steal guest data.
> > 
> > it seems highly unlikely that any secret data is used during boot.
> > So just let guest boot normally, and encrypt afterwards.
> 
> After boot seems too late for the attestation part (see Section
> 1.3.1: Launch in the spec), unless you can ensure the memory
> contents will always be exactly what the guest owner expects
> after every boot.

Again it isn't clear how much value does attestation have,
we are assuming arbitrary restrictions on the attacker such
as inability to trigger exits at random times, why not
assume it can't attack guest during boot?
IOW it seems reasonable to just ignore the need for attestation
completely as the first step.
Get the other stuff merged first.

> -- 
> Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode
  2016-09-21 18:03         ` Michael S. Tsirkin
@ 2016-09-21 18:19           ` Brijesh Singh
  0 siblings, 0 replies; 125+ messages in thread
From: Brijesh Singh @ 2016-09-21 18:19 UTC (permalink / raw)
  To: Michael S. Tsirkin, Eduardo Habkost
  Cc: brijesh.singh, Paolo Bonzini, crosthwaite.peter, armbru, p.fedin,
	qemu-devel, lcapitulino, rth

Hi Michael,

>
> Again it isn't clear how much value does attestation have,
> we are assuming arbitrary restrictions on the attacker such
> as inability to trigger exits at random times, why not
> assume it can't attack guest during boot?
> IOW it seems reasonable to just ignore the need for attestation
> completely as the first step.
> Get the other stuff merged first.
>

Thanks for feedbacks. In v2, I will try to remove the attestation code 
and we can revisit it later.

-Brijesh

^ permalink raw reply	[flat|nested] 125+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f
  2016-09-21 16:20     ` Brijesh Singh
  2016-09-21 16:24       ` Paolo Bonzini
@ 2016-09-21 18:21       ` Eduardo Habkost
  1 sibling, 0 replies; 125+ messages in thread
From: Eduardo Habkost @ 2016-09-21 18:21 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Paolo Bonzini, crosthwaite.peter, armbru, mst, p.fedin,
	qemu-devel, lcapitulino, rth

On Wed, Sep 21, 2016 at 11:20:59AM -0500, Brijesh Singh wrote:
> On 09/13/2016 06:07 PM, Paolo Bonzini wrote:
> > On 13/09/2016 16:49, Brijesh Singh wrote:
[...]
> > > +    case 0x8000001F:
> > > +        host_cpuid(index, 0, eax, ebx, ecx, edx);
> > > +        break;

Do we really need to expose the raw host CPUID values directly to
the guest? It will make it harder to support migration later.


> > >      case 0xC0000000:
> > >          *eax = env->cpuid_xlevel2;
> > >          *ebx = 0;
> > > 
> > > 
> > > 
> > 
> > This should only be visible to a SEV-enabled guest.  Also, the xlevel
> > should be bumped to 0x8000001F for SEV-enabled guests.
> > 
> 
> Okay I will add sev_enabled() check before getting the cpuid.
> 
> Regarding xlevel, I am not able to locate qemu code which bumped the xelevel
> for KVM enabled guests.

Because QEMU doesn't do that automatically (yet), except for
CPUID[7].EBX features.

> Maybe I am missing something, looking at code gave
> me impression that xlevel is obtained using CPUID_80000000. One of the KVM
> RFC patch [1] updates the min level. Do I need to do something more into
> qemu to bumped the xlevel?

I will send a series today that will increase level/xlevel
automatically depending on the features that are enabled. I will
add you to CC.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 125+ messages in thread

end of thread, other threads:[~2016-09-21 18:21 UTC | newest]

Thread overview: 125+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-13 14:46 [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2016-09-13 14:46 ` [Qemu-devel] [RFC PATCH v1 01/22] exec: add guest RAM read/write ops Brijesh Singh
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 02/22] cpu-common: add debug version of physical memory read/write Brijesh Singh
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 03/22] monitor: use debug version of physical memory read api Brijesh Singh
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 04/22] memattrs: add SEV debug attrs Brijesh Singh
2016-09-13 23:00   ` Paolo Bonzini
2016-09-14 20:30     ` Brijesh Singh
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 05/22] i386: add new option to enable SEV guest Brijesh Singh
2016-09-13 22:41   ` Paolo Bonzini
2016-09-14  8:41     ` Daniel P. Berrange
2016-09-14  9:11       ` Paolo Bonzini
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 06/22] sev: add initial SEV support Brijesh Singh
2016-09-13 15:58   ` Eduardo Habkost
2016-09-13 19:54     ` Brijesh Singh
2016-09-13 20:10       ` Michael S. Tsirkin
2016-09-13 22:00       ` Eduardo Habkost
2016-09-14  8:30         ` Daniel P. Berrange
2016-09-14 11:54           ` Eduardo Habkost
2016-09-14 11:58             ` Daniel P. Berrange
2016-09-14 16:10         ` Brijesh Singh
2016-09-14 16:13           ` Daniel P. Berrange
2016-09-14 16:20           ` Michael S. Tsirkin
2016-09-14 18:46             ` Brijesh Singh
2016-09-14 20:23               ` Michael S. Tsirkin
2016-09-14  8:37   ` Daniel P. Berrange
2016-09-13 14:47 ` [Qemu-devel] [RFC PATCH v1 07/22] sev: add SEV launch start command Brijesh Singh
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 08/22] sev: add SEV launch update command Brijesh Singh
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 09/22] sev: add SEV launch finish command Brijesh Singh
2016-09-13 22:15   ` Eduardo Habkost
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
2016-09-14  2:28   ` Michael S. Tsirkin
2016-09-14  8:57     ` Paolo Bonzini
2016-09-14 13:05       ` Michael S. Tsirkin
2016-09-14 13:07         ` Paolo Bonzini
2016-09-14 13:23           ` Daniel P. Berrange
2016-09-14 13:32             ` Michael S. Tsirkin
2016-09-14 13:37               ` Daniel P. Berrange
2016-09-14 13:50                 ` Michael S. Tsirkin
2016-09-14 14:08                   ` Eduardo Habkost
2016-09-14 14:14                     ` Paolo Bonzini
2016-09-14 14:38                       ` Michael S. Tsirkin
2016-09-14 15:17                     ` Michael S. Tsirkin
2016-09-14 14:15                   ` Daniel P. Berrange
2016-09-14 14:48                     ` Michael S. Tsirkin
2016-09-14 15:06                       ` Daniel P. Berrange
2016-09-14 15:46                         ` Michael S. Tsirkin
2016-09-14 17:35                           ` Eduardo Habkost
2016-09-14 22:05                             ` Michael S. Tsirkin
2016-09-15 14:58                               ` Eduardo Habkost
2016-09-14 13:27           ` [Qemu-devel] [PATCH v2] virtio_pci: Limit DMA mask to 44 bits for legacy virtio devices Michael S. Tsirkin
2016-09-14 13:36     ` [Qemu-devel] [RFC PATCH v1 10/22] sev: add SEV debug decrypt command Brijesh Singh
2016-09-14 13:48       ` Michael S. Tsirkin
2016-09-14 14:19         ` Paolo Bonzini
2016-09-14 15:02           ` Michael S. Tsirkin
2016-09-14 16:53             ` Paolo Bonzini
2016-09-14 18:15               ` Michael S. Tsirkin
2016-09-14 18:45                 ` Paolo Bonzini
2016-09-14 19:24                   ` Michael S. Tsirkin
2016-09-14 19:58                     ` Paolo Bonzini
2016-09-14 20:36                       ` Michael S. Tsirkin
2016-09-14 20:44                         ` Paolo Bonzini
2016-09-14 21:25                           ` Brijesh Singh
2016-09-14 21:38                           ` Michael S. Tsirkin
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 11/22] sev: add SEV debug encrypt command Brijesh Singh
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 12/22] sev: add SEV guest status command Brijesh Singh
2016-09-13 14:48 ` [Qemu-devel] [RFC PATCH v1 13/22] hmp: update 'info kvm' to display SEV status Brijesh Singh
2016-09-13 16:09   ` Eric Blake
2016-09-14 16:16     ` Brijesh Singh
2016-09-15  4:13       ` Michael S. Tsirkin
2016-09-13 23:01   ` Paolo Bonzini
2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 14/22] sev: provide SEV-enabled guest RAM read/write ops Brijesh Singh
2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region Brijesh Singh
2016-09-13 23:05   ` Paolo Bonzini
2016-09-14 20:59     ` Brijesh Singh
2016-09-14 21:00       ` Paolo Bonzini
2016-09-14 21:47         ` Brijesh Singh
2016-09-14 21:52           ` Paolo Bonzini
2016-09-14 22:06             ` Brijesh Singh
2016-09-14 22:17               ` Paolo Bonzini
2016-09-14 22:26                 ` Brijesh Singh
2016-09-15 14:13                 ` Brijesh Singh
2016-09-15 15:19                   ` Paolo Bonzini
2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 17/22] target-i386: add cpuid Fn8000_001f Brijesh Singh
2016-09-13 23:07   ` Paolo Bonzini
2016-09-21 16:20     ` Brijesh Singh
2016-09-21 16:24       ` Paolo Bonzini
2016-09-21 18:21       ` Eduardo Habkost
2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 18/22] i386: clear C-bit in SEV guest page table walk Brijesh Singh
2016-09-13 14:49 ` [Qemu-devel] [RFC PATCH v1 19/22] exec: set debug attribute in SEV-enabled guest Brijesh Singh
2016-09-13 23:06   ` Paolo Bonzini
2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Brijesh Singh
2016-09-13 18:39   ` Michael S. Tsirkin
2016-09-13 20:46     ` Brijesh Singh
2016-09-13 20:55       ` Michael S. Tsirkin
2016-09-13 22:53   ` Paolo Bonzini
2016-09-14  2:33     ` Michael S. Tsirkin
2016-09-14  8:58       ` Paolo Bonzini
2016-09-21 18:00         ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Message-ID: <20160921205731-mutt-send-email-mst@kernel.org> Michael S. Tsirkin
2016-09-14 12:09       ` [Qemu-devel] [RFC PATCH v1 20/22] fw_cfg: sev: disable dma in real mode Eduardo Habkost
2016-09-14 13:01         ` Paolo Bonzini
2016-09-14 13:14           ` Michael S. Tsirkin
2016-09-14 13:51             ` Eduardo Habkost
2016-09-14 16:10               ` Michael S. Tsirkin
2016-09-14 17:25                 ` Eduardo Habkost
2016-09-21 18:03         ` Michael S. Tsirkin
2016-09-21 18:19           ` Brijesh Singh
2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 21/22] hw: add pre and post system reset callback Brijesh Singh
2016-09-13 22:47   ` Paolo Bonzini
2016-09-14 16:19     ` Brijesh Singh
2016-09-13 14:50 ` [Qemu-devel] [RFC PATCH v1 22/22] loader: reload bios image on ROM reset in SEV-enabled guest Brijesh Singh
2016-09-13 18:47   ` Michael S. Tsirkin
2016-09-13 22:59   ` Paolo Bonzini
2016-09-14  2:38     ` Michael S. Tsirkin
2016-09-14 20:29     ` Brijesh Singh
2016-09-14 20:38       ` Paolo Bonzini
2016-09-14 21:09         ` Michael S. Tsirkin
2016-09-14 21:11           ` Paolo Bonzini
2016-09-14 21:24         ` Brijesh Singh
2016-09-13 15:20 ` [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Eduardo Habkost
     [not found] ` <147377816978.11859.942423377333907417.stgit@brijesh-build-machine>
2016-09-13 18:37   ` [Qemu-devel] [RFC PATCH v1 16/22] i386: pc: load OS images at fixed location in SEV-enabled guest Michael S. Tsirkin
2016-09-21 15:55     ` Brijesh Singh
2016-09-21 15:58       ` Paolo Bonzini
2016-09-21 16:08         ` Brijesh Singh
2016-09-21 16:17           ` Paolo Bonzini
2016-09-14  2:55 ` [Qemu-devel] [RFC PATCH v1 00/22] x86: Secure Encrypted Virtualization (AMD) Michael S. Tsirkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.