All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/23] x86: Secure Encrypted Virtualization (AMD)
@ 2017-12-06 20:03 ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

This patch series provides support for AMD's new Secure Encrypted 
Virtualization (SEV) feature.

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.

The KVM SEV patch series [1] introduced a new ioctl (KVM_MEMORY_ENCRYPTION_OP)
which is used by qemu to issue the SEV commands to assist performing
common hypervisor activities such as a launching, running, snapshooting,
migration and debugging guests.

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_Specification.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] https://marc.info/?l=linux-kernel&m=151243663119420&w=2

Video of the KVM Forum Talk:
https://www.youtube.com/watch?v=RcvQ1xN55Ew

---

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

TODO:

* Add SEV guest migration support
* Add SEV guest snapshot and restore support

Changes since v4:
 - extend sev-guest object to add new properties 'dh-cert-file', 'session-file' etc.
 - emit SEV_MEASUREMENT event when measurement is available
 - add migration blocker
 - add memory encryption cpuid support
 - rebase the series with recent qemu tree

Changes since v3:
 - update to newer SEV spec (0.12 -> 0.14)
 - update to newer KVM RFC and use KVM_MEMORY_ENCRYPTION_OP ioctl instead
   of KVM_ISSUE_SEV.
 - add support to encrypt plfash

Changes since v2:
- rename ram_ops to ram_debug_ops
- use '-' rather than '_' when adding new member in KvmInfo struct
- update sev object to use link properties when referencing other objects
- use ldq_phys_debug in tlb_info_64 and mem_info_64.
- remove sev-guest-policy object, we will revisit it after basic SEV
  guest support is merged.
- remove kernel API from doc and add SEV guest LAUNCH model. The doc will
  be updated as we integerate the remaining SEV APIs.

Changes since v1:
- Added Documentation
- Added security-policy object.
- Drop sev config parsing support and create new objects to get/set SEV
  specific parameters
- Added sev-guest-info object.
- Added sev-launch-info object.
- Added kvm_memory_encrytion_* APIs. The idea behind this was to allow adding
  a non SEV memory encrytion object without modifying interfaces.
- Drop patch to load OS image at fixed location.
- updated LAUNCH_FINISH command structure. Now the structure contains
  just 'measurement' field. Other fields are not used and will also be removed
  from newer SEV firmware API spec.


Brijesh Singh (23):
  memattrs: add debug attribute
  exec: add ram_debug_ops support
  exec: add debug version of physical memory read and write API
  monitor/i386: use debug APIs when accessing guest memory
  target/i386: define memory encryption cpuid support
  machine: add -memory-encryption property
  kvm: update kvm.h to include memory encryption ioctls
  docs: add AMD Secure Encrypted Virtualization (SEV)
  accel: add Secure Encrypted Virtulization (SEV) object
  sev: add command to initialize the memory encryption context
  sev: register the guest memory range which may contain encrypted data
  kvm: introduce memory encryption APIs
  hmp: display memory encryption support in 'info kvm'
  sev: add command to create launch memory encryption context
  sev: add command to encrypt guest memory region
  target/i386: encrypt bios rom
  qapi: add SEV_MEASUREMENT event
  sev: emit the SEV_MEASUREMENT event
  sev: Finalize the SEV guest launch flow
  hw: i386: set ram_debug_ops when memory encryption is enabled
  sev: add debug encrypt and decrypt commands
  target/i386: clear C-bit when walking SEV guest page table
  sev: add migration blocker

 accel/kvm/Makefile.objs        |   2 +-
 accel/kvm/kvm-all.c            |  48 +++
 accel/kvm/sev.c                | 641 +++++++++++++++++++++++++++++++++++++++++
 accel/stubs/kvm-stub.c         |  14 +
 cpus.c                         |   2 +-
 disas.c                        |   2 +-
 docs/amd-memory-encryption.txt | 109 +++++++
 exec.c                         |  96 +++++-
 hmp.c                          |   2 +
 hw/core/machine.c              |  22 ++
 hw/i386/pc.c                   |   9 +
 hw/i386/pc_sysfw.c             |  19 ++
 include/exec/cpu-common.h      |  15 +
 include/exec/memattrs.h        |   4 +
 include/exec/memory.h          |  27 ++
 include/hw/boards.h            |   1 +
 include/sysemu/kvm.h           |  25 ++
 include/sysemu/sev.h           |  77 +++++
 linux-headers/linux/kvm.h      |  90 ++++++
 monitor.c                      |   2 +-
 qapi-schema.json               |  18 +-
 qemu-options.hx                |  36 +++
 qmp.c                          |   1 +
 target/i386/cpu.c              |  38 ++-
 target/i386/cpu.h              |   6 +
 target/i386/helper.c           |  46 ++-
 target/i386/monitor.c          | 145 ++++++----
 27 files changed, 1409 insertions(+), 88 deletions(-)
 create mode 100644 accel/kvm/sev.c
 create mode 100644 docs/amd-memory-encryption.txt
 create mode 100644 include/sysemu/sev.h

-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 00/23] x86: Secure Encrypted Virtualization (AMD)
@ 2017-12-06 20:03 ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

This patch series provides support for AMD's new Secure Encrypted 
Virtualization (SEV) feature.

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.

The KVM SEV patch series [1] introduced a new ioctl (KVM_MEMORY_ENCRYPTION_OP)
which is used by qemu to issue the SEV commands to assist performing
common hypervisor activities such as a launching, running, snapshooting,
migration and debugging guests.

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_Specification.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] https://marc.info/?l=linux-kernel&m=151243663119420&w=2

Video of the KVM Forum Talk:
https://www.youtube.com/watch?v=RcvQ1xN55Ew

---

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

TODO:

* Add SEV guest migration support
* Add SEV guest snapshot and restore support

Changes since v4:
 - extend sev-guest object to add new properties 'dh-cert-file', 'session-file' etc.
 - emit SEV_MEASUREMENT event when measurement is available
 - add migration blocker
 - add memory encryption cpuid support
 - rebase the series with recent qemu tree

Changes since v3:
 - update to newer SEV spec (0.12 -> 0.14)
 - update to newer KVM RFC and use KVM_MEMORY_ENCRYPTION_OP ioctl instead
   of KVM_ISSUE_SEV.
 - add support to encrypt plfash

Changes since v2:
- rename ram_ops to ram_debug_ops
- use '-' rather than '_' when adding new member in KvmInfo struct
- update sev object to use link properties when referencing other objects
- use ldq_phys_debug in tlb_info_64 and mem_info_64.
- remove sev-guest-policy object, we will revisit it after basic SEV
  guest support is merged.
- remove kernel API from doc and add SEV guest LAUNCH model. The doc will
  be updated as we integerate the remaining SEV APIs.

Changes since v1:
- Added Documentation
- Added security-policy object.
- Drop sev config parsing support and create new objects to get/set SEV
  specific parameters
- Added sev-guest-info object.
- Added sev-launch-info object.
- Added kvm_memory_encrytion_* APIs. The idea behind this was to allow adding
  a non SEV memory encrytion object without modifying interfaces.
- Drop patch to load OS image at fixed location.
- updated LAUNCH_FINISH command structure. Now the structure contains
  just 'measurement' field. Other fields are not used and will also be removed
  from newer SEV firmware API spec.


Brijesh Singh (23):
  memattrs: add debug attribute
  exec: add ram_debug_ops support
  exec: add debug version of physical memory read and write API
  monitor/i386: use debug APIs when accessing guest memory
  target/i386: define memory encryption cpuid support
  machine: add -memory-encryption property
  kvm: update kvm.h to include memory encryption ioctls
  docs: add AMD Secure Encrypted Virtualization (SEV)
  accel: add Secure Encrypted Virtulization (SEV) object
  sev: add command to initialize the memory encryption context
  sev: register the guest memory range which may contain encrypted data
  kvm: introduce memory encryption APIs
  hmp: display memory encryption support in 'info kvm'
  sev: add command to create launch memory encryption context
  sev: add command to encrypt guest memory region
  target/i386: encrypt bios rom
  qapi: add SEV_MEASUREMENT event
  sev: emit the SEV_MEASUREMENT event
  sev: Finalize the SEV guest launch flow
  hw: i386: set ram_debug_ops when memory encryption is enabled
  sev: add debug encrypt and decrypt commands
  target/i386: clear C-bit when walking SEV guest page table
  sev: add migration blocker

 accel/kvm/Makefile.objs        |   2 +-
 accel/kvm/kvm-all.c            |  48 +++
 accel/kvm/sev.c                | 641 +++++++++++++++++++++++++++++++++++++++++
 accel/stubs/kvm-stub.c         |  14 +
 cpus.c                         |   2 +-
 disas.c                        |   2 +-
 docs/amd-memory-encryption.txt | 109 +++++++
 exec.c                         |  96 +++++-
 hmp.c                          |   2 +
 hw/core/machine.c              |  22 ++
 hw/i386/pc.c                   |   9 +
 hw/i386/pc_sysfw.c             |  19 ++
 include/exec/cpu-common.h      |  15 +
 include/exec/memattrs.h        |   4 +
 include/exec/memory.h          |  27 ++
 include/hw/boards.h            |   1 +
 include/sysemu/kvm.h           |  25 ++
 include/sysemu/sev.h           |  77 +++++
 linux-headers/linux/kvm.h      |  90 ++++++
 monitor.c                      |   2 +-
 qapi-schema.json               |  18 +-
 qemu-options.hx                |  36 +++
 qmp.c                          |   1 +
 target/i386/cpu.c              |  38 ++-
 target/i386/cpu.h              |   6 +
 target/i386/helper.c           |  46 ++-
 target/i386/monitor.c          | 145 ++++++----
 27 files changed, 1409 insertions(+), 88 deletions(-)
 create mode 100644 accel/kvm/sev.c
 create mode 100644 docs/amd-memory-encryption.txt
 create mode 100644 include/sysemu/sev.h

-- 
2.9.5

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

* [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

The debug attribute will be set when qemu attempts to access the guest
memory for debug (e.g memory access from gdbstub, memory dump commands
etc).

When guest memory is encrypted, the debug access will need to go through
the memory encryption APIs.

Cc: Alistair Francis <alistair.francis@xilinx.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
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 d4a16420984b..721362e06292 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;
+    /* Debug memory access for encrypted guest */
+    unsigned int debug:1;
 } MemTxAttrs;
 
 /* Bus masters which don't specify any attributes will get this,
@@ -56,4 +58,6 @@ typedef struct MemTxAttrs {
 #define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */
 typedef uint32_t MemTxResult;
 
+/* Access the guest memory for debug purposes */
+#define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
 #endif
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

The debug attribute will be set when qemu attempts to access the guest
memory for debug (e.g memory access from gdbstub, memory dump commands
etc).

When guest memory is encrypted, the debug access will need to go through
the memory encryption APIs.

Cc: Alistair Francis <alistair.francis@xilinx.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
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 d4a16420984b..721362e06292 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;
+    /* Debug memory access for encrypted guest */
+    unsigned int debug:1;
 } MemTxAttrs;
 
 /* Bus masters which don't specify any attributes will get this,
@@ -56,4 +58,6 @@ typedef struct MemTxAttrs {
 #define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */
 typedef uint32_t MemTxResult;
 
+/* Access the guest memory for debug purposes */
+#define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
 #endif
-- 
2.9.5

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

* [PATCH v5 02/23] exec: add ram_debug_ops support
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Currently, the guest memory access for the debug purpose is performed
using the memcpy(). Lets extend the 'struct MemoryRegion' to include
ram_debug_ops callbacks. The ram_debug_ops can be used to override
memcpy() with something else.

The feature can be used by encrypted guest -- which can register
callbacks to override memcpy() with memory encryption/decryption APIs.

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_debug_ops(mem, ops);

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 exec.c                | 65 ++++++++++++++++++++++++++++++++++++++-------------
 include/exec/memory.h | 27 +++++++++++++++++++++
 2 files changed, 76 insertions(+), 16 deletions(-)

diff --git a/exec.c b/exec.c
index 03238a3449d9..9b0ab1648945 100644
--- a/exec.c
+++ b/exec.c
@@ -2981,7 +2981,11 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
         } else {
             /* RAM case */
             ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
-            memcpy(ptr, buf, l);
+            if (attrs.debug && mr->ram_debug_ops) {
+                mr->ram_debug_ops->write(ptr, buf, l, attrs);
+            } else {
+                memcpy(ptr, buf, l);
+            }
             invalidate_and_set_dirty(mr, addr1, l);
         }
 
@@ -3079,7 +3083,10 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
         } else {
             /* RAM case */
             ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
-            memcpy(buf, ptr, l);
+            if (attrs.debug && mr->ram_debug_ops)
+                mr->ram_debug_ops->read(buf, ptr, l, attrs);
+            else
+                memcpy(buf, ptr, l);
         }
 
         if (release_lock) {
@@ -3149,11 +3156,13 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
 
 enum write_rom_type {
     WRITE_DATA,
+    READ_DATA,
     FLUSH_CACHE,
 };
 
-static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
-    hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
+static inline void cpu_physical_memory_rw_debug_internal(AddressSpace *as,
+    hwaddr addr, uint8_t *buf, int len, MemTxAttrs attrs,
+    enum write_rom_type type)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -3168,12 +3177,33 @@ 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 address_space_rw */
+            switch (type) {
+            case READ_DATA:
+            case WRITE_DATA:
+                address_space_rw(as, addr1, 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:
+                if (mr->ram_debug_ops) {
+                    mr->ram_debug_ops->read(buf, ptr, l, attrs);
+                } else {
+                    memcpy(buf, ptr, l);
+                }
+                break;
             case WRITE_DATA:
-                memcpy(ptr, buf, l);
+                if (mr->ram_debug_ops) {
+                    mr->ram_debug_ops->write(ptr, buf, l, attrs);
+                } else {
+                    memcpy(ptr, buf, l);
+                }
                 invalidate_and_set_dirty(mr, addr1, l);
                 break;
             case FLUSH_CACHE:
@@ -3192,7 +3222,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_rw_debug_internal(as, addr, (uint8_t *)buf, len,
+            MEMTXATTRS_UNSPECIFIED, WRITE_DATA);
 }
 
 void cpu_flush_icache_range(hwaddr start, int len)
@@ -3207,8 +3238,10 @@ 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,
+                                           MEMTXATTRS_UNSPECIFIED,
+                                           FLUSH_CACHE);
 }
 
 typedef struct {
@@ -3514,6 +3547,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
     int l;
     hwaddr phys_addr;
     target_ulong page;
+    int type = is_write ? WRITE_DATA : READ_DATA;
 
     cpu_synchronize_state(cpu);
     while (len > 0) {
@@ -3523,6 +3557,10 @@ 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);
+
+        /* set debug attribute */
+        attrs.debug = 1;
+
         /* if no physical page mapped, return an error */
         if (phys_addr == -1)
             return -1;
@@ -3530,14 +3568,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, attrs,
+                                               type);
         len -= l;
         buf += l;
         addr += l;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 5ed4042f877d..546a67bf0dac 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -215,6 +215,18 @@ typedef struct IOMMUMemoryRegionClass {
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
+/* Memory Region RAM debug 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);
+};
+
 struct MemoryRegion {
     Object parent_obj;
 
@@ -254,6 +266,7 @@ struct MemoryRegion {
     const char *name;
     unsigned ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
+    const MemoryRegionRAMReadWriteOps *ram_debug_ops;
 };
 
 struct IOMMUMemoryRegion {
@@ -621,6 +634,20 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
                                              Error **errp);
 
 /**
+ * memory_region_set_ram_debug_ops: Set debug access ops for a given memory region
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that will be used for when accessing @target region during
+ *       debug
+ */
+static inline void
+memory_region_set_ram_debug_ops(MemoryRegion *mr,
+                                const MemoryRegionRAMReadWriteOps *ops)
+{
+    mr->ram_debug_ops = ops;
+}
+
+/**
  * memory_region_init_reservation: Initialize a memory region that reserves
  *                                 I/O space.
  *
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 02/23] exec: add ram_debug_ops support
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Currently, the guest memory access for the debug purpose is performed
using the memcpy(). Lets extend the 'struct MemoryRegion' to include
ram_debug_ops callbacks. The ram_debug_ops can be used to override
memcpy() with something else.

The feature can be used by encrypted guest -- which can register
callbacks to override memcpy() with memory encryption/decryption APIs.

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_debug_ops(mem, ops);

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 exec.c                | 65 ++++++++++++++++++++++++++++++++++++++-------------
 include/exec/memory.h | 27 +++++++++++++++++++++
 2 files changed, 76 insertions(+), 16 deletions(-)

diff --git a/exec.c b/exec.c
index 03238a3449d9..9b0ab1648945 100644
--- a/exec.c
+++ b/exec.c
@@ -2981,7 +2981,11 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
         } else {
             /* RAM case */
             ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
-            memcpy(ptr, buf, l);
+            if (attrs.debug && mr->ram_debug_ops) {
+                mr->ram_debug_ops->write(ptr, buf, l, attrs);
+            } else {
+                memcpy(ptr, buf, l);
+            }
             invalidate_and_set_dirty(mr, addr1, l);
         }
 
@@ -3079,7 +3083,10 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
         } else {
             /* RAM case */
             ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
-            memcpy(buf, ptr, l);
+            if (attrs.debug && mr->ram_debug_ops)
+                mr->ram_debug_ops->read(buf, ptr, l, attrs);
+            else
+                memcpy(buf, ptr, l);
         }
 
         if (release_lock) {
@@ -3149,11 +3156,13 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
 
 enum write_rom_type {
     WRITE_DATA,
+    READ_DATA,
     FLUSH_CACHE,
 };
 
-static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
-    hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
+static inline void cpu_physical_memory_rw_debug_internal(AddressSpace *as,
+    hwaddr addr, uint8_t *buf, int len, MemTxAttrs attrs,
+    enum write_rom_type type)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -3168,12 +3177,33 @@ 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 address_space_rw */
+            switch (type) {
+            case READ_DATA:
+            case WRITE_DATA:
+                address_space_rw(as, addr1, 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:
+                if (mr->ram_debug_ops) {
+                    mr->ram_debug_ops->read(buf, ptr, l, attrs);
+                } else {
+                    memcpy(buf, ptr, l);
+                }
+                break;
             case WRITE_DATA:
-                memcpy(ptr, buf, l);
+                if (mr->ram_debug_ops) {
+                    mr->ram_debug_ops->write(ptr, buf, l, attrs);
+                } else {
+                    memcpy(ptr, buf, l);
+                }
                 invalidate_and_set_dirty(mr, addr1, l);
                 break;
             case FLUSH_CACHE:
@@ -3192,7 +3222,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_rw_debug_internal(as, addr, (uint8_t *)buf, len,
+            MEMTXATTRS_UNSPECIFIED, WRITE_DATA);
 }
 
 void cpu_flush_icache_range(hwaddr start, int len)
@@ -3207,8 +3238,10 @@ 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,
+                                           MEMTXATTRS_UNSPECIFIED,
+                                           FLUSH_CACHE);
 }
 
 typedef struct {
@@ -3514,6 +3547,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
     int l;
     hwaddr phys_addr;
     target_ulong page;
+    int type = is_write ? WRITE_DATA : READ_DATA;
 
     cpu_synchronize_state(cpu);
     while (len > 0) {
@@ -3523,6 +3557,10 @@ 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);
+
+        /* set debug attribute */
+        attrs.debug = 1;
+
         /* if no physical page mapped, return an error */
         if (phys_addr == -1)
             return -1;
@@ -3530,14 +3568,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, attrs,
+                                               type);
         len -= l;
         buf += l;
         addr += l;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 5ed4042f877d..546a67bf0dac 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -215,6 +215,18 @@ typedef struct IOMMUMemoryRegionClass {
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
+/* Memory Region RAM debug 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);
+};
+
 struct MemoryRegion {
     Object parent_obj;
 
@@ -254,6 +266,7 @@ struct MemoryRegion {
     const char *name;
     unsigned ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
+    const MemoryRegionRAMReadWriteOps *ram_debug_ops;
 };
 
 struct IOMMUMemoryRegion {
@@ -621,6 +634,20 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
                                              Error **errp);
 
 /**
+ * memory_region_set_ram_debug_ops: Set debug access ops for a given memory region
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that will be used for when accessing @target region during
+ *       debug
+ */
+static inline void
+memory_region_set_ram_debug_ops(MemoryRegion *mr,
+                                const MemoryRegionRAMReadWriteOps *ops)
+{
+    mr->ram_debug_ops = ops;
+}
+
+/**
  * memory_region_init_reservation: Initialize a memory region that reserves
  *                                 I/O space.
  *
-- 
2.9.5

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

* [PATCH v5 03/23] exec: add debug version of physical memory read and write API
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Adds the following new APIs
- cpu_physical_memory_read_debug
- cpu_physical_memory_write_debug
- cpu_physical_memory_rw_debug
- ldl_phys_debug
- ldq_phys_debug

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                    | 31 +++++++++++++++++++++++++++++++
 include/exec/cpu-common.h | 15 +++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/exec.c b/exec.c
index 9b0ab1648945..e1837cad61f9 100644
--- a/exec.c
+++ b/exec.c
@@ -3540,6 +3540,37 @@ void address_space_cache_destroy(MemoryRegionCache *cache)
 #define RCU_READ_UNLOCK()        rcu_read_unlock()
 #include "memory_ldst.inc.c"
 
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr)
+{
+    MemTxAttrs attrs = MEMTXATTRS_DEBUG;
+    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, attrs, READ_DATA);
+    return tswap32(val);
+}
+
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr)
+{
+    MemTxAttrs attrs = MEMTXATTRS_DEBUG;
+    int asidx = cpu_asidx_from_attrs(cpu, attrs);
+    uint64_t val;
+
+    cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
+                                          addr, (void *) &val,
+                                          8, attrs, READ_DATA);
+    return val;
+}
+
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+                                  int len, int is_write)
+{
+    address_space_rw(&address_space_memory, addr, MEMTXATTRS_DEBUG, 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 74341b19d26a..fa01385d4f1b 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -77,11 +77,26 @@ size_t qemu_ram_pagesize_largest(void);
 
 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)
 {
     cpu_physical_memory_rw(addr, buf, len, 0);
 }
+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);
+}
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr);
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr);
+
 static inline void cpu_physical_memory_write(hwaddr addr,
                                              const void *buf, int len)
 {
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 03/23] exec: add debug version of physical memory read and write API
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Adds the following new APIs
- cpu_physical_memory_read_debug
- cpu_physical_memory_write_debug
- cpu_physical_memory_rw_debug
- ldl_phys_debug
- ldq_phys_debug

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                    | 31 +++++++++++++++++++++++++++++++
 include/exec/cpu-common.h | 15 +++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/exec.c b/exec.c
index 9b0ab1648945..e1837cad61f9 100644
--- a/exec.c
+++ b/exec.c
@@ -3540,6 +3540,37 @@ void address_space_cache_destroy(MemoryRegionCache *cache)
 #define RCU_READ_UNLOCK()        rcu_read_unlock()
 #include "memory_ldst.inc.c"
 
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr)
+{
+    MemTxAttrs attrs = MEMTXATTRS_DEBUG;
+    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, attrs, READ_DATA);
+    return tswap32(val);
+}
+
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr)
+{
+    MemTxAttrs attrs = MEMTXATTRS_DEBUG;
+    int asidx = cpu_asidx_from_attrs(cpu, attrs);
+    uint64_t val;
+
+    cpu_physical_memory_rw_debug_internal(cpu->cpu_ases[asidx].as,
+                                          addr, (void *) &val,
+                                          8, attrs, READ_DATA);
+    return val;
+}
+
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+                                  int len, int is_write)
+{
+    address_space_rw(&address_space_memory, addr, MEMTXATTRS_DEBUG, 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 74341b19d26a..fa01385d4f1b 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -77,11 +77,26 @@ size_t qemu_ram_pagesize_largest(void);
 
 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)
 {
     cpu_physical_memory_rw(addr, buf, len, 0);
 }
+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);
+}
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr);
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr);
+
 static inline void cpu_physical_memory_write(hwaddr addr,
                                              const void *buf, int len)
 {
-- 
2.9.5

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

* [PATCH v5 04/23] monitor/i386: use debug APIs when accessing guest memory
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Updates HMP commands to use the debug version of APIs when accessing the
guest memory.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 cpus.c                |  2 +-
 disas.c               |  2 +-
 monitor.c             |  2 +-
 target/i386/helper.c  | 14 ++++++------
 target/i386/monitor.c | 59 +++++++++++++++++++++++++++------------------------
 5 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/cpus.c b/cpus.c
index 114c29b6a0d3..d1e7e28993e8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2026,7 +2026,7 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
         l = sizeof(buf);
         if (l > size)
             l = size;
-        cpu_physical_memory_read(addr, buf, l);
+        cpu_physical_memory_read_debug(addr, buf, l);
         if (fwrite(buf, 1, l, f) != l) {
             error_setg(errp, QERR_IO_ERROR);
             goto exit;
diff --git a/disas.c b/disas.c
index d4ad1089efb3..fcedbf263302 100644
--- a/disas.c
+++ b/disas.c
@@ -586,7 +586,7 @@ static int
 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
                      struct disassemble_info *info)
 {
-    cpu_physical_memory_read(memaddr, myaddr, length);
+    cpu_physical_memory_read_debug(memaddr, myaddr, length);
     return 0;
 }
 
diff --git a/monitor.c b/monitor.c
index e36fb5308d34..d8f05b9f88fa 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1359,7 +1359,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(cs, addr, buf, l, 0) < 0) {
                 monitor_printf(mon, " Cannot access memory\n");
diff --git a/target/i386/helper.c b/target/i386/helper.c
index f63eb3d3f4fb..5dc9e8839bc8 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -757,7 +757,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             if (la57) {
                 pml5e_addr = ((env->cr[3] & ~0xfff) +
                         (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
-                pml5e = x86_ldq_phys(cs, pml5e_addr);
+                pml5e = ldq_phys_debug(cs, pml5e_addr);
                 if (!(pml5e & PG_PRESENT_MASK)) {
                     return -1;
                 }
@@ -767,7 +767,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
             pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
                     (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
-            pml4e = x86_ldq_phys(cs, pml4e_addr);
+            pml4e = ldq_phys_debug(cs, pml4e_addr);
             if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
             }
@@ -788,14 +788,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         {
             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
                 a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = ldq_phys_debug(cs, pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
         }
 
         pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
-        pde = x86_ldq_phys(cs, pde_addr);
+        pde = ldq_phys_debug(cs, pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
         }
@@ -808,7 +808,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
             page_size = 4096;
-            pte = x86_ldq_phys(cs, pte_addr);
+            pte = ldq_phys_debug(cs, pte_addr);
         }
         if (!(pte & PG_PRESENT_MASK)) {
             return -1;
@@ -818,7 +818,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
         /* page directory entry */
         pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
-        pde = x86_ldl_phys(cs, pde_addr);
+        pde = ldl_phys_debug(cs, pde_addr);
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +827,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
-            pte = x86_ldl_phys(cs, pte_addr);
+            pte = ldl_phys_debug(cs, pte_addr);
             if (!(pte & PG_PRESENT_MASK)) {
                 return -1;
             }
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 75e155ffb1c4..96890547f6b4 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -66,7 +66,7 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
 
     pgd = env->cr[3] & ~0xfff;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+        cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -74,7 +74,8 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
                 print_pte(mon, env, (l1 << 22), pde, ~((1 << 21) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+                    cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+                                                   &pte, 4);
                     pte = le32_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l1 << 22) + (l2 << 12),
@@ -95,12 +96,12 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
 
     pdp_addr = env->cr[3] & ~0x1f;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+        cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+                cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
@@ -110,7 +111,8 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+                            cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+                                                           &pte, 8);
                             pte = le64_to_cpu(pte);
                             if (pte & PG_PRESENT_MASK) {
                                 print_pte(mon, env, (l1 << 30) + (l2 << 21)
@@ -135,7 +137,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
     uint64_t pdp_addr, pd_addr, pt_addr;
 
     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)) {
             continue;
@@ -143,7 +145,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
         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)) {
                 continue;
@@ -158,7 +160,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
             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)) {
                     continue;
@@ -173,9 +175,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
                 pt_addr = pde & 0x3fffffffff000ULL;
                 for (l4 = 0; l4 < 512; l4++) {
-                    cpu_physical_memory_read(pt_addr
-                            + l4 * 8,
-                            &pte, 8);
+                    cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
                     pte = le64_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l0 << 48) + (l1 << 39) +
@@ -196,7 +196,7 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
 
     pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
     for (l0 = 0; l0 < 512; l0++) {
-        cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+        cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
         pml5e = le64_to_cpu(pml5e);
         if (pml5e & PG_PRESENT_MASK) {
             tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
@@ -271,7 +271,7 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+        cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         end = l1 << 22;
         if (pde & PG_PRESENT_MASK) {
@@ -280,7 +280,8 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
                 mem_print(mon, &start, &last_prot, end, prot);
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+                    cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+                                                   &pte, 4);
                     pte = le32_to_cpu(pte);
                     end = (l1 << 22) + (l2 << 12);
                     if (pte & PG_PRESENT_MASK) {
@@ -313,13 +314,13 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+        cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         end = l1 << 30;
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+                cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 end = (l1 << 30) + (l2 << 21);
                 if (pde & PG_PRESENT_MASK) {
@@ -330,7 +331,8 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+                            cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+                                                           &pte, 8);
                             pte = le64_to_cpu(pte);
                             end = (l1 << 30) + (l2 << 21) + (l3 << 12);
                             if (pte & PG_PRESENT_MASK) {
@@ -369,13 +371,13 @@ static void mem_info_la48(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) {
@@ -387,7 +389,8 @@ static void mem_info_la48(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) {
@@ -399,9 +402,9 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                                 } else {
                                     pt_addr = pde & 0x3fffffffff000ULL;
                                     for (l4 = 0; l4 < 512; l4++) {
-                                        cpu_physical_memory_read(pt_addr
-                                                                 + l4 * 8,
-                                                                 &pte, 8);
+                                        cpu_physical_memory_read_debug(pt_addr
+                                                                  + l4 * 8,
+                                                                  &pte, 8);
                                         pte = le64_to_cpu(pte);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);
@@ -446,7 +449,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for (l0 = 0; l0 < 512; l0++) {
-        cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+        cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
         pml5e = le64_to_cpu(pml5e);
         end = l0 << 48;
         if (!(pml5e & PG_PRESENT_MASK)) {
@@ -457,7 +460,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
         pml4_addr = pml5e & 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);
             end = (l0 << 48) + (l1 << 39);
             if (!(pml4e & PG_PRESENT_MASK)) {
@@ -468,7 +471,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
             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 = (l0 << 48) + (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
@@ -487,7 +490,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
                 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 = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
                     if (pde & PG_PRESENT_MASK) {
@@ -506,7 +509,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
                     pt_addr = pde & 0x3fffffffff000ULL;
                     for (l4 = 0; l4 < 512; l4++) {
-                        cpu_physical_memory_read(pt_addr + l4 * 8, &pte, 8);
+                        cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
                         pte = le64_to_cpu(pte);
                         end = (l0 << 48) + (l1 << 39) + (l2 << 30) +
                             (l3 << 21) + (l4 << 12);
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 04/23] monitor/i386: use debug APIs when accessing guest memory
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Updates HMP commands to use the debug version of APIs when accessing the
guest memory.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 cpus.c                |  2 +-
 disas.c               |  2 +-
 monitor.c             |  2 +-
 target/i386/helper.c  | 14 ++++++------
 target/i386/monitor.c | 59 +++++++++++++++++++++++++++------------------------
 5 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/cpus.c b/cpus.c
index 114c29b6a0d3..d1e7e28993e8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2026,7 +2026,7 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
         l = sizeof(buf);
         if (l > size)
             l = size;
-        cpu_physical_memory_read(addr, buf, l);
+        cpu_physical_memory_read_debug(addr, buf, l);
         if (fwrite(buf, 1, l, f) != l) {
             error_setg(errp, QERR_IO_ERROR);
             goto exit;
diff --git a/disas.c b/disas.c
index d4ad1089efb3..fcedbf263302 100644
--- a/disas.c
+++ b/disas.c
@@ -586,7 +586,7 @@ static int
 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
                      struct disassemble_info *info)
 {
-    cpu_physical_memory_read(memaddr, myaddr, length);
+    cpu_physical_memory_read_debug(memaddr, myaddr, length);
     return 0;
 }
 
diff --git a/monitor.c b/monitor.c
index e36fb5308d34..d8f05b9f88fa 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1359,7 +1359,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(cs, addr, buf, l, 0) < 0) {
                 monitor_printf(mon, " Cannot access memory\n");
diff --git a/target/i386/helper.c b/target/i386/helper.c
index f63eb3d3f4fb..5dc9e8839bc8 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -757,7 +757,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             if (la57) {
                 pml5e_addr = ((env->cr[3] & ~0xfff) +
                         (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
-                pml5e = x86_ldq_phys(cs, pml5e_addr);
+                pml5e = ldq_phys_debug(cs, pml5e_addr);
                 if (!(pml5e & PG_PRESENT_MASK)) {
                     return -1;
                 }
@@ -767,7 +767,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
             pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
                     (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
-            pml4e = x86_ldq_phys(cs, pml4e_addr);
+            pml4e = ldq_phys_debug(cs, pml4e_addr);
             if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
             }
@@ -788,14 +788,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         {
             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
                 a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = ldq_phys_debug(cs, pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
         }
 
         pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
-        pde = x86_ldq_phys(cs, pde_addr);
+        pde = ldq_phys_debug(cs, pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
         }
@@ -808,7 +808,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
             page_size = 4096;
-            pte = x86_ldq_phys(cs, pte_addr);
+            pte = ldq_phys_debug(cs, pte_addr);
         }
         if (!(pte & PG_PRESENT_MASK)) {
             return -1;
@@ -818,7 +818,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
         /* page directory entry */
         pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
-        pde = x86_ldl_phys(cs, pde_addr);
+        pde = ldl_phys_debug(cs, pde_addr);
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +827,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
-            pte = x86_ldl_phys(cs, pte_addr);
+            pte = ldl_phys_debug(cs, pte_addr);
             if (!(pte & PG_PRESENT_MASK)) {
                 return -1;
             }
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 75e155ffb1c4..96890547f6b4 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -66,7 +66,7 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
 
     pgd = env->cr[3] & ~0xfff;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+        cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -74,7 +74,8 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
                 print_pte(mon, env, (l1 << 22), pde, ~((1 << 21) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+                    cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+                                                   &pte, 4);
                     pte = le32_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l1 << 22) + (l2 << 12),
@@ -95,12 +96,12 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
 
     pdp_addr = env->cr[3] & ~0x1f;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+        cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+                cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
@@ -110,7 +111,8 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+                            cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+                                                           &pte, 8);
                             pte = le64_to_cpu(pte);
                             if (pte & PG_PRESENT_MASK) {
                                 print_pte(mon, env, (l1 << 30) + (l2 << 21)
@@ -135,7 +137,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
     uint64_t pdp_addr, pd_addr, pt_addr;
 
     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)) {
             continue;
@@ -143,7 +145,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
         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)) {
                 continue;
@@ -158,7 +160,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
             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)) {
                     continue;
@@ -173,9 +175,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
 
                 pt_addr = pde & 0x3fffffffff000ULL;
                 for (l4 = 0; l4 < 512; l4++) {
-                    cpu_physical_memory_read(pt_addr
-                            + l4 * 8,
-                            &pte, 8);
+                    cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
                     pte = le64_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l0 << 48) + (l1 << 39) +
@@ -196,7 +196,7 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
 
     pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
     for (l0 = 0; l0 < 512; l0++) {
-        cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+        cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
         pml5e = le64_to_cpu(pml5e);
         if (pml5e & PG_PRESENT_MASK) {
             tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
@@ -271,7 +271,7 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+        cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         end = l1 << 22;
         if (pde & PG_PRESENT_MASK) {
@@ -280,7 +280,8 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
                 mem_print(mon, &start, &last_prot, end, prot);
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+                    cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+                                                   &pte, 4);
                     pte = le32_to_cpu(pte);
                     end = (l1 << 22) + (l2 << 12);
                     if (pte & PG_PRESENT_MASK) {
@@ -313,13 +314,13 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+        cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         end = l1 << 30;
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+                cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 end = (l1 << 30) + (l2 << 21);
                 if (pde & PG_PRESENT_MASK) {
@@ -330,7 +331,8 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+                            cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+                                                           &pte, 8);
                             pte = le64_to_cpu(pte);
                             end = (l1 << 30) + (l2 << 21) + (l3 << 12);
                             if (pte & PG_PRESENT_MASK) {
@@ -369,13 +371,13 @@ static void mem_info_la48(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) {
@@ -387,7 +389,8 @@ static void mem_info_la48(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) {
@@ -399,9 +402,9 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                                 } else {
                                     pt_addr = pde & 0x3fffffffff000ULL;
                                     for (l4 = 0; l4 < 512; l4++) {
-                                        cpu_physical_memory_read(pt_addr
-                                                                 + l4 * 8,
-                                                                 &pte, 8);
+                                        cpu_physical_memory_read_debug(pt_addr
+                                                                  + l4 * 8,
+                                                                  &pte, 8);
                                         pte = le64_to_cpu(pte);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);
@@ -446,7 +449,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
     last_prot = 0;
     start = -1;
     for (l0 = 0; l0 < 512; l0++) {
-        cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+        cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
         pml5e = le64_to_cpu(pml5e);
         end = l0 << 48;
         if (!(pml5e & PG_PRESENT_MASK)) {
@@ -457,7 +460,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
         pml4_addr = pml5e & 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);
             end = (l0 << 48) + (l1 << 39);
             if (!(pml4e & PG_PRESENT_MASK)) {
@@ -468,7 +471,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
             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 = (l0 << 48) + (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
@@ -487,7 +490,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
                 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 = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
                     if (pde & PG_PRESENT_MASK) {
@@ -506,7 +509,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
 
                     pt_addr = pde & 0x3fffffffff000ULL;
                     for (l4 = 0; l4 < 512; l4++) {
-                        cpu_physical_memory_read(pt_addr + l4 * 8, &pte, 8);
+                        cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
                         pte = le64_to_cpu(pte);
                         end = (l0 << 48) + (l1 << 39) + (l2 << 30) +
                             (l3 << 21) + (l4 << 12);
-- 
2.9.5

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

* [PATCH v5 05/23] target/i386: add memory encryption feature cpuid support
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

AMD EPYC processors support memory encryption feature. The feature
is reported through CPUID 8000_001F[EAX].

Fn8000_001F [EAX]:
 Bit 0   Secure Memory Encryption (SME) supported
 Bit 1   Secure Encrypted Virtualization (SEV) supported
 Bit 2   Page flush MSR supported
 Bit 3   Ecrypted State (SEV-ES) support

when memory encryption feature is reported, CPUID 8000_001F[EBX] should
provide additional information regarding the feature (such as which page
table bit is used to mark pages as encrypted etc). The information in EBX
and ECX may vary from one family to another hence we use the host cpuid
to populate the EBX information.

The details for memory encryption CPUID is available in AMD APM
(http://support.amd.com/TechDocs/24593.pdf) Section 15.34.1

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target/i386/cpu.c | 36 ++++++++++++++++++++++++++++++++++++
 target/i386/cpu.h |  6 ++++++
 2 files changed, 42 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 045d66191f28..0cc7bb88ce2d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -233,6 +233,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #define TCG_EXT4_FEATURES 0
 #define TCG_SVM_FEATURES 0
 #define TCG_KVM_FEATURES 0
+#define TCG_MEM_ENCRYPT_FEATURES 0
 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
           CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
           CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT |            \
@@ -528,6 +529,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .cpuid_reg = R_EDX,
         .tcg_features = ~0U,
     },
+    [FEAT_MEM_ENCRYPT] = {
+        .feat_names = {
+            "sme", "sev", "page-flush-msr", "sev-es",
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+        },
+        .cpuid_eax = 0x8000001F, .cpuid_reg = R_EAX,
+        .tcg_features = TCG_MEM_ENCRYPT_FEATURES,
+    }
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1562,6 +1577,9 @@ static X86CPUDefinition builtin_x86_defs[] = {
             CPUID_XSAVE_XGETBV1,
         .features[FEAT_6_EAX] =
             CPUID_6_EAX_ARAT,
+        /* Missing: SEV_ES */
+        .features[FEAT_MEM_ENCRYPT] =
+            CPUID_8000_001F_EAX_SME | CPUID_8000_001F_EAX_SEV,
         .xlevel = 0x8000000A,
         .model_id = "AMD EPYC Processor",
     },
@@ -3110,6 +3128,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             *edx = 0;
         }
         break;
+    case 0x8000001F:
+        if (env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV) {
+            *eax = env->features[FEAT_MEM_ENCRYPT];
+            host_cpuid(0x8000001F, 0, NULL, ebx, NULL, NULL);
+            *ecx = 0;
+            *edx = 0;
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
     case 0xC0000000:
         *eax = env->cpuid_xlevel2;
         *ebx = 0;
@@ -3549,10 +3580,15 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
         x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
         x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
         x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
+        x86_cpu_adjust_feat_level(cpu, FEAT_MEM_ENCRYPT);
         /* SVM requires CPUID[0x8000000A] */
         if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
             x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
         }
+        /* SEV requires CPUID[0x8000001F] */
+        if ((env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV)) {
+            x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F);
+        }
     }
 
     /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index b086b1528b89..a99e89c368ba 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -463,6 +463,7 @@ typedef enum FeatureWord {
     FEAT_6_EAX,         /* CPUID[6].EAX */
     FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
     FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
+    FEAT_MEM_ENCRYPT,   /* CPUID[8000_001F].EAX */
     FEATURE_WORDS,
 } FeatureWord;
 
@@ -649,6 +650,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 
 #define CPUID_6_EAX_ARAT       (1U << 2)
 
+#define CPUID_8000_001F_EAX_SME             (1U << 0) /* SME */
+#define CPUID_8000_001F_EAX_SEV             (1U << 1) /* SEV */
+#define CPUID_8000_001F_EAX_PAGE_FLUSH_MSR  (1U << 2) /* Page flush MSR */
+#define CPUID_8000_001F_EAX_SEV_ES          (1U << 3) /* SEV-ES */
+
 /* CPUID[0x80000007].EDX flags: */
 #define CPUID_APM_INVTSC       (1U << 8)
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 05/23] target/i386: add memory encryption feature cpuid support
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

AMD EPYC processors support memory encryption feature. The feature
is reported through CPUID 8000_001F[EAX].

Fn8000_001F [EAX]:
 Bit 0   Secure Memory Encryption (SME) supported
 Bit 1   Secure Encrypted Virtualization (SEV) supported
 Bit 2   Page flush MSR supported
 Bit 3   Ecrypted State (SEV-ES) support

when memory encryption feature is reported, CPUID 8000_001F[EBX] should
provide additional information regarding the feature (such as which page
table bit is used to mark pages as encrypted etc). The information in EBX
and ECX may vary from one family to another hence we use the host cpuid
to populate the EBX information.

The details for memory encryption CPUID is available in AMD APM
(http://support.amd.com/TechDocs/24593.pdf) Section 15.34.1

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target/i386/cpu.c | 36 ++++++++++++++++++++++++++++++++++++
 target/i386/cpu.h |  6 ++++++
 2 files changed, 42 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 045d66191f28..0cc7bb88ce2d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -233,6 +233,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #define TCG_EXT4_FEATURES 0
 #define TCG_SVM_FEATURES 0
 #define TCG_KVM_FEATURES 0
+#define TCG_MEM_ENCRYPT_FEATURES 0
 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
           CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
           CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT |            \
@@ -528,6 +529,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .cpuid_reg = R_EDX,
         .tcg_features = ~0U,
     },
+    [FEAT_MEM_ENCRYPT] = {
+        .feat_names = {
+            "sme", "sev", "page-flush-msr", "sev-es",
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+        },
+        .cpuid_eax = 0x8000001F, .cpuid_reg = R_EAX,
+        .tcg_features = TCG_MEM_ENCRYPT_FEATURES,
+    }
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1562,6 +1577,9 @@ static X86CPUDefinition builtin_x86_defs[] = {
             CPUID_XSAVE_XGETBV1,
         .features[FEAT_6_EAX] =
             CPUID_6_EAX_ARAT,
+        /* Missing: SEV_ES */
+        .features[FEAT_MEM_ENCRYPT] =
+            CPUID_8000_001F_EAX_SME | CPUID_8000_001F_EAX_SEV,
         .xlevel = 0x8000000A,
         .model_id = "AMD EPYC Processor",
     },
@@ -3110,6 +3128,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             *edx = 0;
         }
         break;
+    case 0x8000001F:
+        if (env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV) {
+            *eax = env->features[FEAT_MEM_ENCRYPT];
+            host_cpuid(0x8000001F, 0, NULL, ebx, NULL, NULL);
+            *ecx = 0;
+            *edx = 0;
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
     case 0xC0000000:
         *eax = env->cpuid_xlevel2;
         *ebx = 0;
@@ -3549,10 +3580,15 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
         x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
         x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
         x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
+        x86_cpu_adjust_feat_level(cpu, FEAT_MEM_ENCRYPT);
         /* SVM requires CPUID[0x8000000A] */
         if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
             x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
         }
+        /* SEV requires CPUID[0x8000001F] */
+        if ((env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV)) {
+            x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F);
+        }
     }
 
     /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index b086b1528b89..a99e89c368ba 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -463,6 +463,7 @@ typedef enum FeatureWord {
     FEAT_6_EAX,         /* CPUID[6].EAX */
     FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
     FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
+    FEAT_MEM_ENCRYPT,   /* CPUID[8000_001F].EAX */
     FEATURE_WORDS,
 } FeatureWord;
 
@@ -649,6 +650,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 
 #define CPUID_6_EAX_ARAT       (1U << 2)
 
+#define CPUID_8000_001F_EAX_SME             (1U << 0) /* SME */
+#define CPUID_8000_001F_EAX_SEV             (1U << 1) /* SEV */
+#define CPUID_8000_001F_EAX_PAGE_FLUSH_MSR  (1U << 2) /* Page flush MSR */
+#define CPUID_8000_001F_EAX_SEV_ES          (1U << 3) /* SEV-ES */
+
 /* CPUID[0x80000007].EDX flags: */
 #define CPUID_APM_INVTSC       (1U << 8)
 
-- 
2.9.5

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

* [PATCH v5 06/23] machine: add -memory-encryption property
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

When CPU supports memory encryption feature, the property can be used to
specify the encryption object to use when launching an encrypted guest.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcel Apfelbaum <marcel@redhat.com>
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/core/machine.c   | 22 ++++++++++++++++++++++
 include/hw/boards.h |  1 +
 qemu-options.hx     |  2 ++
 3 files changed, 25 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 36c2fb069c01..132c57bc5124 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -335,6 +335,22 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp)
     return ms->enforce_config_section;
 }
 
+static char *machine_get_memory_encryption(Object *obj, Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    return g_strdup(ms->memory_encryption);
+}
+
+static void machine_set_memory_encryption(Object *obj, const char *value,
+                                        Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    g_free(ms->memory_encryption);
+    ms->memory_encryption = g_strdup(value);
+}
+
 static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
 {
     error_report("Option '-device %s' cannot be handled by this machine",
@@ -598,6 +614,12 @@ static void machine_class_init(ObjectClass *oc, void *data)
         &error_abort);
     object_class_property_set_description(oc, "enforce-config-section",
         "Set on to enforce configuration section migration", &error_abort);
+
+    object_class_property_add_str(oc, "memory-encryption",
+        machine_get_memory_encryption, machine_set_memory_encryption,
+        &error_abort);
+    object_class_property_set_description(oc, "memory-encryption",
+        "Set memory encyption object to use", &error_abort);
 }
 
 static void machine_class_base_init(ObjectClass *oc, void *data)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 156b16f7a6b5..41fa5779557c 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -238,6 +238,7 @@ struct MachineState {
     bool suppress_vmdesc;
     bool enforce_config_section;
     bool enable_graphics;
+    char *memory_encryption;
 
     ram_addr_t ram_size;
     ram_addr_t maxram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index f11c4ac960ff..5385832707e0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -104,6 +104,8 @@ code to send configuration section even if the machine-type sets the
 @option{migration.send-configuration} property to @var{off}.
 NOTE: this parameter is deprecated. Please use @option{-global}
 @option{migration.send-configuration}=@var{on|off} instead.
+@item memory-encryption=@var{}
+Memory encryption object to use. The default is none.
 @end table
 ETEXI
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 06/23] machine: add -memory-encryption property
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

When CPU supports memory encryption feature, the property can be used to
specify the encryption object to use when launching an encrypted guest.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcel Apfelbaum <marcel@redhat.com>
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/core/machine.c   | 22 ++++++++++++++++++++++
 include/hw/boards.h |  1 +
 qemu-options.hx     |  2 ++
 3 files changed, 25 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 36c2fb069c01..132c57bc5124 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -335,6 +335,22 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp)
     return ms->enforce_config_section;
 }
 
+static char *machine_get_memory_encryption(Object *obj, Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    return g_strdup(ms->memory_encryption);
+}
+
+static void machine_set_memory_encryption(Object *obj, const char *value,
+                                        Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    g_free(ms->memory_encryption);
+    ms->memory_encryption = g_strdup(value);
+}
+
 static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
 {
     error_report("Option '-device %s' cannot be handled by this machine",
@@ -598,6 +614,12 @@ static void machine_class_init(ObjectClass *oc, void *data)
         &error_abort);
     object_class_property_set_description(oc, "enforce-config-section",
         "Set on to enforce configuration section migration", &error_abort);
+
+    object_class_property_add_str(oc, "memory-encryption",
+        machine_get_memory_encryption, machine_set_memory_encryption,
+        &error_abort);
+    object_class_property_set_description(oc, "memory-encryption",
+        "Set memory encyption object to use", &error_abort);
 }
 
 static void machine_class_base_init(ObjectClass *oc, void *data)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 156b16f7a6b5..41fa5779557c 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -238,6 +238,7 @@ struct MachineState {
     bool suppress_vmdesc;
     bool enforce_config_section;
     bool enable_graphics;
+    char *memory_encryption;
 
     ram_addr_t ram_size;
     ram_addr_t maxram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index f11c4ac960ff..5385832707e0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -104,6 +104,8 @@ code to send configuration section even if the machine-type sets the
 @option{migration.send-configuration} property to @var{off}.
 NOTE: this parameter is deprecated. Please use @option{-global}
 @option{migration.send-configuration}=@var{on|off} instead.
+@item memory-encryption=@var{}
+Memory encryption object to use. The default is none.
 @end table
 ETEXI
 
-- 
2.9.5

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

* [PATCH v5 07/23] kvm: update kvm.h to include memory encryption ioctls
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Updates kmv.h to include memory encryption ioctls and SEV commands.

Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 linux-headers/linux/kvm.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index dd8a91801e82..04b5801d0354 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1356,6 +1356,96 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_S390_CMMA_MIGRATION */
 #define KVM_S390_GET_CMMA_BITS      _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
 #define KVM_S390_SET_CMMA_BITS      _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
+/* Memory Encryption Commands */
+#define KVM_MEMORY_ENCRYPT_OP      _IOWR(KVMIO, 0xba, unsigned long)
+
+struct kvm_enc_region {
+	__u64 addr;
+	__u64 size;
+};
+
+#define KVM_MEMORY_ENCRYPT_REG_REGION    _IOR(KVMIO, 0xbb, struct kvm_enc_region)
+#define KVM_MEMORY_ENCRYPT_UNREG_REGION  _IOR(KVMIO, 0xbc, struct kvm_enc_region)
+
+/* Secure Encrypted Virtualization command */
+enum sev_cmd_id {
+	/* Guest initialization commands */
+	KVM_SEV_INIT = 0,
+	KVM_SEV_ES_INIT,
+	/* Guest launch commands */
+	KVM_SEV_LAUNCH_START,
+	KVM_SEV_LAUNCH_UPDATE_DATA,
+	KVM_SEV_LAUNCH_UPDATE_VMSA,
+	KVM_SEV_LAUNCH_SECRET,
+	KVM_SEV_LAUNCH_MEASURE,
+	KVM_SEV_LAUNCH_FINISH,
+	/* Guest migration commands (outgoing) */
+	KVM_SEV_SEND_START,
+	KVM_SEV_SEND_UPDATE_DATA,
+	KVM_SEV_SEND_UPDATE_VMSA,
+	KVM_SEV_SEND_FINISH,
+	/* Guest migration commands (incoming) */
+	KVM_SEV_RECEIVE_START,
+	KVM_SEV_RECEIVE_UPDATE_DATA,
+	KVM_SEV_RECEIVE_UPDATE_VMSA,
+	KVM_SEV_RECEIVE_FINISH,
+	/* Guest status and debug commands */
+	KVM_SEV_GUEST_STATUS,
+	KVM_SEV_DBG_DECRYPT,
+	KVM_SEV_DBG_ENCRYPT,
+	/* Guest certificates commands */
+	KVM_SEV_CERT_EXPORT,
+
+	KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_cmd {
+	__u32 id;
+	__u64 data;
+	__u32 error;
+	__u32 sev_fd;
+};
+
+struct kvm_sev_launch_start {
+	__u32 handle;
+	__u32 policy;
+	__u64 dh_uaddr;
+	__u32 dh_len;
+	__u64 session_uaddr;
+	__u32 session_len;
+};
+
+struct kvm_sev_launch_update_data {
+	__u64 uaddr;
+	__u32 len;
+};
+
+
+struct kvm_sev_launch_secret {
+	__u64 hdr_uaddr;
+	__u32 hdr_len;
+	__u64 guest_uaddr;
+	__u32 guest_len;
+	__u64 trans_uaddr;
+	__u32 trans_len;
+};
+
+struct kvm_sev_launch_measure {
+	__u64 uaddr;
+	__u32 len;
+};
+
+struct kvm_sev_guest_status {
+	__u32 handle;
+	__u32 policy;
+	__u32 state;
+};
+
+struct kvm_sev_dbg {
+	__u64 src_uaddr;
+	__u64 dst_uaddr;
+	__u32 len;
+};
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 07/23] kvm: update kvm.h to include memory encryption ioctls
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Updates kmv.h to include memory encryption ioctls and SEV commands.

Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 linux-headers/linux/kvm.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index dd8a91801e82..04b5801d0354 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1356,6 +1356,96 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_S390_CMMA_MIGRATION */
 #define KVM_S390_GET_CMMA_BITS      _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
 #define KVM_S390_SET_CMMA_BITS      _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
+/* Memory Encryption Commands */
+#define KVM_MEMORY_ENCRYPT_OP      _IOWR(KVMIO, 0xba, unsigned long)
+
+struct kvm_enc_region {
+	__u64 addr;
+	__u64 size;
+};
+
+#define KVM_MEMORY_ENCRYPT_REG_REGION    _IOR(KVMIO, 0xbb, struct kvm_enc_region)
+#define KVM_MEMORY_ENCRYPT_UNREG_REGION  _IOR(KVMIO, 0xbc, struct kvm_enc_region)
+
+/* Secure Encrypted Virtualization command */
+enum sev_cmd_id {
+	/* Guest initialization commands */
+	KVM_SEV_INIT = 0,
+	KVM_SEV_ES_INIT,
+	/* Guest launch commands */
+	KVM_SEV_LAUNCH_START,
+	KVM_SEV_LAUNCH_UPDATE_DATA,
+	KVM_SEV_LAUNCH_UPDATE_VMSA,
+	KVM_SEV_LAUNCH_SECRET,
+	KVM_SEV_LAUNCH_MEASURE,
+	KVM_SEV_LAUNCH_FINISH,
+	/* Guest migration commands (outgoing) */
+	KVM_SEV_SEND_START,
+	KVM_SEV_SEND_UPDATE_DATA,
+	KVM_SEV_SEND_UPDATE_VMSA,
+	KVM_SEV_SEND_FINISH,
+	/* Guest migration commands (incoming) */
+	KVM_SEV_RECEIVE_START,
+	KVM_SEV_RECEIVE_UPDATE_DATA,
+	KVM_SEV_RECEIVE_UPDATE_VMSA,
+	KVM_SEV_RECEIVE_FINISH,
+	/* Guest status and debug commands */
+	KVM_SEV_GUEST_STATUS,
+	KVM_SEV_DBG_DECRYPT,
+	KVM_SEV_DBG_ENCRYPT,
+	/* Guest certificates commands */
+	KVM_SEV_CERT_EXPORT,
+
+	KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_cmd {
+	__u32 id;
+	__u64 data;
+	__u32 error;
+	__u32 sev_fd;
+};
+
+struct kvm_sev_launch_start {
+	__u32 handle;
+	__u32 policy;
+	__u64 dh_uaddr;
+	__u32 dh_len;
+	__u64 session_uaddr;
+	__u32 session_len;
+};
+
+struct kvm_sev_launch_update_data {
+	__u64 uaddr;
+	__u32 len;
+};
+
+
+struct kvm_sev_launch_secret {
+	__u64 hdr_uaddr;
+	__u32 hdr_len;
+	__u64 guest_uaddr;
+	__u32 guest_len;
+	__u64 trans_uaddr;
+	__u32 trans_len;
+};
+
+struct kvm_sev_launch_measure {
+	__u64 uaddr;
+	__u32 len;
+};
+
+struct kvm_sev_guest_status {
+	__u32 handle;
+	__u32 policy;
+	__u32 state;
+};
+
+struct kvm_sev_dbg {
+	__u64 src_uaddr;
+	__u64 dst_uaddr;
+	__u32 len;
+};
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
-- 
2.9.5

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

* [PATCH v5 08/23] docs: add AMD Secure Encrypted Virtualization (SEV)
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Create a documentation entry to describe the AMD Secure Encrypted
Virtualization (SEV) feature.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 docs/amd-memory-encryption.txt | 92 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 docs/amd-memory-encryption.txt

diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
new file mode 100644
index 000000000000..72a92b6c6353
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,92 @@
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+SEV is an extension to the AMD-V architecture which supports running encrypted
+virtual machine (VMs) under the control of KVM. Encrypted VMs have their pages
+(code and data) secured such that only the guest itself has access to the
+unencrypted version. Each encrypted VM is associated with a unique encryption
+key; if its data is accessed to a different entity using a different key the
+encrypted guests data will be incorrectly decrypted, leading to unintelligible
+data.
+
+The key management of this feature is handled by separate processor known as
+AMD secure processor (AMD-SP) which is present in AMD SOCs. Firmware running
+inside the AMD-SP provide commands to support common VM lifecycle. This
+includes commands for launching, snapshotting, migrating and debugging the
+encrypted guest. Those SEV command can be issued via KVM_MEMORY_ENCRYPT_OP
+ioctls.
+
+Launching
+---------
+Boot images (such as bios) must be encrypted before guest can be booted.
+MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images :LAUNCH_START,
+LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
+together generate a fresh memory encryption key for the VM, encrypt the boot
+images and provide a measurement than can be used as an attestation of the
+successful launch.
+
+LAUNCH_START is called first to create a cryptographic launch context within
+the firmware. To create this context, guest owner must provides guest policy,
+its public Diffie-Hellman key (PDH) and session parameters. These inputs
+should be treated as binary blob and must be passed as-is to the SEV firmware.
+
+The guest policy is passed as plaintext and hypervisor may able to read it
+but should not modify it (any modification of the policy bits will result
+in bad measurement). The guest policy is a 4-byte data structure containing
+several flags that restricts what can be done on running SEV guest.
+See KM Spec section 3 and 6.2 for more details.
+
+Guest owners provided DH certificate and session parameters will be used to
+establish a cryptographic session with the guest owner to negotiate keys used
+for the attestation.
+
+LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
+created via LAUNCH_START command. If required, this command can be called
+multiple times to encrypt different memory regions. The command also calculates
+the measurement of the memory contents as it encrypts.
+
+LAUNCH_MEASURE command can be used to retrieve the measurement of encrypted
+memory. This measurement is a signature of the memory contents that can be
+sent to the guest owner as an attestation that the memory was encrypted
+correctly by the firmware. The guest owner may wait to provide the guest
+confidential information until it can verify the attestation measurement.
+Since the guest owner knows the initial contents of the guest at boot, the
+attestation measurement can be verified by comparing it to what the guest owner
+expects.
+
+LAUNCH_FINISH command finalizes the guest launch and destroy's the cryptographic
+context.
+
+See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
+complete flow chart.
+
+Debugging
+-----------
+Since memory contents of SEV guest is encrypted hence hypervisor access to the
+guest memory will get a cipher text. If guest policy allows debugging, then
+hypervisor can use DEBUG_DECRYPT and DEBUG_ENCRYPT commands access the guest
+memory region for debug purposes.
+
+Snapshot/Restore
+-----------------
+TODO
+
+Live Migration
+----------------
+TODO
+
+References
+-----------------
+
+AMD Memory Encryption whitepaper:
+http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+
+Secure Encrypted Virutualization Key Management:
+[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
+
+KVM Forum slides:
+http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
+
+AMD64 Architecture Programmer's Manual:
+   http://support.amd.com/TechDocs/24593.pdf
+   SME is section 7.10
+   SEV is section 15.34
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 08/23] docs: add AMD Secure Encrypted Virtualization (SEV)
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Create a documentation entry to describe the AMD Secure Encrypted
Virtualization (SEV) feature.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 docs/amd-memory-encryption.txt | 92 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 docs/amd-memory-encryption.txt

diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
new file mode 100644
index 000000000000..72a92b6c6353
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,92 @@
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+SEV is an extension to the AMD-V architecture which supports running encrypted
+virtual machine (VMs) under the control of KVM. Encrypted VMs have their pages
+(code and data) secured such that only the guest itself has access to the
+unencrypted version. Each encrypted VM is associated with a unique encryption
+key; if its data is accessed to a different entity using a different key the
+encrypted guests data will be incorrectly decrypted, leading to unintelligible
+data.
+
+The key management of this feature is handled by separate processor known as
+AMD secure processor (AMD-SP) which is present in AMD SOCs. Firmware running
+inside the AMD-SP provide commands to support common VM lifecycle. This
+includes commands for launching, snapshotting, migrating and debugging the
+encrypted guest. Those SEV command can be issued via KVM_MEMORY_ENCRYPT_OP
+ioctls.
+
+Launching
+---------
+Boot images (such as bios) must be encrypted before guest can be booted.
+MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images :LAUNCH_START,
+LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
+together generate a fresh memory encryption key for the VM, encrypt the boot
+images and provide a measurement than can be used as an attestation of the
+successful launch.
+
+LAUNCH_START is called first to create a cryptographic launch context within
+the firmware. To create this context, guest owner must provides guest policy,
+its public Diffie-Hellman key (PDH) and session parameters. These inputs
+should be treated as binary blob and must be passed as-is to the SEV firmware.
+
+The guest policy is passed as plaintext and hypervisor may able to read it
+but should not modify it (any modification of the policy bits will result
+in bad measurement). The guest policy is a 4-byte data structure containing
+several flags that restricts what can be done on running SEV guest.
+See KM Spec section 3 and 6.2 for more details.
+
+Guest owners provided DH certificate and session parameters will be used to
+establish a cryptographic session with the guest owner to negotiate keys used
+for the attestation.
+
+LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
+created via LAUNCH_START command. If required, this command can be called
+multiple times to encrypt different memory regions. The command also calculates
+the measurement of the memory contents as it encrypts.
+
+LAUNCH_MEASURE command can be used to retrieve the measurement of encrypted
+memory. This measurement is a signature of the memory contents that can be
+sent to the guest owner as an attestation that the memory was encrypted
+correctly by the firmware. The guest owner may wait to provide the guest
+confidential information until it can verify the attestation measurement.
+Since the guest owner knows the initial contents of the guest at boot, the
+attestation measurement can be verified by comparing it to what the guest owner
+expects.
+
+LAUNCH_FINISH command finalizes the guest launch and destroy's the cryptographic
+context.
+
+See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
+complete flow chart.
+
+Debugging
+-----------
+Since memory contents of SEV guest is encrypted hence hypervisor access to the
+guest memory will get a cipher text. If guest policy allows debugging, then
+hypervisor can use DEBUG_DECRYPT and DEBUG_ENCRYPT commands access the guest
+memory region for debug purposes.
+
+Snapshot/Restore
+-----------------
+TODO
+
+Live Migration
+----------------
+TODO
+
+References
+-----------------
+
+AMD Memory Encryption whitepaper:
+http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+
+Secure Encrypted Virutualization Key Management:
+[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
+
+KVM Forum slides:
+http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
+
+AMD64 Architecture Programmer's Manual:
+   http://support.amd.com/TechDocs/24593.pdf
+   SME is section 7.10
+   SEV is section 15.34
-- 
2.9.5

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

* [PATCH v5 09/23] accel: add Secure Encrypted Virtulization (SEV) object
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Add a new memory encryption object 'sev-guest'. The object will be used
to create enrypted VMs on AMD EPYC CPU. The object provides the properties
to pass guest owner's public Diffie-hellman key, guest policy and session
information required to create the memory encryption context within the
SEV firmware.

e.g to launch SEV guest
 # $QEMU \
    -object sev-guest,id=sev0 \
    -machine ....,memory-encryption=sev0

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/Makefile.objs        |   2 +-
 accel/kvm/sev.c                | 179 +++++++++++++++++++++++++++++++++++++++++
 docs/amd-memory-encryption.txt |  17 ++++
 include/sysemu/sev.h           |  53 ++++++++++++
 qemu-options.hx                |  34 ++++++++
 5 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 accel/kvm/sev.c
 create mode 100644 include/sysemu/sev.h

diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs
index 85351e7de7e8..666ceef3dae3 100644
--- a/accel/kvm/Makefile.objs
+++ b/accel/kvm/Makefile.objs
@@ -1 +1 @@
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
new file mode 100644
index 000000000000..a9b9a63c2da0
--- /dev/null
+++ b/accel/kvm/sev.c
@@ -0,0 +1,179 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016-2017
+ *
+ * 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 "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "qemu/base64.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
+#include "sysemu/sysemu.h"
+
+#define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
+#define DEFAULT_SEV_DEVICE      "/dev/sev"
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_guest_get_session_file(Object *obj, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    return s->session_file ? g_strdup(s->session_file) : NULL;
+}
+
+static void
+qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    s->session_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(s->dh_cert_file);
+}
+
+static void
+qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    s->dh_cert_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_sev_device(Object *obj, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(sev->sev_device);
+}
+
+static void
+qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    sev->sev_device = g_strdup(value);
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_str(oc, "sev-device",
+                                  qsev_guest_get_sev_device,
+                                  qsev_guest_set_sev_device,
+                                  NULL);
+    object_class_property_set_description(oc, "sev-device",
+            "SEV device to use", NULL);
+    object_class_property_add_str(oc, "dh-cert-file",
+                                  qsev_guest_get_dh_cert_file,
+                                  qsev_guest_set_dh_cert_file,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-cert-file",
+            "guest owners DH certificate (encoded with base64)", NULL);
+    object_class_property_add_str(oc, "session-file",
+                                  qsev_guest_get_session_file,
+                                  qsev_guest_set_session_file,
+                                  NULL);
+    object_class_property_set_description(oc, "session-file",
+            "guest owners session parameters (encoded with base64)", NULL);
+}
+
+static void
+qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, errp);
+    sev->handle = value;
+}
+
+static void
+qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, errp);
+    sev->policy = value;
+}
+
+static void
+qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    uint32_t value;
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    value = sev->policy;
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    uint32_t value;
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    value = sev->handle;
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_init(Object *obj)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
+    sev->policy = DEFAULT_GUEST_POLICY;
+    object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
+                        qsev_guest_set_policy, NULL, NULL, NULL);
+    object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
+                        qsev_guest_set_handle, NULL, NULL, NULL);
+}
+
+/* sev guest info */
+static const TypeInfo qsev_guest_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_GUEST_INFO,
+    .instance_size = sizeof(QSevGuestInfo),
+    .instance_finalize = qsev_guest_finalize,
+    .class_size = sizeof(QSevGuestInfoClass),
+    .class_init = qsev_guest_class_init,
+    .instance_init = qsev_guest_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+sev_register_types(void)
+{
+    type_register_static(&qsev_guest_info);
+}
+
+type_init(sev_register_types);
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
index 72a92b6c6353..1527f603ea2a 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/amd-memory-encryption.txt
@@ -35,10 +35,21 @@ in bad measurement). The guest policy is a 4-byte data structure containing
 several flags that restricts what can be done on running SEV guest.
 See KM Spec section 3 and 6.2 for more details.
 
+The guest policy can be provided via the 'policy' property (see below)
+
+# ${QEMU} \
+   sev-guest,id=sev0,policy=0x1...\
+
 Guest owners provided DH certificate and session parameters will be used to
 establish a cryptographic session with the guest owner to negotiate keys used
 for the attestation.
 
+The DH certificate and session blob can be provided via 'dh-cert-file' and
+'session-file' property (see below
+
+# ${QEMU} \
+     sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
+
 LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
 created via LAUNCH_START command. If required, this command can be called
 multiple times to encrypt different memory regions. The command also calculates
@@ -59,6 +70,12 @@ context.
 See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
 complete flow chart.
 
+To launch a SEV guest
+
+# ${QEMU} \
+    -machine ...,memory-encryption=sev0 \
+    -object sev-guest,id=sev0
+
 Debugging
 -----------
 Since memory contents of SEV guest is encrypted hence hypervisor access to the
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 000000000000..e00794ec1805
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU Secure Encrypted Virutualization (SEV) support
+ *
+ * Copyright: Advanced Micro Devices, 2016-2017
+ *
+ * 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 "qom/object.h"
+#include "qapi/error.h"
+#include "sysemu/kvm.h"
+#include "qemu/error-report.h"
+
+#define TYPE_QSEV_GUEST_INFO "sev-guest"
+#define QSEV_GUEST_INFO(obj)                  \
+    OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO)
+
+typedef struct QSevGuestInfo QSevGuestInfo;
+typedef struct QSevGuestInfoClass QSevGuestInfoClass;
+
+/**
+ * QSevGuestInfo:
+ *
+ * The QSevGuestInfo object is used for creating a SEV guest.
+ *
+ * # $QEMU \
+ *         -object sev-guest,id=sev0 \
+ *         -machine ...,memory-encryption=sev0
+ */
+struct QSevGuestInfo {
+    Object parent_obj;
+
+    char *sev_device;
+    uint32_t policy;
+    uint32_t handle;
+    char *dh_cert_file;
+    char *session_file;
+};
+
+struct QSevGuestInfoClass {
+    ObjectClass parent_class;
+};
+
+#endif
+
diff --git a/qemu-options.hx b/qemu-options.hx
index 5385832707e0..4611db3c1d51 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4470,6 +4470,40 @@ contents of @code{iv.b64} to the second secret
          data=$SECRET,iv=$(<iv.b64)
 @end example
 
+@item -object sev-guest,id=@var{id},sev-device=@var{string}[,policy=@var{policy},handle=@var{handle},dh-cert-file=@var{file},session-file=@var{file}]
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which can be used
+to provide the guest memory encryption support on AMD processors.
+
+The @option{sev-device} provides the device file to use for communicating with
+the SEV firmware running inside AMD Secure Processor. The default device is
+'/dev/sev'. If hardware supports memory encryption then /dev/sev devices are
+created by CCP driver.
+
+The @option{policy} provides the guest policy to be enforced by the SEV firmware
+and restrict what configuration and operational commands can be performed on this
+guest by the hypervisor. The policy should be provided by the guest owner and is
+bound to the guest and cannot be changed throughout the lifetime of the guest.
+The default is 0.
+
+If guest @option{policy} allows sharing the key with another SEV guest then
+@option{handle} can be use to provide handle of the guest from which to share
+the key.
+
+The @option{dh-cert-file} and @option{session-file} provides the guest owner's
+Public Diffie-Hillman key defined in SEV spec. The PDH and session parameters
+are used for establishing a cryptographic session with the guest owner to
+negotiate keys used for attestation. The file must be encoded in base64.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+     ......
+     -object sev-guest,id=sev0 \
+     -machine ...,memory-encryption=sev0
+     .....
+
+@end example
 @end table
 
 ETEXI
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 09/23] accel: add Secure Encrypted Virtulization (SEV) object
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Add a new memory encryption object 'sev-guest'. The object will be used
to create enrypted VMs on AMD EPYC CPU. The object provides the properties
to pass guest owner's public Diffie-hellman key, guest policy and session
information required to create the memory encryption context within the
SEV firmware.

e.g to launch SEV guest
 # $QEMU \
    -object sev-guest,id=sev0 \
    -machine ....,memory-encryption=sev0

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/Makefile.objs        |   2 +-
 accel/kvm/sev.c                | 179 +++++++++++++++++++++++++++++++++++++++++
 docs/amd-memory-encryption.txt |  17 ++++
 include/sysemu/sev.h           |  53 ++++++++++++
 qemu-options.hx                |  34 ++++++++
 5 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 accel/kvm/sev.c
 create mode 100644 include/sysemu/sev.h

diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs
index 85351e7de7e8..666ceef3dae3 100644
--- a/accel/kvm/Makefile.objs
+++ b/accel/kvm/Makefile.objs
@@ -1 +1 @@
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
new file mode 100644
index 000000000000..a9b9a63c2da0
--- /dev/null
+++ b/accel/kvm/sev.c
@@ -0,0 +1,179 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016-2017
+ *
+ * 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 "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "qemu/base64.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
+#include "sysemu/sysemu.h"
+
+#define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
+#define DEFAULT_SEV_DEVICE      "/dev/sev"
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_guest_get_session_file(Object *obj, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    return s->session_file ? g_strdup(s->session_file) : NULL;
+}
+
+static void
+qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    s->session_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(s->dh_cert_file);
+}
+
+static void
+qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+    s->dh_cert_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_sev_device(Object *obj, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(sev->sev_device);
+}
+
+static void
+qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    sev->sev_device = g_strdup(value);
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_str(oc, "sev-device",
+                                  qsev_guest_get_sev_device,
+                                  qsev_guest_set_sev_device,
+                                  NULL);
+    object_class_property_set_description(oc, "sev-device",
+            "SEV device to use", NULL);
+    object_class_property_add_str(oc, "dh-cert-file",
+                                  qsev_guest_get_dh_cert_file,
+                                  qsev_guest_set_dh_cert_file,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-cert-file",
+            "guest owners DH certificate (encoded with base64)", NULL);
+    object_class_property_add_str(oc, "session-file",
+                                  qsev_guest_get_session_file,
+                                  qsev_guest_set_session_file,
+                                  NULL);
+    object_class_property_set_description(oc, "session-file",
+            "guest owners session parameters (encoded with base64)", NULL);
+}
+
+static void
+qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, errp);
+    sev->handle = value;
+}
+
+static void
+qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, errp);
+    sev->policy = value;
+}
+
+static void
+qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    uint32_t value;
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    value = sev->policy;
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    uint32_t value;
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    value = sev->handle;
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_init(Object *obj)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
+    sev->policy = DEFAULT_GUEST_POLICY;
+    object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
+                        qsev_guest_set_policy, NULL, NULL, NULL);
+    object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
+                        qsev_guest_set_handle, NULL, NULL, NULL);
+}
+
+/* sev guest info */
+static const TypeInfo qsev_guest_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_GUEST_INFO,
+    .instance_size = sizeof(QSevGuestInfo),
+    .instance_finalize = qsev_guest_finalize,
+    .class_size = sizeof(QSevGuestInfoClass),
+    .class_init = qsev_guest_class_init,
+    .instance_init = qsev_guest_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+sev_register_types(void)
+{
+    type_register_static(&qsev_guest_info);
+}
+
+type_init(sev_register_types);
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
index 72a92b6c6353..1527f603ea2a 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/amd-memory-encryption.txt
@@ -35,10 +35,21 @@ in bad measurement). The guest policy is a 4-byte data structure containing
 several flags that restricts what can be done on running SEV guest.
 See KM Spec section 3 and 6.2 for more details.
 
+The guest policy can be provided via the 'policy' property (see below)
+
+# ${QEMU} \
+   sev-guest,id=sev0,policy=0x1...\
+
 Guest owners provided DH certificate and session parameters will be used to
 establish a cryptographic session with the guest owner to negotiate keys used
 for the attestation.
 
+The DH certificate and session blob can be provided via 'dh-cert-file' and
+'session-file' property (see below
+
+# ${QEMU} \
+     sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
+
 LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
 created via LAUNCH_START command. If required, this command can be called
 multiple times to encrypt different memory regions. The command also calculates
@@ -59,6 +70,12 @@ context.
 See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
 complete flow chart.
 
+To launch a SEV guest
+
+# ${QEMU} \
+    -machine ...,memory-encryption=sev0 \
+    -object sev-guest,id=sev0
+
 Debugging
 -----------
 Since memory contents of SEV guest is encrypted hence hypervisor access to the
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 000000000000..e00794ec1805
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU Secure Encrypted Virutualization (SEV) support
+ *
+ * Copyright: Advanced Micro Devices, 2016-2017
+ *
+ * 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 "qom/object.h"
+#include "qapi/error.h"
+#include "sysemu/kvm.h"
+#include "qemu/error-report.h"
+
+#define TYPE_QSEV_GUEST_INFO "sev-guest"
+#define QSEV_GUEST_INFO(obj)                  \
+    OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO)
+
+typedef struct QSevGuestInfo QSevGuestInfo;
+typedef struct QSevGuestInfoClass QSevGuestInfoClass;
+
+/**
+ * QSevGuestInfo:
+ *
+ * The QSevGuestInfo object is used for creating a SEV guest.
+ *
+ * # $QEMU \
+ *         -object sev-guest,id=sev0 \
+ *         -machine ...,memory-encryption=sev0
+ */
+struct QSevGuestInfo {
+    Object parent_obj;
+
+    char *sev_device;
+    uint32_t policy;
+    uint32_t handle;
+    char *dh_cert_file;
+    char *session_file;
+};
+
+struct QSevGuestInfoClass {
+    ObjectClass parent_class;
+};
+
+#endif
+
diff --git a/qemu-options.hx b/qemu-options.hx
index 5385832707e0..4611db3c1d51 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4470,6 +4470,40 @@ contents of @code{iv.b64} to the second secret
          data=$SECRET,iv=$(<iv.b64)
 @end example
 
+@item -object sev-guest,id=@var{id},sev-device=@var{string}[,policy=@var{policy},handle=@var{handle},dh-cert-file=@var{file},session-file=@var{file}]
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which can be used
+to provide the guest memory encryption support on AMD processors.
+
+The @option{sev-device} provides the device file to use for communicating with
+the SEV firmware running inside AMD Secure Processor. The default device is
+'/dev/sev'. If hardware supports memory encryption then /dev/sev devices are
+created by CCP driver.
+
+The @option{policy} provides the guest policy to be enforced by the SEV firmware
+and restrict what configuration and operational commands can be performed on this
+guest by the hypervisor. The policy should be provided by the guest owner and is
+bound to the guest and cannot be changed throughout the lifetime of the guest.
+The default is 0.
+
+If guest @option{policy} allows sharing the key with another SEV guest then
+@option{handle} can be use to provide handle of the guest from which to share
+the key.
+
+The @option{dh-cert-file} and @option{session-file} provides the guest owner's
+Public Diffie-Hillman key defined in SEV spec. The PDH and session parameters
+are used for establishing a cryptographic session with the guest owner to
+negotiate keys used for attestation. The file must be encoded in base64.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+     ......
+     -object sev-guest,id=sev0 \
+     -machine ...,memory-encryption=sev0
+     .....
+
+@end example
 @end table
 
 ETEXI
-- 
2.9.5

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

* [PATCH v5 10/23] sev: add command to initialize the memory encryption context
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

When memory encryption is enabled, KVM_SEV_INIT command is used to
initialize the platform. The command loads the SEV related persistent
data from non-volatile storage and initializes the platform context.
This command should be first issued before invoking any other guest
commands provided by the SEV firmware.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  15 +++++++
 accel/kvm/sev.c      | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  10 +++++
 3 files changed, 147 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f290f487a573..a9b16846675e 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -38,6 +38,7 @@
 #include "qemu/event_notifier.h"
 #include "trace.h"
 #include "hw/irq.h"
+#include "sysemu/sev.h"
 
 #include "hw/boards.h"
 
@@ -103,6 +104,9 @@ struct KVMState
 #endif
     KVMMemoryListener memory_listener;
     QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
+
+    /* memory encryption */
+    void *memcrypt_handle;
 };
 
 KVMState *kvm_state;
@@ -1632,6 +1636,17 @@ static int kvm_init(MachineState *ms)
 
     kvm_state = s;
 
+    /*
+     * if memory encryption object is specified then initialize the memory
+     * encryption context.
+     * */
+    if (ms->memory_encryption) {
+        kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption);
+        if (!kvm_state->memcrypt_handle) {
+            goto err;
+        }
+    }
+
     ret = kvm_arch_init(ms, s);
     if (ret < 0) {
         goto err;
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index a9b9a63c2da0..37020751bd14 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,67 @@
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
 
+static int sev_fd;
+
+#define SEV_FW_MAX_ERROR      0x17
+
+static char sev_fw_errlist[SEV_FW_MAX_ERROR][100] = {
+    "",
+    "Platform state is invalid",
+    "Guest state is invalid",
+    "Platform configuration is invalid",
+    "Buffer too small",
+    "Platform is already owned",
+    "Certificate is invalid",
+    "Policy is not allowed",
+    "Guest is not active",
+    "Invalid address",
+    "Bad signature",
+    "Bad measurement",
+    "Asid is already owned",
+    "Invalid ASID",
+    "WBINVD is required",
+    "DF_FLUSH is required",
+    "Guest handle is invalid",
+    "Invalid command",
+    "Guest is active",
+    "Hardware error",
+    "Hardware unsafe",
+    "Feature not supported",
+    "Invalid parameter"
+};
+
+static int
+sev_ioctl(int cmd, void *data, int *error)
+{
+    int r;
+    struct kvm_sev_cmd input;
+
+    memset(&input, 0x0, sizeof(input));
+
+    input.id = cmd;
+    input.sev_fd = sev_fd;
+    input.data = (__u64)data;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
+
+    if (error) {
+        *error = input.error;
+    }
+
+    return r;
+}
+
+static char *
+fw_error_to_str(int code)
+{
+    if (code > SEV_FW_MAX_ERROR) {
+        return NULL;
+    }
+
+    return sev_fw_errlist[code];
+}
+
 static void
 qsev_guest_finalize(Object *obj)
 {
@@ -170,6 +231,67 @@ static const TypeInfo qsev_guest_info = {
     }
 };
 
+static QSevGuestInfo *
+lookup_sev_guest_info(const char *id)
+{
+    Object *obj;
+    QSevGuestInfo *info;
+
+    obj = object_resolve_path_component(object_get_objects_root(), id);
+    if (!obj) {
+        return NULL;
+    }
+
+    info = (QSevGuestInfo *)
+            object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
+    if (!info) {
+        return NULL;
+    }
+
+    return info;
+}
+
+void *
+sev_guest_init(const char *id)
+{
+    SEVState *s;
+    char *devname;
+    int ret, fw_error;
+
+    s = g_malloc0(sizeof(SEVState));
+    if (!s) {
+        return NULL;
+    }
+
+    s->sev_info = lookup_sev_guest_info(id);
+    if (!s->sev_info) {
+        error_report("%s: '%s' is not a valid '%s' object",
+                     __func__, id, TYPE_QSEV_GUEST_INFO);
+        goto err;
+    }
+
+    devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
+    sev_fd = open(devname, O_RDWR);
+    if (sev_fd < 0) {
+        error_report("%s: Failed to open %s '%s'", __func__,
+                     devname, strerror(errno));
+        goto err;
+    }
+    g_free(devname);
+
+    ret = sev_ioctl(KVM_SEV_INIT, NULL, &fw_error);
+    if (ret) {
+        error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
+                     __func__, ret, fw_error, fw_error_to_str(fw_error));
+        goto err;
+    }
+
+    return s;
+err:
+    g_free(s);
+    return NULL;
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index e00794ec1805..f85517c0b5b5 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -14,6 +14,8 @@
 #ifndef QEMU_SEV_H
 #define QEMU_SEV_H
 
+#include <linux/kvm.h>
+
 #include "qom/object.h"
 #include "qapi/error.h"
 #include "sysemu/kvm.h"
@@ -49,5 +51,13 @@ struct QSevGuestInfoClass {
     ObjectClass parent_class;
 };
 
+struct SEVState {
+    QSevGuestInfo *sev_info;
+};
+
+typedef struct SEVState SEVState;
+
+void *sev_guest_init(const char *id);
+
 #endif
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 10/23] sev: add command to initialize the memory encryption context
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

When memory encryption is enabled, KVM_SEV_INIT command is used to
initialize the platform. The command loads the SEV related persistent
data from non-volatile storage and initializes the platform context.
This command should be first issued before invoking any other guest
commands provided by the SEV firmware.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  15 +++++++
 accel/kvm/sev.c      | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  10 +++++
 3 files changed, 147 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f290f487a573..a9b16846675e 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -38,6 +38,7 @@
 #include "qemu/event_notifier.h"
 #include "trace.h"
 #include "hw/irq.h"
+#include "sysemu/sev.h"
 
 #include "hw/boards.h"
 
@@ -103,6 +104,9 @@ struct KVMState
 #endif
     KVMMemoryListener memory_listener;
     QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
+
+    /* memory encryption */
+    void *memcrypt_handle;
 };
 
 KVMState *kvm_state;
@@ -1632,6 +1636,17 @@ static int kvm_init(MachineState *ms)
 
     kvm_state = s;
 
+    /*
+     * if memory encryption object is specified then initialize the memory
+     * encryption context.
+     * */
+    if (ms->memory_encryption) {
+        kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption);
+        if (!kvm_state->memcrypt_handle) {
+            goto err;
+        }
+    }
+
     ret = kvm_arch_init(ms, s);
     if (ret < 0) {
         goto err;
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index a9b9a63c2da0..37020751bd14 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,67 @@
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
 
+static int sev_fd;
+
+#define SEV_FW_MAX_ERROR      0x17
+
+static char sev_fw_errlist[SEV_FW_MAX_ERROR][100] = {
+    "",
+    "Platform state is invalid",
+    "Guest state is invalid",
+    "Platform configuration is invalid",
+    "Buffer too small",
+    "Platform is already owned",
+    "Certificate is invalid",
+    "Policy is not allowed",
+    "Guest is not active",
+    "Invalid address",
+    "Bad signature",
+    "Bad measurement",
+    "Asid is already owned",
+    "Invalid ASID",
+    "WBINVD is required",
+    "DF_FLUSH is required",
+    "Guest handle is invalid",
+    "Invalid command",
+    "Guest is active",
+    "Hardware error",
+    "Hardware unsafe",
+    "Feature not supported",
+    "Invalid parameter"
+};
+
+static int
+sev_ioctl(int cmd, void *data, int *error)
+{
+    int r;
+    struct kvm_sev_cmd input;
+
+    memset(&input, 0x0, sizeof(input));
+
+    input.id = cmd;
+    input.sev_fd = sev_fd;
+    input.data = (__u64)data;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
+
+    if (error) {
+        *error = input.error;
+    }
+
+    return r;
+}
+
+static char *
+fw_error_to_str(int code)
+{
+    if (code > SEV_FW_MAX_ERROR) {
+        return NULL;
+    }
+
+    return sev_fw_errlist[code];
+}
+
 static void
 qsev_guest_finalize(Object *obj)
 {
@@ -170,6 +231,67 @@ static const TypeInfo qsev_guest_info = {
     }
 };
 
+static QSevGuestInfo *
+lookup_sev_guest_info(const char *id)
+{
+    Object *obj;
+    QSevGuestInfo *info;
+
+    obj = object_resolve_path_component(object_get_objects_root(), id);
+    if (!obj) {
+        return NULL;
+    }
+
+    info = (QSevGuestInfo *)
+            object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
+    if (!info) {
+        return NULL;
+    }
+
+    return info;
+}
+
+void *
+sev_guest_init(const char *id)
+{
+    SEVState *s;
+    char *devname;
+    int ret, fw_error;
+
+    s = g_malloc0(sizeof(SEVState));
+    if (!s) {
+        return NULL;
+    }
+
+    s->sev_info = lookup_sev_guest_info(id);
+    if (!s->sev_info) {
+        error_report("%s: '%s' is not a valid '%s' object",
+                     __func__, id, TYPE_QSEV_GUEST_INFO);
+        goto err;
+    }
+
+    devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
+    sev_fd = open(devname, O_RDWR);
+    if (sev_fd < 0) {
+        error_report("%s: Failed to open %s '%s'", __func__,
+                     devname, strerror(errno));
+        goto err;
+    }
+    g_free(devname);
+
+    ret = sev_ioctl(KVM_SEV_INIT, NULL, &fw_error);
+    if (ret) {
+        error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
+                     __func__, ret, fw_error, fw_error_to_str(fw_error));
+        goto err;
+    }
+
+    return s;
+err:
+    g_free(s);
+    return NULL;
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index e00794ec1805..f85517c0b5b5 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -14,6 +14,8 @@
 #ifndef QEMU_SEV_H
 #define QEMU_SEV_H
 
+#include <linux/kvm.h>
+
 #include "qom/object.h"
 #include "qapi/error.h"
 #include "sysemu/kvm.h"
@@ -49,5 +51,13 @@ struct QSevGuestInfoClass {
     ObjectClass parent_class;
 };
 
+struct SEVState {
+    QSevGuestInfo *sev_info;
+};
+
+typedef struct SEVState SEVState;
+
+void *sev_guest_init(const char *id);
+
 #endif
 
-- 
2.9.5

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

* [PATCH v5 11/23] sev: register the guest memory range which may contain encrypted data
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

When SEV is enabled, the hardware encryption engine uses a tweak such
that the two identical plaintext at different location will have a
different ciphertexts. So swapping or moving a ciphertexts of two guest
pages will not result in plaintexts being swapped. Hence relocating
a physical backing pages of the SEV guest will require some additional
steps in KVM driver. The KVM_MEMORY_ENCRYPT_{UN,}REG_REGION ioctl can be
used to register/unregister the guest memory region which may contain the
encrypted data. KVM driver will internally handle the relocating physical
backing pages of registered memory regions.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 37020751bd14..7b5318993969 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -84,6 +84,43 @@ fw_error_to_str(int code)
 }
 
 static void
+sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
+{
+    int r;
+    struct kvm_enc_region range;
+
+    range.addr = (__u64)host;
+    range.size = size;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
+    if (r) {
+        error_report("%s: failed to register region (%#llx+%#llx)",
+                     __func__, range.addr, range.size);
+    }
+}
+
+static void
+sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
+{
+    int r;
+    struct kvm_enc_region range;
+
+    range.addr = (__u64)host;
+    range.size = size;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
+    if (r) {
+        error_report("%s: failed to unregister region (%#llx+%#llx)",
+                     __func__, range.addr, range.size);
+    }
+}
+
+static struct RAMBlockNotifier sev_ram_notifier = {
+    .ram_block_added = sev_ram_block_added,
+    .ram_block_removed = sev_ram_block_removed,
+};
+
+static void
 qsev_guest_finalize(Object *obj)
 {
 }
@@ -286,6 +323,8 @@ sev_guest_init(const char *id)
         goto err;
     }
 
+    ram_block_notifier_add(&sev_ram_notifier);
+
     return s;
 err:
     g_free(s);
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 11/23] sev: register the guest memory range which may contain encrypted data
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

When SEV is enabled, the hardware encryption engine uses a tweak such
that the two identical plaintext at different location will have a
different ciphertexts. So swapping or moving a ciphertexts of two guest
pages will not result in plaintexts being swapped. Hence relocating
a physical backing pages of the SEV guest will require some additional
steps in KVM driver. The KVM_MEMORY_ENCRYPT_{UN,}REG_REGION ioctl can be
used to register/unregister the guest memory region which may contain the
encrypted data. KVM driver will internally handle the relocating physical
backing pages of registered memory regions.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 37020751bd14..7b5318993969 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -84,6 +84,43 @@ fw_error_to_str(int code)
 }
 
 static void
+sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
+{
+    int r;
+    struct kvm_enc_region range;
+
+    range.addr = (__u64)host;
+    range.size = size;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
+    if (r) {
+        error_report("%s: failed to register region (%#llx+%#llx)",
+                     __func__, range.addr, range.size);
+    }
+}
+
+static void
+sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
+{
+    int r;
+    struct kvm_enc_region range;
+
+    range.addr = (__u64)host;
+    range.size = size;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
+    if (r) {
+        error_report("%s: failed to unregister region (%#llx+%#llx)",
+                     __func__, range.addr, range.size);
+    }
+}
+
+static struct RAMBlockNotifier sev_ram_notifier = {
+    .ram_block_added = sev_ram_block_added,
+    .ram_block_removed = sev_ram_block_removed,
+};
+
+static void
 qsev_guest_finalize(Object *obj)
 {
 }
@@ -286,6 +323,8 @@ sev_guest_init(const char *id)
         goto err;
     }
 
+    ram_block_notifier_add(&sev_ram_notifier);
+
     return s;
 err:
     g_free(s);
-- 
2.9.5

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

* [PATCH v5 12/23] kvm: introduce memory encryption APIs
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Inorder to integerate the Secure Encryption Virtualization (SEV) support
add few high-level memory encryption APIs which can be used for encrypting
the guest memory region.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c    | 30 ++++++++++++++++++++++++++++++
 accel/stubs/kvm-stub.c | 14 ++++++++++++++
 include/sysemu/kvm.h   | 25 +++++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index a9b16846675e..54a0fd6097fb 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -107,6 +107,8 @@ struct KVMState
 
     /* memory encryption */
     void *memcrypt_handle;
+    int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
+    void (*memcrypt_debug_ops)(void *handle, MemoryRegion *mr);
 };
 
 KVMState *kvm_state;
@@ -142,6 +144,34 @@ int kvm_get_max_memslots(void)
     return s->nr_slots;
 }
 
+bool kvm_memcrypt_enabled(void)
+{
+    if (kvm_state && kvm_state->memcrypt_handle) {
+        return true;
+    }
+
+    return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+    if (kvm_state->memcrypt_handle &&
+        kvm_state->memcrypt_encrypt_data) {
+        return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle,
+                                              ptr, len);
+    }
+
+    return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+    if (kvm_state->memcrypt_handle &&
+        kvm_state->memcrypt_debug_ops) {
+        kvm_state->memcrypt_debug_ops(kvm_state->memcrypt_handle, mr);
+    }
+}
+
 static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
 {
     KVMState *s = kvm_state;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index c964af3e1c97..5739712a67e3 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -105,6 +105,20 @@ int kvm_on_sigbus(int code, void *addr)
     return 1;
 }
 
+bool kvm_memcrypt_enabled(void)
+{
+    return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+  return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+}
+
 #ifndef CONFIG_USER_ONLY
 int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
 {
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bbf12a172339..4a5db5dde390 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -231,6 +231,31 @@ int kvm_destroy_vcpu(CPUState *cpu);
  */
 bool kvm_arm_supports_user_irq(void);
 
+/**
+ * kvm_memcrypt_enabled - return boolean indicating whether memory encryption
+ *                        is enabled
+ * Returns: 1 memory encryption is enabled
+ *          0 memory encryption is disabled
+ */
+bool kvm_memcrypt_enabled(void);
+
+/**
+ * kvm_memcrypt_encrypt_data: encrypt the memory range
+ *
+ * Return: 1 failed to encrypt the range
+ *         0 succesfully encrypted memory region
+ */
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len);
+
+/**
+ * kvm_memcrypt_set_debug_ram_ops: set debug_ram_ops callback
+ *
+ * When debug_ram_ops is set, debug access to this memory region will use
+ * memory encryption APIs.
+ */
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr);
+
+
 #ifdef NEED_CPU_H
 #include "cpu.h"
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 12/23] kvm: introduce memory encryption APIs
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Inorder to integerate the Secure Encryption Virtualization (SEV) support
add few high-level memory encryption APIs which can be used for encrypting
the guest memory region.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c    | 30 ++++++++++++++++++++++++++++++
 accel/stubs/kvm-stub.c | 14 ++++++++++++++
 include/sysemu/kvm.h   | 25 +++++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index a9b16846675e..54a0fd6097fb 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -107,6 +107,8 @@ struct KVMState
 
     /* memory encryption */
     void *memcrypt_handle;
+    int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
+    void (*memcrypt_debug_ops)(void *handle, MemoryRegion *mr);
 };
 
 KVMState *kvm_state;
@@ -142,6 +144,34 @@ int kvm_get_max_memslots(void)
     return s->nr_slots;
 }
 
+bool kvm_memcrypt_enabled(void)
+{
+    if (kvm_state && kvm_state->memcrypt_handle) {
+        return true;
+    }
+
+    return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+    if (kvm_state->memcrypt_handle &&
+        kvm_state->memcrypt_encrypt_data) {
+        return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle,
+                                              ptr, len);
+    }
+
+    return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+    if (kvm_state->memcrypt_handle &&
+        kvm_state->memcrypt_debug_ops) {
+        kvm_state->memcrypt_debug_ops(kvm_state->memcrypt_handle, mr);
+    }
+}
+
 static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
 {
     KVMState *s = kvm_state;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index c964af3e1c97..5739712a67e3 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -105,6 +105,20 @@ int kvm_on_sigbus(int code, void *addr)
     return 1;
 }
 
+bool kvm_memcrypt_enabled(void)
+{
+    return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+  return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+}
+
 #ifndef CONFIG_USER_ONLY
 int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
 {
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bbf12a172339..4a5db5dde390 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -231,6 +231,31 @@ int kvm_destroy_vcpu(CPUState *cpu);
  */
 bool kvm_arm_supports_user_irq(void);
 
+/**
+ * kvm_memcrypt_enabled - return boolean indicating whether memory encryption
+ *                        is enabled
+ * Returns: 1 memory encryption is enabled
+ *          0 memory encryption is disabled
+ */
+bool kvm_memcrypt_enabled(void);
+
+/**
+ * kvm_memcrypt_encrypt_data: encrypt the memory range
+ *
+ * Return: 1 failed to encrypt the range
+ *         0 succesfully encrypted memory region
+ */
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len);
+
+/**
+ * kvm_memcrypt_set_debug_ram_ops: set debug_ram_ops callback
+ *
+ * When debug_ram_ops is set, debug access to this memory region will use
+ * memory encryption APIs.
+ */
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr);
+
+
 #ifdef NEED_CPU_H
 #include "cpu.h"
 
-- 
2.9.5

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

* [PATCH v5 13/23] hmp: display memory encryption support in 'info kvm'
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

update 'info kvm' to display the memory encryption support.

(qemu) info kvm
kvm support: enabled
memory encryption: disabled

Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hmp.c            | 2 ++
 qapi-schema.json | 5 ++++-
 qmp.c            | 1 +
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/hmp.c b/hmp.c
index 35a704182494..3184ed5d1550 100644
--- a/hmp.c
+++ b/hmp.c
@@ -88,6 +88,8 @@ void hmp_info_kvm(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "kvm support: ");
     if (info->present) {
         monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
+        monitor_printf(mon, "memory encryption: %s\n",
+                       info->mem_encryption ? "enabled" : "disabled");
     } else {
         monitor_printf(mon, "not compiled\n");
     }
diff --git a/qapi-schema.json b/qapi-schema.json
index 18457954a841..7eec403cd34a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -314,9 +314,12 @@
 #
 # @present: true if KVM acceleration is built into this executable
 #
+# @mem-encryption: true if Memory Encryption is active (since 2.11)
+#
 # Since: 0.14.0
 ##
-{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool',
+            'mem-encryption' : 'bool'} }
 
 ##
 # @query-kvm:
diff --git a/qmp.c b/qmp.c
index e8c303116af2..baf367af55c0 100644
--- a/qmp.c
+++ b/qmp.c
@@ -69,6 +69,7 @@ KvmInfo *qmp_query_kvm(Error **errp)
 
     info->enabled = kvm_enabled();
     info->present = kvm_available();
+    info->mem_encryption = kvm_memcrypt_enabled();
 
     return info;
 }
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 13/23] hmp: display memory encryption support in 'info kvm'
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

update 'info kvm' to display the memory encryption support.

(qemu) info kvm
kvm support: enabled
memory encryption: disabled

Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hmp.c            | 2 ++
 qapi-schema.json | 5 ++++-
 qmp.c            | 1 +
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/hmp.c b/hmp.c
index 35a704182494..3184ed5d1550 100644
--- a/hmp.c
+++ b/hmp.c
@@ -88,6 +88,8 @@ void hmp_info_kvm(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "kvm support: ");
     if (info->present) {
         monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
+        monitor_printf(mon, "memory encryption: %s\n",
+                       info->mem_encryption ? "enabled" : "disabled");
     } else {
         monitor_printf(mon, "not compiled\n");
     }
diff --git a/qapi-schema.json b/qapi-schema.json
index 18457954a841..7eec403cd34a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -314,9 +314,12 @@
 #
 # @present: true if KVM acceleration is built into this executable
 #
+# @mem-encryption: true if Memory Encryption is active (since 2.11)
+#
 # Since: 0.14.0
 ##
-{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool',
+            'mem-encryption' : 'bool'} }
 
 ##
 # @query-kvm:
diff --git a/qmp.c b/qmp.c
index e8c303116af2..baf367af55c0 100644
--- a/qmp.c
+++ b/qmp.c
@@ -69,6 +69,7 @@ KvmInfo *qmp_query_kvm(Error **errp)
 
     info->enabled = kvm_enabled();
     info->present = kvm_available();
+    info->mem_encryption = kvm_memcrypt_enabled();
 
     return info;
 }
-- 
2.9.5

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

* [PATCH v5 14/23] sev: add command to create launch memory encryption context
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

The KVM_SEV_LAUNCH_START command creates a new VM encryption key (VEK).
The encryption key created with the command will be used for encrypting
the bootstrap images (such as guest bios).

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c      | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h | 11 +++++++
 2 files changed, 97 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 7b5318993969..74eb67526bd0 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,15 @@
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
 
+#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
+
 static int sev_fd;
 
 #define SEV_FW_MAX_ERROR      0x17
@@ -288,6 +297,77 @@ lookup_sev_guest_info(const char *id)
     return info;
 }
 
+static int
+sev_read_file_base64(const char *filename, guchar **data, gsize *len)
+{
+    gsize sz;
+    gchar *base64;
+    GError *error = NULL;
+
+    if (!g_file_get_contents(filename, &base64, &sz, &error)) {
+        error_report("failed to read '%s' (%s)", filename, error->message);
+        return -1;
+    }
+
+    *data = g_base64_decode(base64, len);
+    return 0;
+}
+
+static int
+sev_launch_start(SEVState *s)
+{
+    gsize sz;
+    int ret = 1;
+    int fw_error;
+    QSevGuestInfo *sev = s->sev_info;
+    struct kvm_sev_launch_start *start;
+    guchar *session = NULL, *dh_cert = NULL;
+
+    start = g_malloc0(sizeof(*start));
+    if (!start) {
+        return 1;
+    }
+
+    start->handle = object_property_get_int(OBJECT(sev), "handle",
+                                            &error_abort);
+    start->policy = object_property_get_int(OBJECT(sev), "policy",
+                                            &error_abort);
+    if (sev->session_file) {
+        if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
+            return 1;
+        }
+        start->session_uaddr = (unsigned long)session;
+        start->session_len = sz;
+    }
+
+    if (sev->dh_cert_file) {
+        if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
+            return 1;
+        }
+        start->dh_uaddr = (unsigned long)dh_cert;
+        start->dh_len = sz;
+    }
+
+    ret = sev_ioctl(KVM_SEV_LAUNCH_START, start, &fw_error);
+    if (ret < 0) {
+        error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
+                __func__, ret, fw_error, fw_error_to_str(fw_error));
+        return 1;
+    }
+
+    DPRINTF("SEV: LAUNCH_START\n");
+
+    object_property_set_int(OBJECT(sev), start->handle, "handle",
+                            &error_abort);
+    s->cur_state = SEV_STATE_LUPDATE;
+
+    g_free(start);
+    g_free(session);
+    g_free(dh_cert);
+
+    return 0;
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -323,6 +403,12 @@ sev_guest_init(const char *id)
         goto err;
     }
 
+    ret = sev_launch_start(s);
+    if (ret) {
+        error_report("%s: failed to create encryption context", __func__);
+        goto err;
+    }
+
     ram_block_notifier_add(&sev_ram_notifier);
 
     return s;
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index f85517c0b5b5..45b464cc96f5 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -51,8 +51,19 @@ struct QSevGuestInfoClass {
     ObjectClass parent_class;
 };
 
+enum {
+    SEV_STATE_INVALID = 0,
+    SEV_STATE_LUPDATE,
+    SEV_STATE_SECRET,
+    SEV_STATE_RUNNING,
+    SEV_STATE_SENDING,
+    SEV_STATE_RECEIVING,
+    SEV_STATE_MAX
+};
+
 struct SEVState {
     QSevGuestInfo *sev_info;
+    int cur_state;
 };
 
 typedef struct SEVState SEVState;
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 14/23] sev: add command to create launch memory encryption context
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

The KVM_SEV_LAUNCH_START command creates a new VM encryption key (VEK).
The encryption key created with the command will be used for encrypting
the bootstrap images (such as guest bios).

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c      | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h | 11 +++++++
 2 files changed, 97 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 7b5318993969..74eb67526bd0 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,15 @@
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
 
+#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
+
 static int sev_fd;
 
 #define SEV_FW_MAX_ERROR      0x17
@@ -288,6 +297,77 @@ lookup_sev_guest_info(const char *id)
     return info;
 }
 
+static int
+sev_read_file_base64(const char *filename, guchar **data, gsize *len)
+{
+    gsize sz;
+    gchar *base64;
+    GError *error = NULL;
+
+    if (!g_file_get_contents(filename, &base64, &sz, &error)) {
+        error_report("failed to read '%s' (%s)", filename, error->message);
+        return -1;
+    }
+
+    *data = g_base64_decode(base64, len);
+    return 0;
+}
+
+static int
+sev_launch_start(SEVState *s)
+{
+    gsize sz;
+    int ret = 1;
+    int fw_error;
+    QSevGuestInfo *sev = s->sev_info;
+    struct kvm_sev_launch_start *start;
+    guchar *session = NULL, *dh_cert = NULL;
+
+    start = g_malloc0(sizeof(*start));
+    if (!start) {
+        return 1;
+    }
+
+    start->handle = object_property_get_int(OBJECT(sev), "handle",
+                                            &error_abort);
+    start->policy = object_property_get_int(OBJECT(sev), "policy",
+                                            &error_abort);
+    if (sev->session_file) {
+        if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
+            return 1;
+        }
+        start->session_uaddr = (unsigned long)session;
+        start->session_len = sz;
+    }
+
+    if (sev->dh_cert_file) {
+        if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
+            return 1;
+        }
+        start->dh_uaddr = (unsigned long)dh_cert;
+        start->dh_len = sz;
+    }
+
+    ret = sev_ioctl(KVM_SEV_LAUNCH_START, start, &fw_error);
+    if (ret < 0) {
+        error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
+                __func__, ret, fw_error, fw_error_to_str(fw_error));
+        return 1;
+    }
+
+    DPRINTF("SEV: LAUNCH_START\n");
+
+    object_property_set_int(OBJECT(sev), start->handle, "handle",
+                            &error_abort);
+    s->cur_state = SEV_STATE_LUPDATE;
+
+    g_free(start);
+    g_free(session);
+    g_free(dh_cert);
+
+    return 0;
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -323,6 +403,12 @@ sev_guest_init(const char *id)
         goto err;
     }
 
+    ret = sev_launch_start(s);
+    if (ret) {
+        error_report("%s: failed to create encryption context", __func__);
+        goto err;
+    }
+
     ram_block_notifier_add(&sev_ram_notifier);
 
     return s;
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index f85517c0b5b5..45b464cc96f5 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -51,8 +51,19 @@ struct QSevGuestInfoClass {
     ObjectClass parent_class;
 };
 
+enum {
+    SEV_STATE_INVALID = 0,
+    SEV_STATE_LUPDATE,
+    SEV_STATE_SECRET,
+    SEV_STATE_RUNNING,
+    SEV_STATE_SENDING,
+    SEV_STATE_RECEIVING,
+    SEV_STATE_MAX
+};
+
 struct SEVState {
     QSevGuestInfo *sev_info;
+    int cur_state;
 };
 
 typedef struct SEVState SEVState;
-- 
2.9.5

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

* [PATCH v5 15/23] sev: add command to encrypt guest memory region
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

The KVM_SEV_LAUNCH_UPDATE_DATA command is used to encrypt a guest memory
region using the VM Encryption Key created using LAUNCH_START.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  2 ++
 accel/kvm/sev.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 3 files changed, 47 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 54a0fd6097fb..d35eebb97901 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1675,6 +1675,8 @@ static int kvm_init(MachineState *ms)
         if (!kvm_state->memcrypt_handle) {
             goto err;
         }
+
+        kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
     }
 
     ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 74eb67526bd0..83fc950bd3ac 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -368,6 +368,37 @@ sev_launch_start(SEVState *s)
     return 0;
 }
 
+static int
+sev_launch_update_data(uint8_t *addr, uint64_t len)
+{
+    int ret, fw_error;
+    struct kvm_sev_launch_update_data *update;
+
+    if (addr == NULL || len <= 0) {
+        return 1;
+    }
+
+    update = g_malloc0(sizeof(*update));
+    if (!update) {
+        return 1;
+    }
+
+    update->uaddr = (__u64)addr;
+    update->len = len;
+    ret = sev_ioctl(KVM_SEV_LAUNCH_UPDATE_DATA, update, &fw_error);
+    if (ret) {
+        error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
+                __func__, ret, fw_error, fw_error_to_str(fw_error));
+        goto err;
+    }
+
+    DPRINTF("SEV: LAUNCH_UPDATE_DATA %#lx+%#lx\n", (unsigned long)addr, len);
+
+err:
+    g_free(update);
+    return ret;
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -417,6 +448,19 @@ err:
     return NULL;
 }
 
+int
+sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
+{
+    SEVState *s = (SEVState *)handle;
+
+    /* if SEV is in update state then encrypt the data else do nothing */
+    if (s->cur_state == SEV_STATE_LUPDATE) {
+        return sev_launch_update_data(ptr, len);
+    }
+
+    return 0;
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 45b464cc96f5..b1ea3f805290 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -69,6 +69,7 @@ struct SEVState {
 typedef struct SEVState SEVState;
 
 void *sev_guest_init(const char *id);
+int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
 
 #endif
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 15/23] sev: add command to encrypt guest memory region
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

The KVM_SEV_LAUNCH_UPDATE_DATA command is used to encrypt a guest memory
region using the VM Encryption Key created using LAUNCH_START.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  2 ++
 accel/kvm/sev.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 3 files changed, 47 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 54a0fd6097fb..d35eebb97901 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1675,6 +1675,8 @@ static int kvm_init(MachineState *ms)
         if (!kvm_state->memcrypt_handle) {
             goto err;
         }
+
+        kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
     }
 
     ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 74eb67526bd0..83fc950bd3ac 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -368,6 +368,37 @@ sev_launch_start(SEVState *s)
     return 0;
 }
 
+static int
+sev_launch_update_data(uint8_t *addr, uint64_t len)
+{
+    int ret, fw_error;
+    struct kvm_sev_launch_update_data *update;
+
+    if (addr == NULL || len <= 0) {
+        return 1;
+    }
+
+    update = g_malloc0(sizeof(*update));
+    if (!update) {
+        return 1;
+    }
+
+    update->uaddr = (__u64)addr;
+    update->len = len;
+    ret = sev_ioctl(KVM_SEV_LAUNCH_UPDATE_DATA, update, &fw_error);
+    if (ret) {
+        error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
+                __func__, ret, fw_error, fw_error_to_str(fw_error));
+        goto err;
+    }
+
+    DPRINTF("SEV: LAUNCH_UPDATE_DATA %#lx+%#lx\n", (unsigned long)addr, len);
+
+err:
+    g_free(update);
+    return ret;
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -417,6 +448,19 @@ err:
     return NULL;
 }
 
+int
+sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
+{
+    SEVState *s = (SEVState *)handle;
+
+    /* if SEV is in update state then encrypt the data else do nothing */
+    if (s->cur_state == SEV_STATE_LUPDATE) {
+        return sev_launch_update_data(ptr, len);
+    }
+
+    return 0;
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 45b464cc96f5..b1ea3f805290 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -69,6 +69,7 @@ struct SEVState {
 typedef struct SEVState SEVState;
 
 void *sev_guest_init(const char *id);
+int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
 
 #endif
 
-- 
2.9.5

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

* [PATCH v5 16/23] target/i386: encrypt bios rom
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

SEV requires that guest bios must be encrypted before booting the guest.

Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc_sysfw.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 6b183747fcea..8ddbbf74d330 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -112,6 +112,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
     pflash_t *system_flash;
     MemoryRegion *flash_mem;
     char name[64];
+    void *flash_ptr;
+    int ret, flash_size;
 
     sector_bits = 12;
     sector_size = 1 << sector_bits;
@@ -168,6 +170,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
         if (unit == 0) {
             flash_mem = pflash_cfi01_get_memory(system_flash);
             pc_isa_bios_init(rom_memory, flash_mem, size);
+
+            /* Encrypt the pflash boot ROM */
+            if (kvm_memcrypt_enabled()) {
+                flash_ptr = memory_region_get_ram_ptr(flash_mem);
+                flash_size = memory_region_size(flash_mem);
+                ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
+                if (ret) {
+                    error_report("failed to encrypt pflash rom");
+                    exit(1);
+                }
+            }
         }
     }
 }
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 16/23] target/i386: encrypt bios rom
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

SEV requires that guest bios must be encrypted before booting the guest.

Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc_sysfw.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 6b183747fcea..8ddbbf74d330 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -112,6 +112,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
     pflash_t *system_flash;
     MemoryRegion *flash_mem;
     char name[64];
+    void *flash_ptr;
+    int ret, flash_size;
 
     sector_bits = 12;
     sector_size = 1 << sector_bits;
@@ -168,6 +170,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
         if (unit == 0) {
             flash_mem = pflash_cfi01_get_memory(system_flash);
             pc_isa_bios_init(rom_memory, flash_mem, size);
+
+            /* Encrypt the pflash boot ROM */
+            if (kvm_memcrypt_enabled()) {
+                flash_ptr = memory_region_get_ram_ptr(flash_mem);
+                flash_size = memory_region_size(flash_mem);
+                ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
+                if (ret) {
+                    error_report("failed to encrypt pflash rom");
+                    exit(1);
+                }
+            }
         }
     }
 }
-- 
2.9.5

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

* [PATCH v5 17/23] qapi: add SEV_MEASUREMENT event
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

Add SEV_MEASUREMENT event which can be used by libvirt to get the
measurement of the memory regions encrypted through the SEV launch
flow. The measurement value is base64 encoded.

Cc: Daniel P. Berrange <berrange@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 qapi-schema.json | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index 7eec403cd34a..f63659eda45b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3203,3 +3203,16 @@
 # Since: 2.11
 ##
 { 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
+##
+# @SEV_MEASUREMENT:
+#
+# Emitted when measurement is available for the SEV guest.
+#
+# @value: measurement value encoded in base64
+#
+# Since: 2.11
+#
+##
+{ 'event' : 'SEV_MEASUREMENT',
+  'data' : { 'value' : 'str' } }
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 17/23] qapi: add SEV_MEASUREMENT event
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

Add SEV_MEASUREMENT event which can be used by libvirt to get the
measurement of the memory regions encrypted through the SEV launch
flow. The measurement value is base64 encoded.

Cc: Daniel P. Berrange <berrange@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 qapi-schema.json | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index 7eec403cd34a..f63659eda45b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3203,3 +3203,16 @@
 # Since: 2.11
 ##
 { 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
+##
+# @SEV_MEASUREMENT:
+#
+# Emitted when measurement is available for the SEV guest.
+#
+# @value: measurement value encoded in base64
+#
+# Since: 2.11
+#
+##
+{ 'event' : 'SEV_MEASUREMENT',
+  'data' : { 'value' : 'str' } }
-- 
2.9.5

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

* [PATCH v5 18/23] sev: emit the SEV_MEASUREMENT event
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

During machine creation we encrypted the guest bios image, the
LAUNCH_MEASURE command can be used to retrieve the measurement of
the encrypted memory region. Emit the SEV_MEASUREMENT event so that
libvirt can grab the measurement value as soon as we are done with
creating the encrypted machine.

Cc: Daniel P. Berrange <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c      | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 2 files changed, 59 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 83fc950bd3ac..c0eea371fa06 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -18,6 +18,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/sev.h"
 #include "sysemu/sysemu.h"
+#include "qapi-event.h"
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
@@ -32,6 +33,7 @@
 #endif
 
 static int sev_fd;
+static SEVState *sev_state;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -399,6 +401,59 @@ err:
     return ret;
 }
 
+static void
+sev_launch_get_measure(Notifier *notifier, void *unused)
+{
+    int ret, error;
+    guchar *data;
+    SEVState *s = sev_state;
+    struct kvm_sev_launch_measure *measurement;
+
+    measurement = g_malloc0(sizeof(*measurement));
+    if (!measurement) {
+        return;
+    }
+
+    /* query the measurement blob length */
+    ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+    if (!measurement->len) {
+        error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(errno));
+        goto free_measurement;
+    }
+
+    s->cur_state = SEV_STATE_SECRET;
+
+    data = g_malloc(measurement->len);
+    if (s->measurement) {
+        goto free_data;
+    }
+
+    measurement->uaddr = (unsigned long)data;
+
+    /* get the measurement blob */
+    ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+    if (ret) {
+        error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(errno));
+        goto free_data;
+    }
+
+    s->measurement = g_base64_encode(data, measurement->len);
+
+    DPRINTF("SEV: MEASUREMENT: %s\n", s->measurement);
+    qapi_event_send_sev_measurement(s->measurement, &error_abort);
+
+free_data:
+    g_free(data);
+free_measurement:
+    g_free(measurement);
+}
+
+static Notifier sev_machine_done_notify = {
+    .notify = sev_launch_get_measure,
+};
+
 void *
 sev_guest_init(const char *id)
 {
@@ -441,6 +496,9 @@ sev_guest_init(const char *id)
     }
 
     ram_block_notifier_add(&sev_ram_notifier);
+    qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+
+    sev_state = s;
 
     return s;
 err:
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index b1ea3f805290..3af945935b60 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -64,6 +64,7 @@ enum {
 struct SEVState {
     QSevGuestInfo *sev_info;
     int cur_state;
+    gchar *measurement;
 };
 
 typedef struct SEVState SEVState;
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 18/23] sev: emit the SEV_MEASUREMENT event
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

During machine creation we encrypted the guest bios image, the
LAUNCH_MEASURE command can be used to retrieve the measurement of
the encrypted memory region. Emit the SEV_MEASUREMENT event so that
libvirt can grab the measurement value as soon as we are done with
creating the encrypted machine.

Cc: Daniel P. Berrange <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c      | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 2 files changed, 59 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 83fc950bd3ac..c0eea371fa06 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -18,6 +18,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/sev.h"
 #include "sysemu/sysemu.h"
+#include "qapi-event.h"
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
@@ -32,6 +33,7 @@
 #endif
 
 static int sev_fd;
+static SEVState *sev_state;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -399,6 +401,59 @@ err:
     return ret;
 }
 
+static void
+sev_launch_get_measure(Notifier *notifier, void *unused)
+{
+    int ret, error;
+    guchar *data;
+    SEVState *s = sev_state;
+    struct kvm_sev_launch_measure *measurement;
+
+    measurement = g_malloc0(sizeof(*measurement));
+    if (!measurement) {
+        return;
+    }
+
+    /* query the measurement blob length */
+    ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+    if (!measurement->len) {
+        error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(errno));
+        goto free_measurement;
+    }
+
+    s->cur_state = SEV_STATE_SECRET;
+
+    data = g_malloc(measurement->len);
+    if (s->measurement) {
+        goto free_data;
+    }
+
+    measurement->uaddr = (unsigned long)data;
+
+    /* get the measurement blob */
+    ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+    if (ret) {
+        error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(errno));
+        goto free_data;
+    }
+
+    s->measurement = g_base64_encode(data, measurement->len);
+
+    DPRINTF("SEV: MEASUREMENT: %s\n", s->measurement);
+    qapi_event_send_sev_measurement(s->measurement, &error_abort);
+
+free_data:
+    g_free(data);
+free_measurement:
+    g_free(measurement);
+}
+
+static Notifier sev_machine_done_notify = {
+    .notify = sev_launch_get_measure,
+};
+
 void *
 sev_guest_init(const char *id)
 {
@@ -441,6 +496,9 @@ sev_guest_init(const char *id)
     }
 
     ram_block_notifier_add(&sev_ram_notifier);
+    qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+
+    sev_state = s;
 
     return s;
 err:
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index b1ea3f805290..3af945935b60 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -64,6 +64,7 @@ enum {
 struct SEVState {
     QSevGuestInfo *sev_info;
     int cur_state;
+    gchar *measurement;
 };
 
 typedef struct SEVState SEVState;
-- 
2.9.5

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

* [PATCH v5 19/23] sev: Finalize the SEV guest launch flow
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

SEV launch flow requires us to issue LAUNCH_FINISH command before guest
is ready to run.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index c0eea371fa06..fbbd99becc0a 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -454,6 +454,35 @@ static Notifier sev_machine_done_notify = {
     .notify = sev_launch_get_measure,
 };
 
+static void
+sev_launch_finish(SEVState *s)
+{
+    int ret, error;
+
+    ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
+    if (ret) {
+        error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(error));
+        exit(1);
+    }
+
+    s->cur_state = SEV_STATE_RUNNING;
+    DPRINTF("SEV: LAUNCH_FINISH\n");
+}
+
+static void
+sev_vm_state_change(void *opaque, int running, RunState state)
+{
+    SEVState *s = opaque;
+
+    if (running) {
+        /* we are about to resume the guest, finalize the launch flow */
+        if (s->cur_state == SEV_STATE_SECRET) {
+            sev_launch_finish(s);
+        }
+    }
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -497,6 +526,7 @@ sev_guest_init(const char *id)
 
     ram_block_notifier_add(&sev_ram_notifier);
     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+    qemu_add_vm_change_state_handler(sev_vm_state_change, s);
 
     sev_state = s;
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 19/23] sev: Finalize the SEV guest launch flow
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

SEV launch flow requires us to issue LAUNCH_FINISH command before guest
is ready to run.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index c0eea371fa06..fbbd99becc0a 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -454,6 +454,35 @@ static Notifier sev_machine_done_notify = {
     .notify = sev_launch_get_measure,
 };
 
+static void
+sev_launch_finish(SEVState *s)
+{
+    int ret, error;
+
+    ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
+    if (ret) {
+        error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
+                     __func__, ret, error, fw_error_to_str(error));
+        exit(1);
+    }
+
+    s->cur_state = SEV_STATE_RUNNING;
+    DPRINTF("SEV: LAUNCH_FINISH\n");
+}
+
+static void
+sev_vm_state_change(void *opaque, int running, RunState state)
+{
+    SEVState *s = opaque;
+
+    if (running) {
+        /* we are about to resume the guest, finalize the launch flow */
+        if (s->cur_state == SEV_STATE_SECRET) {
+            sev_launch_finish(s);
+        }
+    }
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -497,6 +526,7 @@ sev_guest_init(const char *id)
 
     ram_block_notifier_add(&sev_ram_notifier);
     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+    qemu_add_vm_change_state_handler(sev_vm_state_change, s);
 
     sev_state = s;
 
-- 
2.9.5

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

* [PATCH v5 20/23] hw: i386: set ram_debug_ops when memory encryption is enabled
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

When memory encryption is enabled, the guest RAM and boot flash ROM will
contain the encrypted data. By setting the debug ops allow us to invoke
encryption APIs when accessing the memory for the debug purposes.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc.c       | 9 +++++++++
 hw/i386/pc_sysfw.c | 6 ++++++
 2 files changed, 15 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 186545d2a4e5..937cf75d5545 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1355,6 +1355,15 @@ void pc_memory_init(PCMachineState *pcms,
         e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
     }
 
+    /*
+     * When memory encryption is enabled, the guest RAM will be encrypted with
+     * a guest unique key. Set the debug ops so that any debug access to the
+     * guest RAM will go through the memory encryption APIs.
+     */
+    if (kvm_memcrypt_enabled()) {
+        kvm_memcrypt_set_debug_ops(ram);
+    }
+
     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 8ddbbf74d330..3d149b1c9f3c 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -180,6 +180,12 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
                     error_report("failed to encrypt pflash rom");
                     exit(1);
                 }
+
+                /*
+                 * The pflash ROM is encrypted, set the debug ops so that any
+                 * debug accesses will use memory encryption APIs.
+                 */
+                kvm_memcrypt_set_debug_ops(flash_mem);
             }
         }
     }
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 20/23] hw: i386: set ram_debug_ops when memory encryption is enabled
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

When memory encryption is enabled, the guest RAM and boot flash ROM will
contain the encrypted data. By setting the debug ops allow us to invoke
encryption APIs when accessing the memory for the debug purposes.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc.c       | 9 +++++++++
 hw/i386/pc_sysfw.c | 6 ++++++
 2 files changed, 15 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 186545d2a4e5..937cf75d5545 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1355,6 +1355,15 @@ void pc_memory_init(PCMachineState *pcms,
         e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
     }
 
+    /*
+     * When memory encryption is enabled, the guest RAM will be encrypted with
+     * a guest unique key. Set the debug ops so that any debug access to the
+     * guest RAM will go through the memory encryption APIs.
+     */
+    if (kvm_memcrypt_enabled()) {
+        kvm_memcrypt_set_debug_ops(ram);
+    }
+
     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 8ddbbf74d330..3d149b1c9f3c 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -180,6 +180,12 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
                     error_report("failed to encrypt pflash rom");
                     exit(1);
                 }
+
+                /*
+                 * The pflash ROM is encrypted, set the debug ops so that any
+                 * debug accesses will use memory encryption APIs.
+                 */
+                kvm_memcrypt_set_debug_ops(flash_mem);
             }
         }
     }
-- 
2.9.5

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

* [PATCH v5 21/23] sev: add debug encrypt and decrypt commands
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

KVM_SEV_DBG_DECRYPT and KVM_SEV_DBG_ENCRYPT commands are used for
decrypting and encrypting guest memory region. The command works only if
the guest policy allows the debugging.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  1 +
 accel/kvm/sev.c      | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 3 files changed, 72 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index d35eebb97901..b069261de32a 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1677,6 +1677,7 @@ static int kvm_init(MachineState *ms)
         }
 
         kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
+        kvm_state->memcrypt_debug_ops = sev_set_debug_ops;
     }
 
     ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index fbbd99becc0a..3edfb5b08416 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,7 @@
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
+#define GUEST_POLICY_DBG_BIT    0x1
 
 #define DEBUG_SEV
 #ifdef DEBUG_SEV
@@ -34,6 +35,7 @@
 
 static int sev_fd;
 static SEVState *sev_state;
+static MemoryRegionRAMReadWriteOps  sev_ops;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -483,6 +485,49 @@ sev_vm_state_change(void *opaque, int running, RunState state)
     }
 }
 
+static int
+sev_dbg_enc_dec(uint8_t *dst, const uint8_t *src, uint32_t len, bool write)
+{
+    int ret, error;
+    struct kvm_sev_dbg *dbg;
+    dbg = g_malloc0(sizeof(*dbg));
+    if (!dbg) {
+        return 1;
+    }
+
+    dbg->src_uaddr = (unsigned long)src;
+    dbg->dst_uaddr = (unsigned long)dst;
+    dbg->len = len;
+
+    ret = sev_ioctl(write ? KVM_SEV_DBG_ENCRYPT : KVM_SEV_DBG_DECRYPT,
+                    dbg, &error);
+    if (ret) {
+        error_report("%s (%s) %#llx->%#llx+%#x ret=%d fw_error=%d '%s'",
+                     __func__, write ? "write" : "read", dbg->src_uaddr,
+                     dbg->dst_uaddr, dbg->len, ret, error,
+                     fw_error_to_str(error));
+    }
+
+    g_free(dbg);
+    return ret;
+}
+
+static int
+sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    assert(attrs.debug);
+
+    return sev_dbg_enc_dec(dst, src, len, false);
+}
+
+static int
+sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    assert(attrs.debug);
+
+    return sev_dbg_enc_dec(dst, src, len, true);
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -549,6 +594,31 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
     return 0;
 }
 
+void
+sev_set_debug_ops(void *handle, MemoryRegion *mr)
+{
+    int policy;
+    SEVState *s = (SEVState *)handle;
+
+    policy = object_property_get_int(OBJECT(s->sev_info),
+                                     "policy", &error_abort);
+
+    /*
+     * Check if guest policy supports debugging
+     * Bit 0 :
+     *   0 - debug allowed
+     *   1 - debug is not allowed
+     */
+    if (policy & GUEST_POLICY_DBG_BIT) {
+        return;
+    }
+
+    sev_ops.read = sev_mem_read;
+    sev_ops.write = sev_mem_write;
+
+    memory_region_set_ram_debug_ops(mr, &sev_ops);
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 3af945935b60..7c50d33af4a9 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -71,6 +71,7 @@ typedef struct SEVState SEVState;
 
 void *sev_guest_init(const char *id);
 int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
+void sev_set_debug_ops(void *handle, MemoryRegion *mr);
 
 #endif
 
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 21/23] sev: add debug encrypt and decrypt commands
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

KVM_SEV_DBG_DECRYPT and KVM_SEV_DBG_ENCRYPT commands are used for
decrypting and encrypting guest memory region. The command works only if
the guest policy allows the debugging.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/kvm-all.c  |  1 +
 accel/kvm/sev.c      | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sev.h |  1 +
 3 files changed, 72 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index d35eebb97901..b069261de32a 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1677,6 +1677,7 @@ static int kvm_init(MachineState *ms)
         }
 
         kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
+        kvm_state->memcrypt_debug_ops = sev_set_debug_ops;
     }
 
     ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index fbbd99becc0a..3edfb5b08416 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -22,6 +22,7 @@
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
+#define GUEST_POLICY_DBG_BIT    0x1
 
 #define DEBUG_SEV
 #ifdef DEBUG_SEV
@@ -34,6 +35,7 @@
 
 static int sev_fd;
 static SEVState *sev_state;
+static MemoryRegionRAMReadWriteOps  sev_ops;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -483,6 +485,49 @@ sev_vm_state_change(void *opaque, int running, RunState state)
     }
 }
 
+static int
+sev_dbg_enc_dec(uint8_t *dst, const uint8_t *src, uint32_t len, bool write)
+{
+    int ret, error;
+    struct kvm_sev_dbg *dbg;
+    dbg = g_malloc0(sizeof(*dbg));
+    if (!dbg) {
+        return 1;
+    }
+
+    dbg->src_uaddr = (unsigned long)src;
+    dbg->dst_uaddr = (unsigned long)dst;
+    dbg->len = len;
+
+    ret = sev_ioctl(write ? KVM_SEV_DBG_ENCRYPT : KVM_SEV_DBG_DECRYPT,
+                    dbg, &error);
+    if (ret) {
+        error_report("%s (%s) %#llx->%#llx+%#x ret=%d fw_error=%d '%s'",
+                     __func__, write ? "write" : "read", dbg->src_uaddr,
+                     dbg->dst_uaddr, dbg->len, ret, error,
+                     fw_error_to_str(error));
+    }
+
+    g_free(dbg);
+    return ret;
+}
+
+static int
+sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    assert(attrs.debug);
+
+    return sev_dbg_enc_dec(dst, src, len, false);
+}
+
+static int
+sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    assert(attrs.debug);
+
+    return sev_dbg_enc_dec(dst, src, len, true);
+}
+
 void *
 sev_guest_init(const char *id)
 {
@@ -549,6 +594,31 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
     return 0;
 }
 
+void
+sev_set_debug_ops(void *handle, MemoryRegion *mr)
+{
+    int policy;
+    SEVState *s = (SEVState *)handle;
+
+    policy = object_property_get_int(OBJECT(s->sev_info),
+                                     "policy", &error_abort);
+
+    /*
+     * Check if guest policy supports debugging
+     * Bit 0 :
+     *   0 - debug allowed
+     *   1 - debug is not allowed
+     */
+    if (policy & GUEST_POLICY_DBG_BIT) {
+        return;
+    }
+
+    sev_ops.read = sev_mem_read;
+    sev_ops.write = sev_mem_write;
+
+    memory_region_set_ram_debug_ops(mr, &sev_ops);
+}
+
 static void
 sev_register_types(void)
 {
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 3af945935b60..7c50d33af4a9 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -71,6 +71,7 @@ typedef struct SEVState SEVState;
 
 void *sev_guest_init(const char *id);
 int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
+void sev_set_debug_ops(void *handle, MemoryRegion *mr);
 
 #endif
 
-- 
2.9.5

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

* [PATCH v5 22/23] target/i386: clear C-bit when walking SEV guest page table
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

In SEV-enabled guest the pte entry 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]

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target/i386/helper.c  | 46 +++++++++++++++++++--------
 target/i386/monitor.c | 86 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 94 insertions(+), 38 deletions(-)

diff --git a/target/i386/helper.c b/target/i386/helper.c
index 5dc9e8839bc8..7dbbb9812950 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -723,6 +723,22 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
 }
 
 #if !defined(CONFIG_USER_ONLY)
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /*
+     * When SEV is active, Fn8000_001F[EBX] Bit 0:5 contains the C-bit position
+     */
+    if (kvm_memcrypt_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << (pos & 0x3f));
+    }
+
+    return ~me_mask;
+}
+
 hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -732,6 +748,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     int32_t a20_mask;
     uint32_t page_offset;
     int page_size;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     a20_mask = x86_get_a20_mask(env);
     if (!(env->cr[0] & CR0_PG_MASK)) {
@@ -755,25 +774,25 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             }
 
             if (la57) {
-                pml5e_addr = ((env->cr[3] & ~0xfff) +
+                pml5e_addr = ((env->cr[3] & ~0xfff & me_mask) +
                         (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
-                pml5e = ldq_phys_debug(cs, pml5e_addr);
+                pml5e = ldq_phys_debug(cs, pml5e_addr) & me_mask;
                 if (!(pml5e & PG_PRESENT_MASK)) {
                     return -1;
                 }
             } else {
-                pml5e = env->cr[3];
+                pml5e = env->cr[3] & me_mask;
             }
 
             pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
                     (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
-            pml4e = ldq_phys_debug(cs, pml4e_addr);
+            pml4e = ldq_phys_debug(cs, pml4e_addr) & me_mask;
             if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
             }
             pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
                          (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK)) {
                 return -1;
             }
@@ -786,16 +805,16 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else
 #endif
         {
-            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
-                a20_mask;
-            pdpe = ldq_phys_debug(cs, pdpe_addr);
+            pdpe_addr = ((env->cr[3] & ~0x1f & me_mask) + ((addr >> 27) & 0x18))
+                          & a20_mask;
+            pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
         }
 
         pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
-        pde = ldq_phys_debug(cs, pde_addr);
+        pde = ldq_phys_debug(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
         }
@@ -808,7 +827,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
             page_size = 4096;
-            pte = ldq_phys_debug(cs, pte_addr);
+            pte = ldq_phys_debug(cs, pte_addr) & me_mask;
         }
         if (!(pte & PG_PRESENT_MASK)) {
             return -1;
@@ -817,8 +836,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         uint32_t pde;
 
         /* page directory entry */
-        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
-        pde = ldl_phys_debug(cs, pde_addr);
+        pde_addr = ((env->cr[3] & ~0xfff & me_mask) + ((addr >> 20) & 0xffc))
+                     & a20_mask;
+        pde = ldl_phys_debug(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +847,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
-            pte = ldl_phys_debug(cs, pte_addr);
+            pte = ldl_phys_debug(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 96890547f6b4..0b290f004a21 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -59,6 +59,22 @@ static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr,
                    pte & PG_RW_MASK ? 'W' : '-');
 }
 
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /*
+     * When SEV is active, Fn8000_001F[EBX] Bit 0:5 contains the C-bit position
+     */
+    if (kvm_memcrypt_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << (pos & 0x3f));
+    }
+
+    return ~me_mask;
+}
+
 static void tlb_info_32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2;
@@ -93,16 +109,20 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
     unsigned int l1, l2, l3;
     uint64_t pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     pdp_addr = env->cr[3] & ~0x1f;
+    pdp_addr &= me_mask;
     for (l1 = 0; l1 < 4; l1++) {
         cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
-        pdpe = le64_to_cpu(pdpe);
+        pdpe = le64_to_cpu(pdpe & me_mask);
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
                         /* 2M pages with PAE, CR4.PSE is ignored */
@@ -113,7 +133,7 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pt_addr + l3 * 8,
                                                            &pte, 8);
-                            pte = le64_to_cpu(pte);
+                            pte = le64_to_cpu(pte & me_mask);
                             if (pte & PG_PRESENT_MASK) {
                                 print_pte(mon, env, (l1 << 30) + (l2 << 21)
                                           + (l3 << 12),
@@ -135,10 +155,13 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
     uint64_t l1, l2, l3, l4;
     uint64_t pml4e, pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     for (l1 = 0; l1 < 512; l1++) {
         cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
-        pml4e = le64_to_cpu(pml4e);
+        pml4e = le64_to_cpu(pml4e & me_mask);
         if (!(pml4e & PG_PRESENT_MASK)) {
             continue;
         }
@@ -146,7 +169,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
         pdp_addr = pml4e & 0x3fffffffff000ULL;
         for (l2 = 0; l2 < 512; l2++) {
             cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
-            pdpe = le64_to_cpu(pdpe);
+            pdpe = le64_to_cpu(pdpe & me_mask);
             if (!(pdpe & PG_PRESENT_MASK)) {
                 continue;
             }
@@ -161,7 +184,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l3 = 0; l3 < 512; l3++) {
                 cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 if (!(pde & PG_PRESENT_MASK)) {
                     continue;
                 }
@@ -176,7 +199,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
                 pt_addr = pde & 0x3fffffffff000ULL;
                 for (l4 = 0; l4 < 512; l4++) {
                     cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
-                    pte = le64_to_cpu(pte);
+                    pte = le64_to_cpu(pte & me_mask);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l0 << 48) + (l1 << 39) +
                                 (l2 << 30) + (l3 << 21) + (l4 << 12),
@@ -193,11 +216,14 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
     uint64_t l0;
     uint64_t pml5e;
     uint64_t pml5_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
-    pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
     for (l0 = 0; l0 < 512; l0++) {
         cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
-        pml5e = le64_to_cpu(pml5e);
+        pml5e = le64_to_cpu(pml5e & me_mask);
         if (pml5e & PG_PRESENT_MASK) {
             tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
         }
@@ -225,7 +251,8 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
             if (env->cr[4] & CR4_LA57_MASK) {
                 tlb_info_la57(mon, env);
             } else {
-                tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL);
+                tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL &
+                              get_me_mask());
             }
         } else
 #endif
@@ -309,19 +336,22 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
     uint64_t pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
     hwaddr start, end;
+    uint64_t me_mask;
 
-    pdp_addr = env->cr[3] & ~0x1f;
+    me_mask = get_me_mask();
+
+    pdp_addr = env->cr[3] & ~0x1f & me_mask;
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 4; l1++) {
         cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
-        pdpe = le64_to_cpu(pdpe);
+        pdpe = le64_to_cpu(pdpe & me_mask);
         end = l1 << 30;
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 end = (l1 << 30) + (l2 << 21);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
@@ -333,7 +363,7 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pt_addr + l3 * 8,
                                                            &pte, 8);
-                            pte = le64_to_cpu(pte);
+                            pte = le64_to_cpu(pte & me_mask);
                             end = (l1 << 30) + (l2 << 21) + (l3 << 12);
                             if (pte & PG_PRESENT_MASK) {
                                 prot = pte & pde & (PG_USER_MASK | PG_RW_MASK |
@@ -366,19 +396,22 @@ static void mem_info_la48(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 = env->cr[3] & 0x3fffffffff000ULL & 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 = le64_to_cpu(pml4e);
+        pml4e = le64_to_cpu(pml4e & me_mask);
         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 = le64_to_cpu(pdpe);
+                pdpe = le64_to_cpu(pdpe & me_mask);
                 end = (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
                     if (pdpe & PG_PSE_MASK) {
@@ -391,7 +424,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pd_addr + l3 * 8,
                                                            &pde, 8);
-                            pde = le64_to_cpu(pde);
+                            pde = le64_to_cpu(pde & me_mask);
                             end = (l1 << 39) + (l2 << 30) + (l3 << 21);
                             if (pde & PG_PRESENT_MASK) {
                                 if (pde & PG_PSE_MASK) {
@@ -405,7 +438,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                                         cpu_physical_memory_read_debug(pt_addr
                                                                   + l4 * 8,
                                                                   &pte, 8);
-                                        pte = le64_to_cpu(pte);
+                                        pte = le64_to_cpu(pte & me_mask);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);
                                         if (pte & PG_PRESENT_MASK) {
@@ -444,13 +477,16 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
     uint64_t l0, l1, l2, l3, l4;
     uint64_t pml5e, pml4e, pdpe, pde, pte;
     uint64_t pml5_addr, pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
-    pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
     last_prot = 0;
     start = -1;
     for (l0 = 0; l0 < 512; l0++) {
         cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
-        pml5e = le64_to_cpu(pml5e);
+        pml5e = le64_to_cpu(pml5e & me_mask);
         end = l0 << 48;
         if (!(pml5e & PG_PRESENT_MASK)) {
             prot = 0;
@@ -461,7 +497,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
         pml4_addr = pml5e & 0x3fffffffff000ULL;
         for (l1 = 0; l1 < 512; l1++) {
             cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
-            pml4e = le64_to_cpu(pml4e);
+            pml4e = le64_to_cpu(pml4e & me_mask);
             end = (l0 << 48) + (l1 << 39);
             if (!(pml4e & PG_PRESENT_MASK)) {
                 prot = 0;
@@ -472,7 +508,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
-                pdpe = le64_to_cpu(pdpe);
+                pdpe = le64_to_cpu(pdpe & me_mask);
                 end = (l0 << 48) + (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
                     prot = 0;
@@ -491,7 +527,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
                 pd_addr = pdpe & 0x3fffffffff000ULL;
                 for (l3 = 0; l3 < 512; l3++) {
                     cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
-                    pde = le64_to_cpu(pde);
+                    pde = le64_to_cpu(pde & me_mask);
                     end = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
                     if (pde & PG_PRESENT_MASK) {
                         prot = 0;
@@ -510,7 +546,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
                     pt_addr = pde & 0x3fffffffff000ULL;
                     for (l4 = 0; l4 < 512; l4++) {
                         cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
-                        pte = le64_to_cpu(pte);
+                        pte = le64_to_cpu(pte & me_mask);
                         end = (l0 << 48) + (l1 << 39) + (l2 << 30) +
                             (l3 << 21) + (l4 << 12);
                         if (pte & PG_PRESENT_MASK) {
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 22/23] target/i386: clear C-bit when walking SEV guest page table
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

In SEV-enabled guest the pte entry 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]

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target/i386/helper.c  | 46 +++++++++++++++++++--------
 target/i386/monitor.c | 86 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 94 insertions(+), 38 deletions(-)

diff --git a/target/i386/helper.c b/target/i386/helper.c
index 5dc9e8839bc8..7dbbb9812950 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -723,6 +723,22 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
 }
 
 #if !defined(CONFIG_USER_ONLY)
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /*
+     * When SEV is active, Fn8000_001F[EBX] Bit 0:5 contains the C-bit position
+     */
+    if (kvm_memcrypt_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << (pos & 0x3f));
+    }
+
+    return ~me_mask;
+}
+
 hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -732,6 +748,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     int32_t a20_mask;
     uint32_t page_offset;
     int page_size;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     a20_mask = x86_get_a20_mask(env);
     if (!(env->cr[0] & CR0_PG_MASK)) {
@@ -755,25 +774,25 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             }
 
             if (la57) {
-                pml5e_addr = ((env->cr[3] & ~0xfff) +
+                pml5e_addr = ((env->cr[3] & ~0xfff & me_mask) +
                         (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
-                pml5e = ldq_phys_debug(cs, pml5e_addr);
+                pml5e = ldq_phys_debug(cs, pml5e_addr) & me_mask;
                 if (!(pml5e & PG_PRESENT_MASK)) {
                     return -1;
                 }
             } else {
-                pml5e = env->cr[3];
+                pml5e = env->cr[3] & me_mask;
             }
 
             pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
                     (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
-            pml4e = ldq_phys_debug(cs, pml4e_addr);
+            pml4e = ldq_phys_debug(cs, pml4e_addr) & me_mask;
             if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
             }
             pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
                          (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
-            pdpe = x86_ldq_phys(cs, pdpe_addr);
+            pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK)) {
                 return -1;
             }
@@ -786,16 +805,16 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else
 #endif
         {
-            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
-                a20_mask;
-            pdpe = ldq_phys_debug(cs, pdpe_addr);
+            pdpe_addr = ((env->cr[3] & ~0x1f & me_mask) + ((addr >> 27) & 0x18))
+                          & a20_mask;
+            pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
             if (!(pdpe & PG_PRESENT_MASK))
                 return -1;
         }
 
         pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
-        pde = ldq_phys_debug(cs, pde_addr);
+        pde = ldq_phys_debug(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK)) {
             return -1;
         }
@@ -808,7 +827,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
             pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
             page_size = 4096;
-            pte = ldq_phys_debug(cs, pte_addr);
+            pte = ldq_phys_debug(cs, pte_addr) & me_mask;
         }
         if (!(pte & PG_PRESENT_MASK)) {
             return -1;
@@ -817,8 +836,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         uint32_t pde;
 
         /* page directory entry */
-        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
-        pde = ldl_phys_debug(cs, pde_addr);
+        pde_addr = ((env->cr[3] & ~0xfff & me_mask) + ((addr >> 20) & 0xffc))
+                     & a20_mask;
+        pde = ldl_phys_debug(cs, pde_addr) & me_mask;
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +847,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
-            pte = ldl_phys_debug(cs, pte_addr);
+            pte = ldl_phys_debug(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 96890547f6b4..0b290f004a21 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -59,6 +59,22 @@ static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr,
                    pte & PG_RW_MASK ? 'W' : '-');
 }
 
+static uint64_t get_me_mask(void)
+{
+    uint64_t me_mask = 0;
+
+    /*
+     * When SEV is active, Fn8000_001F[EBX] Bit 0:5 contains the C-bit position
+     */
+    if (kvm_memcrypt_enabled()) {
+        uint32_t pos;
+        pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+        me_mask = (1UL << (pos & 0x3f));
+    }
+
+    return ~me_mask;
+}
+
 static void tlb_info_32(Monitor *mon, CPUArchState *env)
 {
     unsigned int l1, l2;
@@ -93,16 +109,20 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
     unsigned int l1, l2, l3;
     uint64_t pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     pdp_addr = env->cr[3] & ~0x1f;
+    pdp_addr &= me_mask;
     for (l1 = 0; l1 < 4; l1++) {
         cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
-        pdpe = le64_to_cpu(pdpe);
+        pdpe = le64_to_cpu(pdpe & me_mask);
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
                         /* 2M pages with PAE, CR4.PSE is ignored */
@@ -113,7 +133,7 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pt_addr + l3 * 8,
                                                            &pte, 8);
-                            pte = le64_to_cpu(pte);
+                            pte = le64_to_cpu(pte & me_mask);
                             if (pte & PG_PRESENT_MASK) {
                                 print_pte(mon, env, (l1 << 30) + (l2 << 21)
                                           + (l3 << 12),
@@ -135,10 +155,13 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
     uint64_t l1, l2, l3, l4;
     uint64_t pml4e, pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
     for (l1 = 0; l1 < 512; l1++) {
         cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
-        pml4e = le64_to_cpu(pml4e);
+        pml4e = le64_to_cpu(pml4e & me_mask);
         if (!(pml4e & PG_PRESENT_MASK)) {
             continue;
         }
@@ -146,7 +169,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
         pdp_addr = pml4e & 0x3fffffffff000ULL;
         for (l2 = 0; l2 < 512; l2++) {
             cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
-            pdpe = le64_to_cpu(pdpe);
+            pdpe = le64_to_cpu(pdpe & me_mask);
             if (!(pdpe & PG_PRESENT_MASK)) {
                 continue;
             }
@@ -161,7 +184,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l3 = 0; l3 < 512; l3++) {
                 cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 if (!(pde & PG_PRESENT_MASK)) {
                     continue;
                 }
@@ -176,7 +199,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
                 pt_addr = pde & 0x3fffffffff000ULL;
                 for (l4 = 0; l4 < 512; l4++) {
                     cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
-                    pte = le64_to_cpu(pte);
+                    pte = le64_to_cpu(pte & me_mask);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, env, (l0 << 48) + (l1 << 39) +
                                 (l2 << 30) + (l3 << 21) + (l4 << 12),
@@ -193,11 +216,14 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
     uint64_t l0;
     uint64_t pml5e;
     uint64_t pml5_addr;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
-    pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
     for (l0 = 0; l0 < 512; l0++) {
         cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
-        pml5e = le64_to_cpu(pml5e);
+        pml5e = le64_to_cpu(pml5e & me_mask);
         if (pml5e & PG_PRESENT_MASK) {
             tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
         }
@@ -225,7 +251,8 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
             if (env->cr[4] & CR4_LA57_MASK) {
                 tlb_info_la57(mon, env);
             } else {
-                tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL);
+                tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL &
+                              get_me_mask());
             }
         } else
 #endif
@@ -309,19 +336,22 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
     uint64_t pdpe, pde, pte;
     uint64_t pdp_addr, pd_addr, pt_addr;
     hwaddr start, end;
+    uint64_t me_mask;
 
-    pdp_addr = env->cr[3] & ~0x1f;
+    me_mask = get_me_mask();
+
+    pdp_addr = env->cr[3] & ~0x1f & me_mask;
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 4; l1++) {
         cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
-        pdpe = le64_to_cpu(pdpe);
+        pdpe = le64_to_cpu(pdpe & me_mask);
         end = l1 << 30;
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
-                pde = le64_to_cpu(pde);
+                pde = le64_to_cpu(pde & me_mask);
                 end = (l1 << 30) + (l2 << 21);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
@@ -333,7 +363,7 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pt_addr + l3 * 8,
                                                            &pte, 8);
-                            pte = le64_to_cpu(pte);
+                            pte = le64_to_cpu(pte & me_mask);
                             end = (l1 << 30) + (l2 << 21) + (l3 << 12);
                             if (pte & PG_PRESENT_MASK) {
                                 prot = pte & pde & (PG_USER_MASK | PG_RW_MASK |
@@ -366,19 +396,22 @@ static void mem_info_la48(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 = env->cr[3] & 0x3fffffffff000ULL & 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 = le64_to_cpu(pml4e);
+        pml4e = le64_to_cpu(pml4e & me_mask);
         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 = le64_to_cpu(pdpe);
+                pdpe = le64_to_cpu(pdpe & me_mask);
                 end = (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
                     if (pdpe & PG_PSE_MASK) {
@@ -391,7 +424,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                         for (l3 = 0; l3 < 512; l3++) {
                             cpu_physical_memory_read_debug(pd_addr + l3 * 8,
                                                            &pde, 8);
-                            pde = le64_to_cpu(pde);
+                            pde = le64_to_cpu(pde & me_mask);
                             end = (l1 << 39) + (l2 << 30) + (l3 << 21);
                             if (pde & PG_PRESENT_MASK) {
                                 if (pde & PG_PSE_MASK) {
@@ -405,7 +438,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
                                         cpu_physical_memory_read_debug(pt_addr
                                                                   + l4 * 8,
                                                                   &pte, 8);
-                                        pte = le64_to_cpu(pte);
+                                        pte = le64_to_cpu(pte & me_mask);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);
                                         if (pte & PG_PRESENT_MASK) {
@@ -444,13 +477,16 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
     uint64_t l0, l1, l2, l3, l4;
     uint64_t pml5e, pml4e, pdpe, pde, pte;
     uint64_t pml5_addr, pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+    uint64_t me_mask;
+
+    me_mask = get_me_mask();
 
-    pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+    pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
     last_prot = 0;
     start = -1;
     for (l0 = 0; l0 < 512; l0++) {
         cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
-        pml5e = le64_to_cpu(pml5e);
+        pml5e = le64_to_cpu(pml5e & me_mask);
         end = l0 << 48;
         if (!(pml5e & PG_PRESENT_MASK)) {
             prot = 0;
@@ -461,7 +497,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
         pml4_addr = pml5e & 0x3fffffffff000ULL;
         for (l1 = 0; l1 < 512; l1++) {
             cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
-            pml4e = le64_to_cpu(pml4e);
+            pml4e = le64_to_cpu(pml4e & me_mask);
             end = (l0 << 48) + (l1 << 39);
             if (!(pml4e & PG_PRESENT_MASK)) {
                 prot = 0;
@@ -472,7 +508,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
                 cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
-                pdpe = le64_to_cpu(pdpe);
+                pdpe = le64_to_cpu(pdpe & me_mask);
                 end = (l0 << 48) + (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
                     prot = 0;
@@ -491,7 +527,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
                 pd_addr = pdpe & 0x3fffffffff000ULL;
                 for (l3 = 0; l3 < 512; l3++) {
                     cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
-                    pde = le64_to_cpu(pde);
+                    pde = le64_to_cpu(pde & me_mask);
                     end = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
                     if (pde & PG_PRESENT_MASK) {
                         prot = 0;
@@ -510,7 +546,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
                     pt_addr = pde & 0x3fffffffff000ULL;
                     for (l4 = 0; l4 < 512; l4++) {
                         cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
-                        pte = le64_to_cpu(pte);
+                        pte = le64_to_cpu(pte & me_mask);
                         end = (l0 << 48) + (l1 << 39) + (l2 << 30) +
                             (l3 << 21) + (l4 << 12);
                         if (pte & PG_PRESENT_MASK) {
-- 
2.9.5

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

* [PATCH v5 23/23] sev: add migration blocker
  2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 20:03   ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

SEV guest migration is not yet implemented yet.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 3edfb5b08416..10647645eacd 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -19,6 +19,7 @@
 #include "sysemu/sev.h"
 #include "sysemu/sysemu.h"
 #include "qapi-event.h"
+#include "migration/blocker.h"
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
@@ -36,6 +37,7 @@
 static int sev_fd;
 static SEVState *sev_state;
 static MemoryRegionRAMReadWriteOps  sev_ops;
+static Error *sev_mig_blocker;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -460,6 +462,7 @@ static void
 sev_launch_finish(SEVState *s)
 {
     int ret, error;
+    Error *local_err = NULL;
 
     ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
     if (ret) {
@@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
 
     s->cur_state = SEV_STATE_RUNNING;
     DPRINTF("SEV: LAUNCH_FINISH\n");
+
+    /* add migration blocker */
+    error_setg(&sev_mig_blocker,
+               "SEV: Migration is not implemented");
+    ret = migrate_add_blocker(sev_mig_blocker, &local_err);
+    if (local_err) {
+        error_report_err(local_err);
+        error_free(sev_mig_blocker);
+        exit(1);
+    }
 }
 
 static void
-- 
2.9.5

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

* [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-06 20:03   ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-06 20:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
	Daniel P . Berrange, Dr. David Alan Gilbert, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov, Brijesh Singh

SEV guest migration is not yet implemented yet.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 accel/kvm/sev.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 3edfb5b08416..10647645eacd 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -19,6 +19,7 @@
 #include "sysemu/sev.h"
 #include "sysemu/sysemu.h"
 #include "qapi-event.h"
+#include "migration/blocker.h"
 
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
@@ -36,6 +37,7 @@
 static int sev_fd;
 static SEVState *sev_state;
 static MemoryRegionRAMReadWriteOps  sev_ops;
+static Error *sev_mig_blocker;
 
 #define SEV_FW_MAX_ERROR      0x17
 
@@ -460,6 +462,7 @@ static void
 sev_launch_finish(SEVState *s)
 {
     int ret, error;
+    Error *local_err = NULL;
 
     ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
     if (ret) {
@@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
 
     s->cur_state = SEV_STATE_RUNNING;
     DPRINTF("SEV: LAUNCH_FINISH\n");
+
+    /* add migration blocker */
+    error_setg(&sev_mig_blocker,
+               "SEV: Migration is not implemented");
+    ret = migrate_add_blocker(sev_mig_blocker, &local_err);
+    if (local_err) {
+        error_report_err(local_err);
+        error_free(sev_mig_blocker);
+        exit(1);
+    }
 }
 
 static void
-- 
2.9.5

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

* Re: [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
@ 2017-12-06 22:03     ` Peter Maydell
  -1 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-06 22:03 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: QEMU Developers, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi

On 6 December 2017 at 20:03, Brijesh Singh <brijesh.singh@amd.com> wrote:
> The debug attribute will be set when qemu attempts to access the guest
> memory for debug (e.g memory access from gdbstub, memory dump commands
> etc).
>
> When guest memory is encrypted, the debug access will need to go through
> the memory encryption APIs.
>
> Cc: Alistair Francis <alistair.francis@xilinx.com>
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> 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 d4a16420984b..721362e06292 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;
> +    /* Debug memory access for encrypted guest */
> +    unsigned int debug:1;
>  } MemTxAttrs;

Can we have some more detailed semantics for this please?
For instance, if a device gets a debug=1 transaction
should it refuse to do things like read-clears-bits
semantics or other side-effects you wouldn't expect
of debugger accesses?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-06 22:03     ` Peter Maydell
  0 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-06 22:03 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: QEMU Developers, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

On 6 December 2017 at 20:03, Brijesh Singh <brijesh.singh@amd.com> wrote:
> The debug attribute will be set when qemu attempts to access the guest
> memory for debug (e.g memory access from gdbstub, memory dump commands
> etc).
>
> When guest memory is encrypted, the debug access will need to go through
> the memory encryption APIs.
>
> Cc: Alistair Francis <alistair.francis@xilinx.com>
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> 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 d4a16420984b..721362e06292 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;
> +    /* Debug memory access for encrypted guest */
> +    unsigned int debug:1;
>  } MemTxAttrs;

Can we have some more detailed semantics for this please?
For instance, if a device gets a debug=1 transaction
should it refuse to do things like read-clears-bits
semantics or other side-effects you wouldn't expect
of debugger accesses?

thanks
-- PMM

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

* Re: [PATCH v5 23/23] sev: add migration blocker
  2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
@ 2017-12-07 11:03     ` Dr. David Alan Gilbert
  -1 siblings, 0 replies; 68+ messages in thread
From: Dr. David Alan Gilbert @ 2017-12-07 11:03 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: qemu-devel, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky

* Brijesh Singh (brijesh.singh@amd.com) wrote:
> SEV guest migration is not yet implemented yet.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  accel/kvm/sev.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
> index 3edfb5b08416..10647645eacd 100644
> --- a/accel/kvm/sev.c
> +++ b/accel/kvm/sev.c
> @@ -19,6 +19,7 @@
>  #include "sysemu/sev.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi-event.h"
> +#include "migration/blocker.h"
>  
>  #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
>  #define DEFAULT_SEV_DEVICE      "/dev/sev"
> @@ -36,6 +37,7 @@
>  static int sev_fd;
>  static SEVState *sev_state;
>  static MemoryRegionRAMReadWriteOps  sev_ops;
> +static Error *sev_mig_blocker;
>  
>  #define SEV_FW_MAX_ERROR      0x17
>  
> @@ -460,6 +462,7 @@ static void
>  sev_launch_finish(SEVState *s)
>  {
>      int ret, error;
> +    Error *local_err = NULL;
>  
>      ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
>      if (ret) {
> @@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
>  
>      s->cur_state = SEV_STATE_RUNNING;
>      DPRINTF("SEV: LAUNCH_FINISH\n");

(from a previous patch)
Please use the tracing facility rather than new DPRINTF's
if possible - if you've not used it before, then
--enable-trace-backends=log   is the easy way to get going
and you can turn on and off the stuff you're interested in
tracing at run time without having to rebuild.

> +
> +    /* add migration blocker */
> +    error_setg(&sev_mig_blocker,
> +               "SEV: Migration is not implemented");
> +    ret = migrate_add_blocker(sev_mig_blocker, &local_err);
> +    if (local_err) {
> +        error_report_err(local_err);
> +        error_free(sev_mig_blocker);
> +        exit(1);
> +    }

Yep, reasonable:


Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

>  }
>  
>  static void
> -- 
> 2.9.5
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-07 11:03     ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 68+ messages in thread
From: Dr. David Alan Gilbert @ 2017-12-07 11:03 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: qemu-devel, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Edgar E . Iglesias ,
	Eduardo Habkost, Eric Blake, kvm, Marcel Apfelbaum,
	Markus Armbruster, Michael S. Tsirkin, Paolo Bonzini,
	Peter Crosthwaite, Peter Maydell, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

* Brijesh Singh (brijesh.singh@amd.com) wrote:
> SEV guest migration is not yet implemented yet.
> 
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  accel/kvm/sev.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
> index 3edfb5b08416..10647645eacd 100644
> --- a/accel/kvm/sev.c
> +++ b/accel/kvm/sev.c
> @@ -19,6 +19,7 @@
>  #include "sysemu/sev.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi-event.h"
> +#include "migration/blocker.h"
>  
>  #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
>  #define DEFAULT_SEV_DEVICE      "/dev/sev"
> @@ -36,6 +37,7 @@
>  static int sev_fd;
>  static SEVState *sev_state;
>  static MemoryRegionRAMReadWriteOps  sev_ops;
> +static Error *sev_mig_blocker;
>  
>  #define SEV_FW_MAX_ERROR      0x17
>  
> @@ -460,6 +462,7 @@ static void
>  sev_launch_finish(SEVState *s)
>  {
>      int ret, error;
> +    Error *local_err = NULL;
>  
>      ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
>      if (ret) {
> @@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
>  
>      s->cur_state = SEV_STATE_RUNNING;
>      DPRINTF("SEV: LAUNCH_FINISH\n");

(from a previous patch)
Please use the tracing facility rather than new DPRINTF's
if possible - if you've not used it before, then
--enable-trace-backends=log   is the easy way to get going
and you can turn on and off the stuff you're interested in
tracing at run time without having to rebuild.

> +
> +    /* add migration blocker */
> +    error_setg(&sev_mig_blocker,
> +               "SEV: Migration is not implemented");
> +    ret = migrate_add_blocker(sev_mig_blocker, &local_err);
> +    if (local_err) {
> +        error_report_err(local_err);
> +        error_free(sev_mig_blocker);
> +        exit(1);
> +    }

Yep, reasonable:


Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

>  }
>  
>  static void
> -- 
> 2.9.5
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [PATCH v5 23/23] sev: add migration blocker
  2017-12-07 11:03     ` [Qemu-devel] " Dr. David Alan Gilbert
@ 2017-12-07 11:10       ` Peter Maydell
  -1 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-07 11:10 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas

On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>> SEV guest migration is not yet implemented yet.

Is there at least a plan for how migration of a guest with
encrypted memory would be implemented?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-07 11:10       ` Peter Maydell
  0 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-07 11:10 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>> SEV guest migration is not yet implemented yet.

Is there at least a plan for how migration of a guest with
encrypted memory would be implemented?

thanks
-- PMM

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

* Re: [PATCH v5 23/23] sev: add migration blocker
  2017-12-07 11:10       ` [Qemu-devel] " Peter Maydell
@ 2017-12-07 11:27         ` Dr. David Alan Gilbert
  -1 siblings, 0 replies; 68+ messages in thread
From: Dr. David Alan Gilbert @ 2017-12-07 11:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas

* Peter Maydell (peter.maydell@linaro.org) wrote:
> On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
> > * Brijesh Singh (brijesh.singh@amd.com) wrote:
> >> SEV guest migration is not yet implemented yet.
> 
> Is there at least a plan for how migration of a guest with
> encrypted memory would be implemented?

It's something I've discussed with Brijesh and co and I've read
through the spec and it does look doable; I understand wanting to
get the basics of SEV going first though.

Dave

> thanks
> -- PMM
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-07 11:27         ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 68+ messages in thread
From: Dr. David Alan Gilbert @ 2017-12-07 11:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

* Peter Maydell (peter.maydell@linaro.org) wrote:
> On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
> > * Brijesh Singh (brijesh.singh@amd.com) wrote:
> >> SEV guest migration is not yet implemented yet.
> 
> Is there at least a plan for how migration of a guest with
> encrypted memory would be implemented?

It's something I've discussed with Brijesh and co and I've read
through the spec and it does look doable; I understand wanting to
get the basics of SEV going first though.

Dave

> thanks
> -- PMM
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-06 22:03     ` [Qemu-devel] " Peter Maydell
@ 2017-12-07 21:20       ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 21:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Edgar E . Iglesias, Eduardo Habkost,
	Eric Blake, kvm-devel, Marcel Apfelbaum, Markus Armbruster,
	Michael S. Tsirkin, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi


On 12/06/2017 04:03 PM, Peter Maydell wrote:
> On 6 December 2017 at 20:03, Brijesh Singh <brijesh.singh@amd.com> wrote:
>> The debug attribute will be set when qemu attempts to access the guest
>> memory for debug (e.g memory access from gdbstub, memory dump commands
>> etc).
>>
>> When guest memory is encrypted, the debug access will need to go through
>> the memory encryption APIs.
>>
>> Cc: Alistair Francis <alistair.francis@xilinx.com>
>> Cc: Peter Maydell <peter.maydell@linaro.org>
>> Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>> Cc: Richard Henderson <richard.henderson@linaro.org>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> 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 d4a16420984b..721362e06292 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;
>> +    /* Debug memory access for encrypted guest */
>> +    unsigned int debug:1;
>>   } MemTxAttrs;
> 
> Can we have some more detailed semantics for this please?


Sure, I will add more details. The flag is mainly used to distinguish 
the debug vs non debug access when using address_space_read/write/rw().

If a debug=1 is set then flatview_read(), flatview_write(), 
flatview_rw() will use the encryption APIs when accessing the guest RAM 
case. Since the MMIO regions are not encrypted with guest-specific keys 
hence we don't need to do anything special for the MMIO cases.


> For instance, if a device gets a debug=1 transaction
> should it refuse to do things like read-clears-bits
> semantics or other side-effects you wouldn't expect
> of debugger accesses?
> 

Sorry I am not able to understand "if a device gets a debug=1 
transition" comment, Can you please explain me a bit more. If you give 
me example on how to trigger this type of request with debug=1 then I 
can look into the code and see what we can do when memory encryption is 
enabled. The things like read-clears-bits semantics will be tricky.


> thanks
> -- PMM
> 

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

* Re: [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-07 21:20       ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 21:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Edgar E . Iglesias, Eduardo Habkost,
	Eric Blake, kvm-devel, Marcel Apfelbaum, Markus Armbruster,
	Michael S. Tsirkin, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi,
	Thomas Lendacky, Borislav Petkov


On 12/06/2017 04:03 PM, Peter Maydell wrote:
> On 6 December 2017 at 20:03, Brijesh Singh <brijesh.singh@amd.com> wrote:
>> The debug attribute will be set when qemu attempts to access the guest
>> memory for debug (e.g memory access from gdbstub, memory dump commands
>> etc).
>>
>> When guest memory is encrypted, the debug access will need to go through
>> the memory encryption APIs.
>>
>> Cc: Alistair Francis <alistair.francis@xilinx.com>
>> Cc: Peter Maydell <peter.maydell@linaro.org>
>> Cc: Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>> Cc: Richard Henderson <richard.henderson@linaro.org>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> 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 d4a16420984b..721362e06292 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;
>> +    /* Debug memory access for encrypted guest */
>> +    unsigned int debug:1;
>>   } MemTxAttrs;
> 
> Can we have some more detailed semantics for this please?


Sure, I will add more details. The flag is mainly used to distinguish 
the debug vs non debug access when using address_space_read/write/rw().

If a debug=1 is set then flatview_read(), flatview_write(), 
flatview_rw() will use the encryption APIs when accessing the guest RAM 
case. Since the MMIO regions are not encrypted with guest-specific keys 
hence we don't need to do anything special for the MMIO cases.


> For instance, if a device gets a debug=1 transaction
> should it refuse to do things like read-clears-bits
> semantics or other side-effects you wouldn't expect
> of debugger accesses?
> 

Sorry I am not able to understand "if a device gets a debug=1 
transition" comment, Can you please explain me a bit more. If you give 
me example on how to trigger this type of request with debug=1 then I 
can look into the code and see what we can do when memory encryption is 
enabled. The things like read-clears-bits semantics will be tricky.


> thanks
> -- PMM
> 

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

* Re: [PATCH v5 23/23] sev: add migration blocker
  2017-12-07 11:27         ` [Qemu-devel] " Dr. David Alan Gilbert
@ 2017-12-07 21:25           ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 21:25 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky



On 12/07/2017 05:27 AM, Dr. David Alan Gilbert wrote:
> * Peter Maydell (peter.maydell@linaro.org) wrote:
>> On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
>>> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>>>> SEV guest migration is not yet implemented yet.
>>
>> Is there at least a plan for how migration of a guest with
>> encrypted memory would be implemented?
> 
> It's something I've discussed with Brijesh and co and I've read
> through the spec and it does look doable; I understand wanting to
> get the basics of SEV going first though.
> 

Yes this is something I have in plans. Both the spec and firmware 
supports encrypted guest migration. Lets get the basics enabled first.

thanks!

-Brijesh

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

* Re: [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-07 21:25           ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 21:25 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov



On 12/07/2017 05:27 AM, Dr. David Alan Gilbert wrote:
> * Peter Maydell (peter.maydell@linaro.org) wrote:
>> On 7 December 2017 at 11:03, Dr. David Alan Gilbert <dgilbert@redhat.com> wrote:
>>> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>>>> SEV guest migration is not yet implemented yet.
>>
>> Is there at least a plan for how migration of a guest with
>> encrypted memory would be implemented?
> 
> It's something I've discussed with Brijesh and co and I've read
> through the spec and it does look doable; I understand wanting to
> get the basics of SEV going first though.
> 

Yes this is something I have in plans. Both the spec and firmware 
supports encrypted guest migration. Lets get the basics enabled first.

thanks!

-Brijesh

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

* Re: [PATCH v5 23/23] sev: add migration blocker
  2017-12-07 11:03     ` [Qemu-devel] " Dr. David Alan Gilbert
@ 2017-12-07 22:50       ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 22:50 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: brijesh.singh, qemu-devel, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Peter Maydell,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi,
	Thomas Lendacky



On 12/07/2017 05:03 AM, Dr. David Alan Gilbert wrote:
.......

>>   
>>   #define SEV_FW_MAX_ERROR      0x17
>>   
>> @@ -460,6 +462,7 @@ static void
>>   sev_launch_finish(SEVState *s)
>>   {
>>       int ret, error;
>> +    Error *local_err = NULL;
>>   
>>       ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
>>       if (ret) {
>> @@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
>>   
>>       s->cur_state = SEV_STATE_RUNNING;
>>       DPRINTF("SEV: LAUNCH_FINISH\n");
> 
> (from a previous patch)
> Please use the tracing facility rather than new DPRINTF's
> if possible - if you've not used it before, then
> --enable-trace-backends=log   is the easy way to get going
> and you can turn on and off the stuff you're interested in
> tracing at run time without having to rebuild.


Thanks for review, I will look into converting those DPRINTF's in trace 
logging.

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

* Re: [Qemu-devel] [PATCH v5 23/23] sev: add migration blocker
@ 2017-12-07 22:50       ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-07 22:50 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: brijesh.singh, qemu-devel, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Peter Maydell,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi,
	Thomas Lendacky, Borislav Petkov



On 12/07/2017 05:03 AM, Dr. David Alan Gilbert wrote:
.......

>>   
>>   #define SEV_FW_MAX_ERROR      0x17
>>   
>> @@ -460,6 +462,7 @@ static void
>>   sev_launch_finish(SEVState *s)
>>   {
>>       int ret, error;
>> +    Error *local_err = NULL;
>>   
>>       ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
>>       if (ret) {
>> @@ -470,6 +473,16 @@ sev_launch_finish(SEVState *s)
>>   
>>       s->cur_state = SEV_STATE_RUNNING;
>>       DPRINTF("SEV: LAUNCH_FINISH\n");
> 
> (from a previous patch)
> Please use the tracing facility rather than new DPRINTF's
> if possible - if you've not used it before, then
> --enable-trace-backends=log   is the easy way to get going
> and you can turn on and off the stuff you're interested in
> tracing at run time without having to rebuild.


Thanks for review, I will look into converting those DPRINTF's in trace 
logging.

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

* Re: [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-07 21:20       ` [Qemu-devel] " Brijesh Singh
@ 2017-12-08  9:55         ` Peter Maydell
  -1 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-08  9:55 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: QEMU Developers, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi

On 7 December 2017 at 21:20, Brijesh Singh <brijesh.singh@amd.com> wrote:
> On 12/06/2017 04:03 PM, Peter Maydell wrote:
>> For instance, if a device gets a debug=1 transaction
>> should it refuse to do things like read-clears-bits
>> semantics or other side-effects you wouldn't expect
>> of debugger accesses?
>>
>
> Sorry I am not able to understand "if a device gets a debug=1 transition"
> comment, Can you please explain me a bit more.

A device model (eg a UART) can be written to look at the
MemTxAttrs that it's passed and behave differently if debug=1.

> If you give me example on how
> to trigger this type of request with debug=1 then I can look into the code
> and see what we can do when memory encryption is enabled. The things like
> read-clears-bits semantics will be tricky.

The question was really whether we want to make this a general
indicator of "this operation was triggered by a debugger" and
expand that to mean "don't do things that mess with the state
of the simulation unexpectedly", or if this is really a very
encrypted-memory specific thing.

By the way, I don't think this:

> /* Access the guest memory for debug purposes */
> #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })

is a great idea. Callers that care about the transaction
attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
is a fallback for the large set of places that don't care at all.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-08  9:55         ` Peter Maydell
  0 siblings, 0 replies; 68+ messages in thread
From: Peter Maydell @ 2017-12-08  9:55 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: QEMU Developers, Alistair Francis, Christian Borntraeger,
	Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
	Edgar E . Iglesias, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

On 7 December 2017 at 21:20, Brijesh Singh <brijesh.singh@amd.com> wrote:
> On 12/06/2017 04:03 PM, Peter Maydell wrote:
>> For instance, if a device gets a debug=1 transaction
>> should it refuse to do things like read-clears-bits
>> semantics or other side-effects you wouldn't expect
>> of debugger accesses?
>>
>
> Sorry I am not able to understand "if a device gets a debug=1 transition"
> comment, Can you please explain me a bit more.

A device model (eg a UART) can be written to look at the
MemTxAttrs that it's passed and behave differently if debug=1.

> If you give me example on how
> to trigger this type of request with debug=1 then I can look into the code
> and see what we can do when memory encryption is enabled. The things like
> read-clears-bits semantics will be tricky.

The question was really whether we want to make this a general
indicator of "this operation was triggered by a debugger" and
expand that to mean "don't do things that mess with the state
of the simulation unexpectedly", or if this is really a very
encrypted-memory specific thing.

By the way, I don't think this:

> /* Access the guest memory for debug purposes */
> #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })

is a great idea. Callers that care about the transaction
attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
is a fallback for the large set of places that don't care at all.

thanks
-- PMM

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

* Re: [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-08  9:55         ` [Qemu-devel] " Peter Maydell
@ 2017-12-08 10:24           ` Edgar E. Iglesias
  -1 siblings, 0 replies; 68+ messages in thread
From: Edgar E. Iglesias @ 2017-12-08 10:24 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas

On Fri, Dec 08, 2017 at 09:55:26AM +0000, Peter Maydell wrote:
> On 7 December 2017 at 21:20, Brijesh Singh <brijesh.singh@amd.com> wrote:
> > On 12/06/2017 04:03 PM, Peter Maydell wrote:
> >> For instance, if a device gets a debug=1 transaction
> >> should it refuse to do things like read-clears-bits
> >> semantics or other side-effects you wouldn't expect
> >> of debugger accesses?
> >>
> >
> > Sorry I am not able to understand "if a device gets a debug=1 transition"
> > comment, Can you please explain me a bit more.
> 
> A device model (eg a UART) can be written to look at the
> MemTxAttrs that it's passed and behave differently if debug=1.
> 
> > If you give me example on how
> > to trigger this type of request with debug=1 then I can look into the code
> > and see what we can do when memory encryption is enabled. The things like
> > read-clears-bits semantics will be tricky.
> 
> The question was really whether we want to make this a general
> indicator of "this operation was triggered by a debugger" and
> expand that to mean "don't do things that mess with the state
> of the simulation unexpectedly", or if this is really a very
> encrypted-memory specific thing.


IMO, It sounds like a good idea to make it a general indicator of
debugger access. We may not need to be very strict about an
exact global meaning, but individual device models may for example
choose to expose additional debug registers and features or
to avoid certain register access side-effects.

In some cases it may be confusing to change the behaviour of
existing regs with side-effects based on debug access, so it may
not always make sense.

Cheers,
Edgar


> 
> By the way, I don't think this:
> 
> > /* Access the guest memory for debug purposes */
> > #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
> 
> is a great idea. Callers that care about the transaction
> attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
> is a fallback for the large set of places that don't care at all.
> 
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-08 10:24           ` Edgar E. Iglesias
  0 siblings, 0 replies; 68+ messages in thread
From: Edgar E. Iglesias @ 2017-12-08 10:24 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Brijesh Singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Eduardo Habkost, Eric Blake, kvm-devel,
	Marcel Apfelbaum, Markus Armbruster, Michael S. Tsirkin,
	Paolo Bonzini, Peter Crosthwaite, Richard Henderson,
	Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
	Borislav Petkov

On Fri, Dec 08, 2017 at 09:55:26AM +0000, Peter Maydell wrote:
> On 7 December 2017 at 21:20, Brijesh Singh <brijesh.singh@amd.com> wrote:
> > On 12/06/2017 04:03 PM, Peter Maydell wrote:
> >> For instance, if a device gets a debug=1 transaction
> >> should it refuse to do things like read-clears-bits
> >> semantics or other side-effects you wouldn't expect
> >> of debugger accesses?
> >>
> >
> > Sorry I am not able to understand "if a device gets a debug=1 transition"
> > comment, Can you please explain me a bit more.
> 
> A device model (eg a UART) can be written to look at the
> MemTxAttrs that it's passed and behave differently if debug=1.
> 
> > If you give me example on how
> > to trigger this type of request with debug=1 then I can look into the code
> > and see what we can do when memory encryption is enabled. The things like
> > read-clears-bits semantics will be tricky.
> 
> The question was really whether we want to make this a general
> indicator of "this operation was triggered by a debugger" and
> expand that to mean "don't do things that mess with the state
> of the simulation unexpectedly", or if this is really a very
> encrypted-memory specific thing.


IMO, It sounds like a good idea to make it a general indicator of
debugger access. We may not need to be very strict about an
exact global meaning, but individual device models may for example
choose to expose additional debug registers and features or
to avoid certain register access side-effects.

In some cases it may be confusing to change the behaviour of
existing regs with side-effects based on debug access, so it may
not always make sense.

Cheers,
Edgar


> 
> By the way, I don't think this:
> 
> > /* Access the guest memory for debug purposes */
> > #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
> 
> is a great idea. Callers that care about the transaction
> attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
> is a fallback for the large set of places that don't care at all.
> 
> thanks
> -- PMM

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

* Re: [PATCH v5 01/23] memattrs: add debug attribute
  2017-12-08  9:55         ` [Qemu-devel] " Peter Maydell
@ 2017-12-08 22:57           ` Brijesh Singh
  -1 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-08 22:57 UTC (permalink / raw)
  To: Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Edgar E . Iglesias, Eduardo Habkost,
	Eric Blake, kvm-devel, Marcel Apfelbaum, Markus Armbruster,
	Michael S. Tsirkin, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi



On 12/8/17 3:55 AM, Peter Maydell wrote:
>> If you give me example on how
>> to trigger this type of request with debug=1 then I can look into the code
>> and see what we can do when memory encryption is enabled. The things like
>> read-clears-bits semantics will be tricky.
> The question was really whether we want to make this a general
> indicator of "this operation was triggered by a debugger" and
> expand that to mean "don't do things that mess with the state
> of the simulation unexpectedly", or if this is really a very
> encrypted-memory specific thing.

It can be used as a generic indicator that operation was triggered by a
debugger. There is not anything encryption specific. Having said that,
in the current patch series I have been only focused on making it work
from the gdbstub and HMP point of view. The debug=1 from gdbstub and HMP
is tested on both encrypted and non-encrypted guest. If we decide to
extend to support other callers (device model etc) then we may need to
update memory load/store functions defined in memory_ldst_inc.c to work
with debug=1.

> By the way, I don't think this:
>
>> /* Access the guest memory for debug purposes */
>> #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
> is a great idea. Callers that care about the transaction
> attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
> is a fallback for the large set of places that don't care at all.

OK, I will drop the macro and update the patches in the series to set
MemTxAttr.debug = 1 when we do debugger request.  thanks

--Brijesh

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

* Re: [Qemu-devel] [PATCH v5 01/23] memattrs: add debug attribute
@ 2017-12-08 22:57           ` Brijesh Singh
  0 siblings, 0 replies; 68+ messages in thread
From: Brijesh Singh @ 2017-12-08 22:57 UTC (permalink / raw)
  To: Peter Maydell
  Cc: brijesh.singh, QEMU Developers, Alistair Francis,
	Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
	Dr. David Alan Gilbert, Edgar E . Iglesias, Eduardo Habkost,
	Eric Blake, kvm-devel, Marcel Apfelbaum, Markus Armbruster,
	Michael S. Tsirkin, Paolo Bonzini, Peter Crosthwaite,
	Richard Henderson, Richard Henderson, Stefan Hajnoczi,
	Thomas Lendacky, Borislav Petkov



On 12/8/17 3:55 AM, Peter Maydell wrote:
>> If you give me example on how
>> to trigger this type of request with debug=1 then I can look into the code
>> and see what we can do when memory encryption is enabled. The things like
>> read-clears-bits semantics will be tricky.
> The question was really whether we want to make this a general
> indicator of "this operation was triggered by a debugger" and
> expand that to mean "don't do things that mess with the state
> of the simulation unexpectedly", or if this is really a very
> encrypted-memory specific thing.

It can be used as a generic indicator that operation was triggered by a
debugger. There is not anything encryption specific. Having said that,
in the current patch series I have been only focused on making it work
from the gdbstub and HMP point of view. The debug=1 from gdbstub and HMP
is tested on both encrypted and non-encrypted guest. If we decide to
extend to support other callers (device model etc) then we may need to
update memory load/store functions defined in memory_ldst_inc.c to work
with debug=1.

> By the way, I don't think this:
>
>> /* Access the guest memory for debug purposes */
>> #define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
> is a great idea. Callers that care about the transaction
> attributes should just specify them properly. MEMTXATTRS_UNSPECIFIED
> is a fallback for the large set of places that don't care at all.

OK, I will drop the macro and update the patches in the series to set
MemTxAttr.debug = 1 when we do debugger request.  thanks

--Brijesh

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

end of thread, other threads:[~2017-12-08 22:57 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-06 20:03 [PATCH v5 00/23] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-12-06 20:03 ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 01/23] memattrs: add debug attribute Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 22:03   ` Peter Maydell
2017-12-06 22:03     ` [Qemu-devel] " Peter Maydell
2017-12-07 21:20     ` Brijesh Singh
2017-12-07 21:20       ` [Qemu-devel] " Brijesh Singh
2017-12-08  9:55       ` Peter Maydell
2017-12-08  9:55         ` [Qemu-devel] " Peter Maydell
2017-12-08 10:24         ` Edgar E. Iglesias
2017-12-08 10:24           ` [Qemu-devel] " Edgar E. Iglesias
2017-12-08 22:57         ` Brijesh Singh
2017-12-08 22:57           ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 02/23] exec: add ram_debug_ops support Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 03/23] exec: add debug version of physical memory read and write API Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 04/23] monitor/i386: use debug APIs when accessing guest memory Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 05/23] target/i386: add memory encryption feature cpuid support Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 06/23] machine: add -memory-encryption property Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 07/23] kvm: update kvm.h to include memory encryption ioctls Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 08/23] docs: add AMD Secure Encrypted Virtualization (SEV) Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 09/23] accel: add Secure Encrypted Virtulization (SEV) object Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 10/23] sev: add command to initialize the memory encryption context Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 11/23] sev: register the guest memory range which may contain encrypted data Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 12/23] kvm: introduce memory encryption APIs Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 13/23] hmp: display memory encryption support in 'info kvm' Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 14/23] sev: add command to create launch memory encryption context Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 15/23] sev: add command to encrypt guest memory region Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 16/23] target/i386: encrypt bios rom Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 17/23] qapi: add SEV_MEASUREMENT event Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 18/23] sev: emit the " Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 19/23] sev: Finalize the SEV guest launch flow Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 20/23] hw: i386: set ram_debug_ops when memory encryption is enabled Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 21/23] sev: add debug encrypt and decrypt commands Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 22/23] target/i386: clear C-bit when walking SEV guest page table Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-06 20:03 ` [PATCH v5 23/23] sev: add migration blocker Brijesh Singh
2017-12-06 20:03   ` [Qemu-devel] " Brijesh Singh
2017-12-07 11:03   ` Dr. David Alan Gilbert
2017-12-07 11:03     ` [Qemu-devel] " Dr. David Alan Gilbert
2017-12-07 11:10     ` Peter Maydell
2017-12-07 11:10       ` [Qemu-devel] " Peter Maydell
2017-12-07 11:27       ` Dr. David Alan Gilbert
2017-12-07 11:27         ` [Qemu-devel] " Dr. David Alan Gilbert
2017-12-07 21:25         ` Brijesh Singh
2017-12-07 21:25           ` [Qemu-devel] " Brijesh Singh
2017-12-07 22:50     ` Brijesh Singh
2017-12-07 22:50       ` [Qemu-devel] " Brijesh Singh

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.