Discussion:
[Qemu-devel] [RFC PATCH v3 00/18] x86: Secure Encrypted Virtualization (AMD)
Brijesh Singh
2016-11-01 15:51:49 UTC
Permalink
This RFC series provides support for AMD's new Secure Encrypted
Virtualization (SEV) feature. This RFC is based KVM RFC [1].

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

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

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


The following links provide additional details:

AMD Memory Encryption whitepaper:

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

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

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

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

KVM RFC link:

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

Video of the KVM Forum Talk:


---

The patch series implements booting SEV guest from unencrypted boot images
(BIOS, kernel, and initrd) received from the guest owner. In first phase
we ignore the guest policy, key-sharing and measurements etc. Will extend
this later once the first part is reviewed and merged.

Based on feedback from Paolo, I have looked into integrating SEV support in
OVMF/EDK2 BIOS and will start discussion on edk2 mailing list.

The patches are based on (8ff7fd8)

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.

TODO:
- integrate SEV SEND_* command in vmsave code path.
- integerate SEV RECEIVE_* command in vm restore code path.
- virtio support in SEV guest.
- Integrate SEV SEND and RECEIVE command in live migration.

Brijesh Singh (18):
memattrs: add debug attrs
exec: add guest RAM read and write ops
exec: add debug version of physical memory read and write apis
monitor: use debug version of memory access apis
core: add new security-policy object
kvm: add memory encryption APIs
sev: add Secure Encrypted Virtulization (SEV) support
hmp: display memory encryption support in 'info kvm'
core: loader: create memory encryption context before copying data
sev: add LAUNCH_START command
sev: add LAUNCH_UPDATE command
sev: add LAUNCH_FINISH command
sev: add DEBUG_DECRYPT command
sev: add DEBUG_ENCRYPT command
i386: register memory encryption ops
target-i386: add cpuid Fn8000_001f
i386: clear C-bit in SEV guest page table walk
migration: disable save/restore and migration on SEV guest


Makefile.target | 2
cpus.c | 2
disas.c | 2
docs/amd-memory-encryption.txt | 153 +++++++++++
exec.c | 94 ++++++-
hmp.c | 2
hw/core/Makefile.objs | 1
hw/core/loader.c | 22 ++
hw/core/machine.c | 22 ++
hw/core/security-policy.c | 166 ++++++++++++
hw/i386/pc.c | 7 +
hw/i386/pc_sysfw.c | 4
include/exec/cpu-common.h | 15 +
include/exec/memattrs.h | 4
include/exec/memory.h | 25 ++
include/hw/boards.h | 1
include/sysemu/kvm.h | 8 +
include/sysemu/security-policy.h | 75 +++++
include/sysemu/sev.h | 112 ++++++++
kvm-all.c | 90 ++++++
migration/migration.c | 7 +
migration/savevm.c | 11 +
monitor.c | 2
qapi-schema.json | 5
qemu-options.hx | 55 ++++
qmp.c | 1
sev.c | 528 ++++++++++++++++++++++++++++++++++++++
target-i386/cpu.c | 6
target-i386/helper.c | 37 ++-
target-i386/monitor.c | 80 ++++--
30 files changed, 1494 insertions(+), 45 deletions(-)
create mode 100644 docs/amd-memory-encryption.txt
create mode 100644 hw/core/security-policy.c
create mode 100644 include/sysemu/security-policy.h
create mode 100644 include/sysemu/sev.h
create mode 100644 sev.c
--
Brijesh Singh
Brijesh Singh
2016-11-01 15:51:59 UTC
Permalink
Add a new memory debug attribute, this attribute should be set when
memory read or write access is performed for debugging purposes.

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

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index e601061..b802073 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -37,6 +37,8 @@ typedef struct MemTxAttrs {
unsigned int user:1;
/* Requester ID (for MSI for example) */
unsigned int requester_id:16;
+ /* Memory access for debug purposes */
+ unsigned int debug:1;
} MemTxAttrs;

/* Bus masters which don't specify any attributes will get this,
@@ -46,4 +48,6 @@ typedef struct MemTxAttrs {
*/
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })

+/* Access the guest memory for debug purposes */
+#define MEMTXATTRS_DEBUG ((MemTxAttrs) { .debug = 1 })
#endif
Brijesh Singh
2016-11-01 15:52:08 UTC
Permalink
In current implementation, read and write of the guest RAM is
performed using using memcpy(). This patch adds support to register
a callback which can override the memcpy() with something else.

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

a typical usage:

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

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

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

Signed-off-by: Brijesh Singh <***@amd.com>
---
exec.c | 55 ++++++++++++++++++++++++++++++++++++-------------
include/exec/memory.h | 25 ++++++++++++++++++++++
2 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/exec.c b/exec.c
index 4d08581..d3356cd 100644
--- a/exec.c
+++ b/exec.c
@@ -2751,11 +2751,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;
@@ -2769,13 +2771,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, addr, attrs, buf, l,
+ type == WRITE_DATA);
+ break;
+ case FLUSH_CACHE:
+ break;
+ }
} else {
/* ROM/RAM case */
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (type) {
+ case READ_DATA:
+ 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:
@@ -2794,7 +2816,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)
@@ -2809,8 +2832,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 {
@@ -3641,6 +3666,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;

while (len > 0) {
int asidx;
@@ -3649,6 +3675,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;
@@ -3656,14 +3686,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 79ccaab..ce389be 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -167,6 +167,18 @@ struct MemoryRegionOps {
const MemoryRegionMmio old_mmio;
};

+/* Memory Region RAM callback */
+typedef struct MemoryRegionRAMReadWriteOps MemoryRegionRAMReadWriteOps;
+
+struct MemoryRegionRAMReadWriteOps {
+ /* Write data into guest memory */
+ int (*write) (uint8_t *dest, const uint8_t *src,
+ uint32_t len, MemTxAttrs attrs);
+ /* Read data from guest memory */
+ int (*read) (uint8_t *dest, const uint8_t *src,
+ uint32_t len, MemTxAttrs attrs);
+};
+
typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;

struct MemoryRegionIOMMUOps {
@@ -224,6 +236,7 @@ struct MemoryRegion {
MemoryRegionIoeventfd *ioeventfds;
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
IOMMUNotifierFlag iommu_notify_flags;
+ const MemoryRegionRAMReadWriteOps *ram_debug_ops;
};

/**
@@ -506,6 +519,18 @@ void memory_region_init_rom_device(MemoryRegion *mr,
Error **errp);

/**
+ * memory_region_set_ram_ops: Set the Read/Write ops for accessing the RAM
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that will be used to read/write @target region
+ */
+static inline void memory_region_set_ram_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.
*
Brijesh Singh
2016-11-01 15:52:19 UTC
Permalink
The patch 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

The idea behind this patch is that if all the qemu monitor memory dumps
and gdbserver accesses are done through these common APIs then in future
we can define some kind of global debug policy to control debug behavior.

Signed-off-by: Brijesh Singh <***@amd.com>
Reviewed-by: Paolo Bonzini <***@redhat.com>
---
exec.c | 32 ++++++++++++++++++++++++++++++++
include/exec/cpu-common.h | 15 +++++++++++++++
2 files changed, 47 insertions(+)

diff --git a/exec.c b/exec.c
index d3356cd..4022e13 100644
--- a/exec.c
+++ b/exec.c
@@ -3149,6 +3149,30 @@ uint32_t ldl_phys(AddressSpace *as, hwaddr addr)
return address_space_ldl(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
}

+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;
+}
+
uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr)
{
return address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
@@ -3659,6 +3683,14 @@ void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
}

+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+ int len, int is_write)
+{
+ cpu_physical_memory_rw_debug_internal(&address_space_memory, addr,
+ buf, len, MEMTXATTRS_DEBUG,
+ is_write ? WRITE_DATA : READ_DATA);
+}
+
/* 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 cffdc13..9abff47 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -67,6 +67,8 @@ size_t qemu_ram_pagesize(RAMBlock *block);

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)
{
@@ -77,6 +79,19 @@ static inline void cpu_physical_memory_write(hwaddr addr,
{
cpu_physical_memory_rw(addr, (void *)buf, len, 1);
}
+static inline void cpu_physical_memory_read_debug(hwaddr addr,
+ void *buf, int len)
+{
+ cpu_physical_memory_rw_debug(addr, buf, len, 0);
+}
+static inline void cpu_physical_memory_write_debug(hwaddr addr,
+ const void *buf, int len)
+{
+ cpu_physical_memory_rw_debug(addr, (void *)buf, len, 1);
+}
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr);
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr);
+
void *cpu_physical_memory_map(hwaddr addr,
hwaddr *plen,
int is_write);
Brijesh Singh
2016-11-01 15:52:50 UTC
Permalink
Add APIs to provide guest memory encryption support.

Signed-off-by: Brijesh Singh <***@amd.com>
---
include/sysemu/kvm.h | 8 ++++++
kvm-all.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index df67cc0..db00673 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -227,6 +227,14 @@ int kvm_init_vcpu(CPUState *cpu);
int kvm_cpu_exec(CPUState *cpu);
int kvm_destroy_vcpu(CPUState *cpu);

+bool kvm_memory_encryption_enabled(void);
+int kvm_memory_encryption_start(void);
+int kvm_memory_encryption_finish(void);
+void *kvm_memory_encryption_get_handle(void);
+void kvm_memory_encryption_set_debug_ops(MemoryRegion *mr);
+int kvm_memory_encryption_dec(uint8_t *dst, const uint8_t *src, uint32_t len);
+int kvm_memory_encryption_enc(uint8_t *dst, const uint8_t *src, uint32_t len);
+
#ifdef NEED_CPU_H
#include "cpu.h"

diff --git a/kvm-all.c b/kvm-all.c
index 330219e..86c810e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -36,6 +36,7 @@
#include "qemu/event_notifier.h"
#include "trace.h"
#include "hw/irq.h"
+#include "sysemu/security-policy.h"

#include "hw/boards.h"

@@ -101,6 +102,16 @@ struct KVMState
#endif
KVMMemoryListener memory_listener;
QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
+
+ /* memory encryption support */
+ void *ehandle;
+ int (*mem_encrypt_start)(void *ehandle);
+ int (*mem_encrypt_finish)(void *ehandle);
+ int (*mem_encrypt_dec)(void *ehandle, uint8_t *dst, const uint8_t *src,
+ uint32_t len);
+ int (*mem_encrypt_enc)(void *ehandle, uint8_t *dst, const uint8_t *src,
+ uint32_t len);
+ void (*mem_encrypt_debug_ops)(void *ehandle, MemoryRegion *mr);
};

KVMState *kvm_state;
@@ -127,6 +138,59 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_LAST_INFO
};

+bool kvm_memory_encryption_enabled(void)
+{
+ return kvm_state->ehandle ? true : false;
+}
+
+int kvm_memory_encryption_start(void)
+{
+ if (kvm_state->mem_encrypt_start) {
+ return kvm_state->mem_encrypt_start(kvm_state->ehandle);
+ }
+
+ return 1;
+}
+
+int kvm_memory_encryption_finish(void)
+{
+ if (kvm_state->mem_encrypt_finish) {
+ return kvm_state->mem_encrypt_finish(kvm_state->ehandle);
+ }
+
+ return 1;
+}
+
+int kvm_memory_encryption_dec(uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ if (kvm_state->mem_encrypt_dec) {
+ return kvm_state->mem_encrypt_dec(kvm_state->ehandle, dst, src, len);
+ }
+
+ return 1;
+}
+
+int kvm_memory_encryption_enc(uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ if (kvm_state->mem_encrypt_enc) {
+ return kvm_state->mem_encrypt_enc(kvm_state->ehandle, dst, src, len);
+ }
+
+ return 1;
+}
+
+void kvm_memory_encryption_set_debug_ops(MemoryRegion *mr)
+{
+ if (kvm_state->mem_encrypt_debug_ops) {
+ return kvm_state->mem_encrypt_debug_ops(kvm_state->ehandle, mr);
+ }
+}
+
+void *kvm_memory_encryption_get_handle(void)
+{
+ return kvm_state->ehandle;
+}
+
int kvm_get_max_memslots(void)
{
KVMState *s = KVM_STATE(current_machine->accelerator);
Brijesh Singh
2016-11-01 15:52:27 UTC
Permalink
updates hmp monitor to use debug version of memory access apis when
accessing the guest memory.

Signed-off-by: Brijesh Singh <***@amd.com>
---
cpus.c | 2 +-
disas.c | 2 +-
monitor.c | 2 +-
target-i386/helper.c | 14 +++++++-------
target-i386/monitor.c | 47 +++++++++++++++++++++++++++++------------------
5 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/cpus.c b/cpus.c
index 5213351..bf9836a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1654,7 +1654,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 67f116a..8861441 100644
--- a/disas.c
+++ b/disas.c
@@ -354,7 +354,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
CPUDebug *s = container_of(info, CPUDebug, info);

if (monitor_disas_is_physical) {
- cpu_physical_memory_read(memaddr, myaddr, length);
+ cpu_physical_memory_read_debug(memaddr, myaddr, length);
} else {
cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
}
diff --git a/monitor.c b/monitor.c
index 7b963ad..1378491 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1301,7 +1301,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
if (l > line_size)
l = line_size;
if (is_physical) {
- cpu_physical_memory_read(addr, buf, l);
+ cpu_physical_memory_read_debug(addr, buf, l);
} else {
if (cpu_memory_rw_debug(mon_get_cpu(), addr, buf, l, 0) < 0) {
monitor_printf(mon, " Cannot access memory\n");
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 4ecc091..e707350 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1034,13 +1034,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
env->a20_mask;
- pml4e = x86_ldq_phys(cs, pml4e_addr);
+ pml4e = ldq_phys_debug(cs, pml4e_addr);
if (!(pml4e & PG_PRESENT_MASK)) {
return -1;
}
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
(((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
+ pdpe = ldq_phys_debug(cs, pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK)) {
return -1;
}
@@ -1055,14 +1055,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
env->a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
+ pdpe = ldq_phys_debug(cs, pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
}

pde_addr = ((pdpe & PG_ADDRESS_MASK) +
(((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
- pde = x86_ldq_phys(cs, pde_addr);
+ pde = ldq_phys_debug(cs, pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
return -1;
}
@@ -1075,7 +1075,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pte_addr = ((pde & PG_ADDRESS_MASK) +
(((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
page_size = 4096;
- pte = x86_ldq_phys(cs, pte_addr);
+ pte = ldq_phys_debug(cs, pte_addr);
}
if (!(pte & PG_PRESENT_MASK)) {
return -1;
@@ -1085,7 +1085,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)

/* page directory entry */
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
- pde = x86_ldl_phys(cs, pde_addr);
+ pde = ldl_phys_debug(cs, pde_addr);
if (!(pde & PG_PRESENT_MASK))
return -1;
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -1094,7 +1094,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
} else {
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
- pte = x86_ldl_phys(cs, pte_addr);
+ pte = 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 9a3b4d7..2d125c5 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -122,20 +122,22 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
}

#ifdef TARGET_X86_64
-static void tlb_info_64(Monitor *mon, CPUArchState *env)
+static void tlb_info_64(Monitor *mon, CPUState *cs)
{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUArchState *env = &cpu->env;
uint64_t l1, l2, l3, l4;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr;

pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+ pml4e = ldq_phys_debug(cs, pml4_addr + l1 * 8);
pml4e = le64_to_cpu(pml4e);
if (pml4e & PG_PRESENT_MASK) {
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+ pdpe = ldq_phys_debug(cs, pdp_addr + l2 * 8);
pdpe = le64_to_cpu(pdpe);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
@@ -145,7 +147,7 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
} else {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+ pde = ldq_phys_debug(cs, pd_addr + l3 * 8);
pde = le64_to_cpu(pde);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
@@ -156,9 +158,8 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)
} else {
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
+ pte = ldq_phys_debug(cs,
+ pt_addr + l4 * 8);
pte = le64_to_cpu(pte);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, (l1 << 39) +
@@ -181,9 +182,14 @@ static void tlb_info_64(Monitor *mon, CPUArchState *env)

void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
+ X86CPU *cpu;
+ CPUState *cs;
CPUArchState *env;

- env = mon_get_cpu_env();
+ cs = mon_get_cpu();
+ cpu = X86_CPU(cs);
+ env = &cpu->env;
+

if (!(env->cr[0] & CR0_PG_MASK)) {
monitor_printf(mon, "PG disabled\n");
@@ -192,7 +198,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
if (env->cr[4] & CR4_PAE_MASK) {
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
- tlb_info_64(mon, env);
+ tlb_info_64(mon, cs);
} else
#endif
{
@@ -324,10 +330,12 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)


#ifdef TARGET_X86_64
-static void mem_info_64(Monitor *mon, CPUArchState *env)
+static void mem_info_64(Monitor *mon, CPUState *cs)
{
int prot, last_prot;
uint64_t l1, l2, l3, l4;
+ X86CPU *cpu = X86_CPU(cs);
+ CPUArchState *env = &cpu->env;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;

@@ -335,13 +343,13 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+ pml4e = ldq_phys_debug(cs, pml4_addr + l1 * 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);
+ pdpe = ldq_phys_debug(cs, pdp_addr + l2 * 8);
pdpe = le64_to_cpu(pdpe);
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
@@ -353,7 +361,7 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
} else {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+ pde = ldq_phys_debug(cs, pd_addr + l3 * 8);
pde = le64_to_cpu(pde);
end = (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
@@ -365,9 +373,8 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)
} else {
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
+ pte = ldq_phys_debug(cs,
+ pt_addr + l4 * 8);
pte = le64_to_cpu(pte);
end = (l1 << 39) + (l2 << 30) +
(l3 << 21) + (l4 << 12);
@@ -404,9 +411,13 @@ static void mem_info_64(Monitor *mon, CPUArchState *env)

void hmp_info_mem(Monitor *mon, const QDict *qdict)
{
+ X86CPU *cpu;
+ CPUState *cs;
CPUArchState *env;

- env = mon_get_cpu_env();
+ cs = mon_get_cpu();
+ cpu = X86_CPU(cs);
+ env = &cpu->env;

if (!(env->cr[0] & CR0_PG_MASK)) {
monitor_printf(mon, "PG disabled\n");
@@ -415,7 +426,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
if (env->cr[4] & CR4_PAE_MASK) {
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
- mem_info_64(mon, env);
+ mem_info_64(mon, cs);
} else
#endif
{
Brijesh Singh
2016-11-01 15:53:32 UTC
Permalink
The command is used to prepare a guest for the transition into
SEV-enabled mode.

Command uses the parameters specified in 'sev-launch-info' object, see
doc/amd-memory-encryption.txt for parameter details. The command creates
a new VM Encryption Key (VEK) and cryptographic context. The key created
during launch start process will be used to encrypt the guest memory.

Signed-off-by: Brijesh Singh <***@amd.com>
---
sev.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)

diff --git a/sev.c b/sev.c
index 487dba6..2fbab2f 100644
--- a/sev.c
+++ b/sev.c
@@ -33,6 +33,30 @@ static MemoryRegionRAMReadWriteOps sev_ops;
static bool sev_allowed;

static void
+str_to_uint8_ptr(const char *str, uint8_t *ptr, int count)
+{
+ int i = 0;
+
+ while (*str && i != count) {
+ sscanf(str, "%2hhx", &ptr[i]);
+ str += 2;
+ i++;
+ }
+}
+
+static void
+DPRINTF_U8_PTR(const char *name, const uint8_t *ptr, int count)
+{
+ int i;
+
+ DPRINTF("%s = ", name);
+ for (i = 0; i < count; i++) {
+ DPRINTF("%02hhx", ptr[i]);
+ }
+ DPRINTF("\n");
+}
+
+static void
qsev_guest_finalize(Object *obj)
{
}
@@ -189,8 +213,65 @@ static const TypeInfo qsev_launch_info = {


static int
+sev_ioctl(int cmd, void *data)
+{
+ int ret;
+ struct kvm_sev_issue_cmd input;
+
+ input.cmd = cmd;
+ input.opaque = (__u64)data;
+ ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input);
+ if (ret) {
+ fprintf(stderr, "sev_ioctl failed cmd=%#x, ret=%d(%#010x)\n",
+ cmd, ret, input.ret_code);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void
+get_sev_property_ptr(Object *obj, const char *name, uint8_t *ptr, int count)
+{
+ char *value;
+
+ value = object_property_get_str(obj, name, &error_abort);
+ str_to_uint8_ptr(value, ptr, count);
+ DPRINTF_U8_PTR(name, ptr, count);
+ g_free(value);
+}
+
+static int
sev_launch_start(SEVState *s)
{
+ int ret;
+ Object *obj;
+ struct kvm_sev_launch_start *start;
+
+ if (s->state == SEV_STATE_LAUNCHING) {
+ return 0;
+ }
+
+ start = g_malloc0(sizeof(*start));
+ if (!start) {
+ return 1;
+ }
+
+ obj = object_property_get_link(OBJECT(s->sev_info), "launch", &error_abort);
+ get_sev_property_ptr(obj, "dh-pub-qx", start->dh_pub_qx,
+ sizeof(start->dh_pub_qx));
+ get_sev_property_ptr(obj, "dh-pub-qy", start->dh_pub_qy,
+ sizeof(start->dh_pub_qy));
+ get_sev_property_ptr(obj, "nonce", start->nonce, sizeof(start->nonce));
+ ret = sev_ioctl(KVM_SEV_LAUNCH_START, start);
+ if (ret < 0) {
+ return 1;
+ }
+
+ s->state = SEV_STATE_LAUNCHING;
+ g_free(start);
+
+ DPRINTF("SEV: LAUNCH_START\n");
return 0;
}
Brijesh Singh
2016-11-01 15:52:38 UTC
Permalink
The object can be used to define global security policy for the guest.

object provides two properties:

1) debug: can be used to disable guest memory access from hypervisor.

e.g to disable guest memory debug from qemu monitor

# $QEMU \
-object security-policy,debug=false,id=mypolicy \
-machine ...,security-policy=mypolicy

2) memory-encryption: if guest supports memory encryption then property
should be set to memory encryption object id.

# $QEMU \
-object sev-guest,id=sev0 \
-object security-policy,id=memory-encryption=sev0,id=mypolicy \
-machine ...,security-policy=mypolicy

Signed-off-by: Brijesh Singh <***@amd.com>
---
exec.c | 7 ++
hw/core/Makefile.objs | 1
hw/core/machine.c | 22 +++++
hw/core/security-policy.c | 166 ++++++++++++++++++++++++++++++++++++++
include/hw/boards.h | 1
include/sysemu/security-policy.h | 75 +++++++++++++++++
qemu-options.hx | 21 +++++
7 files changed, 293 insertions(+)
create mode 100644 hw/core/security-policy.c
create mode 100644 include/sysemu/security-policy.h

diff --git a/exec.c b/exec.c
index 4022e13..e9ed975 100644
--- a/exec.c
+++ b/exec.c
@@ -42,6 +42,7 @@
#include "exec/memory.h"
#include "exec/ioport.h"
#include "sysemu/dma.h"
+#include "sysemu/security-policy.h"
#include "exec/address-spaces.h"
#include "sysemu/xen-mapcache.h"
#include "trace.h"
@@ -2764,6 +2765,12 @@ static inline void cpu_physical_memory_rw_debug_internal(AddressSpace *as,
hwaddr addr1;
MemoryRegion *mr;

+ if (attrs.debug &&
+ !security_policy_debug_allowed(current_machine->security_policy)) {
+ fprintf(stderr, "WARNING: debug is disabled\n");
+ return;
+ }
+
rcu_read_lock();
while (len > 0) {
l = len;
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index a4c94e5..7641dac 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -18,5 +18,6 @@ common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
common-obj-$(CONFIG_SOFTMMU) += register.o
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
+common-obj-$(CONFIG_SOFTMMU) += security-policy.o

obj-$(CONFIG_SOFTMMU) += generic-loader.o
diff --git a/hw/core/machine.c b/hw/core/machine.c
index b0fd91f..b23b931 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -332,6 +332,23 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp)
return ms->enforce_config_section;
}

+static char *machine_get_security_policy(Object *obj, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ return g_strdup(ms->security_policy);
+}
+
+static void machine_set_security_policy(Object *obj,
+ const char *value, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ g_free(ms->security_policy);
+ ms->security_policy = g_strdup(value);
+}
+
+
static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
{
error_report("Option '-device %s' cannot be handled by this machine",
@@ -462,6 +479,11 @@ 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, "security-policy",
+ machine_get_security_policy, machine_set_security_policy, NULL);
+ object_class_property_set_description(oc, "security-policy",
+ "Set the security policy for the machine", NULL);
}

static void machine_class_base_init(ObjectClass *oc, void *data)
diff --git a/hw/core/security-policy.c b/hw/core/security-policy.c
new file mode 100644
index 0000000..92689ff
--- /dev/null
+++ b/hw/core/security-policy.c
@@ -0,0 +1,166 @@
+/*
+ * QEMU security policy support
+ *
+ * Copyright (c) 2016 Advanced Micro Devices
+ *
+ * Author:
+ * Brijesh Singh <***@amd.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "qemu/base64.h"
+#include "trace.h"
+
+#include "sysemu/security-policy.h"
+
+static SecurityPolicy *
+find_security_policy_obj(const char *name)
+{
+ Object *obj;
+ SecurityPolicy *policy;
+
+ if (!name) {
+ return NULL;
+ }
+
+ obj = object_resolve_path_component(
+ object_get_objects_root(), name);
+ if (!obj) {
+ return NULL;
+ }
+
+ policy = (SecurityPolicy *)
+ object_dynamic_cast(obj,
+ TYPE_SECURITY_POLICY);
+ if (!policy) {
+ return NULL;
+ }
+
+ return policy;
+}
+
+bool
+security_policy_debug_allowed(const char *secure_policy_id)
+{
+ SecurityPolicy *policy = find_security_policy_obj(secure_policy_id);
+
+ /* if id is not a valid security policy then we return true */
+ return policy ? policy->debug : true;
+}
+
+char *
+security_policy_get_memory_encryption_id(const char *secure_policy_id)
+{
+ SecurityPolicy *policy = find_security_policy_obj(secure_policy_id);
+
+ return policy ? g_strdup(policy->memory_encryption) : NULL;
+}
+
+static bool
+security_policy_prop_get_debug(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ SecurityPolicy *policy = SECURITY_POLICY(obj);
+
+ return policy->debug;
+}
+
+
+static void
+security_policy_prop_set_debug(Object *obj,
+ bool value,
+ Error **errp G_GNUC_UNUSED)
+{
+ SecurityPolicy *policy = SECURITY_POLICY(obj);
+
+ policy->debug = value;
+}
+
+static char *
+sev_launch_get_memory_encryption(Object *obj, Error **errp)
+{
+ SecurityPolicy *policy = SECURITY_POLICY(obj);
+
+ return g_strdup(policy->memory_encryption);
+}
+
+static void
+sev_launch_set_memory_encryption(Object *obj, const char *value,
+ Error **errp)
+{
+ SecurityPolicy *policy = SECURITY_POLICY(obj);
+
+ policy->memory_encryption = g_strdup(value);
+}
+
+static void
+security_policy_init(Object *obj)
+{
+ SecurityPolicy *policy = SECURITY_POLICY(obj);
+
+ policy->debug = true;
+}
+
+static void
+security_policy_finalize(Object *obj)
+{
+}
+
+static void
+security_policy_class_init(ObjectClass *oc, void *data)
+{
+ object_class_property_add_bool(oc, "debug",
+ security_policy_prop_get_debug,
+ security_policy_prop_set_debug,
+ NULL);
+ object_class_property_set_description(oc, "debug",
+ "Set on/off if debugging is allowed on this guest (default on)",
+ NULL);
+ object_class_property_add_str(oc, "memory-encryption",
+ sev_launch_get_memory_encryption,
+ sev_launch_set_memory_encryption,
+ NULL);
+ object_class_property_set_description(oc, "memory-encryption",
+ "Set memory encryption object id (if supported by hardware)",
+ NULL);
+}
+
+static const TypeInfo security_policy_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_SECURITY_POLICY,
+ .instance_size = sizeof(SecurityPolicy),
+ .instance_init = security_policy_init,
+ .instance_finalize = security_policy_finalize,
+ .class_size = sizeof(SecurityPolicyClass),
+ .class_init = security_policy_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+security_policy_register_types(void)
+{
+ type_register_static(&security_policy_info);
+}
+
+
+type_init(security_policy_register_types);
diff --git a/include/hw/boards.h b/include/hw/boards.h
index a51da9c..de1a412 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -150,6 +150,7 @@ struct MachineState {
/*< public >*/

char *accel;
+ char *security_policy;
bool kernel_irqchip_allowed;
bool kernel_irqchip_required;
bool kernel_irqchip_split;
diff --git a/include/sysemu/security-policy.h b/include/sysemu/security-policy.h
new file mode 100644
index 0000000..6d3789d
--- /dev/null
+++ b/include/sysemu/security-policy.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU security policy support
+ *
+ * Copyright (c) 2016 Advanced Micro Devices
+ *
+ * Author:
+ * Brijesh Singh <***@amd.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SECURITY_POLICY_H
+#define SECURITY_POLICY_H
+
+#include "qom/object.h"
+
+#define TYPE_SECURITY_POLICY "security-policy"
+#define SECURITY_POLICY(obj) \
+ OBJECT_CHECK(SecurityPolicy, (obj), TYPE_SECURITY_POLICY)
+
+typedef struct SecurityPolicy SecurityPolicy;
+typedef struct SecurityPolicyClass SecurityPolicyClass;
+
+/**
+ * SecurityPolicy:
+ *
+ * The SecurityPolicy object provides method to define
+ * various security releated policies for guest machine.
+ *
+ * e.g
+ * When launching QEMU, user can create a security policy
+ * to disallow memory dump and debug of guest
+ *
+ * # $QEMU \
+ * -object security-policy,id=mypolicy,debug=off \
+ * -machine ...,security-policy=mypolicy
+ *
+ * If hardware supports memory encryption then user can set
+ * encryption policy of guest
+ *
+ * # $QEMU \
+ * -object encrypt-policy,key=xxx,flags=xxxx,id=encrypt \
+ * -object security-policy,debug=off,memory-encryption=encrypt,id=mypolicy \
+ * -machine ...,security-policy=mypolicy
+ *
+ */
+
+struct SecurityPolicy {
+ Object parent_obj;
+
+ bool debug;
+ char *memory_encryption;
+};
+
+
+struct SecurityPolicyClass {
+ ObjectClass parent_class;
+};
+
+bool security_policy_debug_allowed(const char *name);
+char *security_policy_get_memory_encryption_id(const char *name);
+
+#endif /* SECURITY_POLICY_H */
diff --git a/qemu-options.hx b/qemu-options.hx
index 95332cc..7a65015 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4027,6 +4027,27 @@ contents of @code{iv.b64} to the second secret

@end table

+@item -object security-policy,id=@var{id}[,debug=@var{bool}][,memory-encryption=@var{string}]
+
+Create a security policy object, which can be used to define guest security.
+The id parameter is a unique ID that will be used to reference this
+object when security-policy is applied via -machine argument.
+
+The 'debug' parameter can be defined to tell whether the debugging or memory
+dump is allowed through qemu monitor console.
+
+e.g to disable the guest memory dump
+@example
+ # $QEMU \
+ -object security-policy,id=secure0,debug=off \
+ -machine ...,security-policy=secure0
+@end example
+
+if hardware support guest memory encrytion, then 'memory-encryption' parameter
+can be set to the unquie ID of memory encryption object.
+
+On AMD processor, memory encryption is supported via 'sev-guest' object.
+
ETEXI
Brijesh Singh
2016-11-01 15:53:12 UTC
Permalink
update 'info kvm' to display the memory encryption support.

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

Signed-off-by: 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 b5e3f54..b9abb60 100644
--- a/hmp.c
+++ b/hmp.c
@@ -82,6 +82,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 8a7b527..2091193 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -120,9 +120,12 @@
#
# @present: true if KVM acceleration is built into this executable
#
+# @mem-encryption: true if Memory Encryption is active (since 2.8)
+#
# 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 0028f0b..b7b2e7a 100644
--- a/qmp.c
+++ b/qmp.c
@@ -68,6 +68,7 @@ KvmInfo *qmp_query_kvm(Error **errp)

info->enabled = kvm_enabled();
info->present = kvm_available();
+ info->mem_encryption = kvm_memory_encryption_enabled();

return info;
}
Brijesh Singh
2016-11-01 15:53:00 UTC
Permalink
This patch adds the initial support required to integrate Secure
Encrypted Virtualization (SEV) feature. SEV is an extension to the
existing AMD-V technology found on AMD processors. The SEV feature
allows the memory contents of a virtual machine to be transparently
encrypted with a key unique to the guest VM.

In QEMU command line, SEV can be enabled via memory-encryption property
defined in security-policy object.

The patch adds the following new objects:

- sev-launch-info: provides the properties to set/get parameters used
to boot SEV guest from unencrypted boot images.

In this mode the OS images (kernel, initrd and bios) provides by guest
owner are unencrypted. The SEV guest boot process would encrypt the
images using the guest owners PDH key provided through this object.

- sev-guest: a top level object to transition a guest into SEV-enabled

e.g to launch SEV guest from unencrypted boot images
# $QEMU \
-object sev-launch-info,id=launch0,nonce=abcd,pub-dh-qx=1234 \
-object sev-guest,id,sev0 \
-object security-policy,id=secure0,memory-encryption=sev0 \
-machine ....,security-policy=secure0

Signed-off-by: Brijesh Singh <***@amd.com>
---
Makefile.target | 2
docs/amd-memory-encryption.txt | 153 +++++++++++++++++
include/sysemu/sev.h | 112 +++++++++++++
kvm-all.c | 26 +++
qemu-options.hx | 34 ++++
sev.c | 350 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 676 insertions(+), 1 deletion(-)
create mode 100644 docs/amd-memory-encryption.txt
create mode 100644 include/sysemu/sev.h
create mode 100644 sev.c

diff --git a/Makefile.target b/Makefile.target
index 7a5080e..004c3cd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -137,7 +137,7 @@ ifdef CONFIG_SOFTMMU
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
obj-y += qtest.o bootdevice.o
obj-y += hw/
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
obj-y += memory.o cputlb.o
obj-y += memory_mapping.o
obj-y += dump.o
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
new file mode 100644
index 0000000..682f8e9
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,153 @@
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+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 used by different VMs in the system.
+The programming and management of these keys is handled by the AMD Secure
+Processor firmware which exposes commands for these tasks.
+
+At highest level the SEV key management APIs are divided into two sections:
+
+* Platform management commands
+* Guest management commands
+
+In this doc we will focus on Guest management commands.
+
+SEV is capable of supporting both light-weight virtual containers as well as
+conventional VM within an enterprise cloud environment. In either case, there
+are two parties concerned in the deployment of SEV guest: the guest owner and
+the platform owner. For example, in a cloud environment, the platform owner
+would be cloud vendor and the guest owner would be the user that wishes to run
+their workload in the cloud.
+
+1. Guest Management Commands
+-----------------------------
+
+The guest management commands provide the support for common guest lifecycle
+events. These events include launching, running, snapshotting, migrating and
+decommission guest. The guest management commands are issued through
+KVM_SEV_ISSUE_CMD ioctl.
+
+1.1 Launch
+
+When a guest is launched, its memory must first be encrypted using guest owners
+key before SEV can be enabled in hardware. There are two types of launches:
+
+1.1.1 unencrypted
+
+Boot images (such as bios, kernel, initrd) provided by the guest owner to
+bootstrap the guest is unencrypted. The firmware provides interfaces to
+bootstrap the memory encryption for this purpose: LAUNCH_START, LAUNCH_UPDATE,
+and LAUNCH_FINISH. These three commands together generate a fresh memory
+encryption key for the guest, encrypt guest memory and provide an attestation
+of the successful launch.
+
+LAUNCH_START is called first to create a guest context within the firmware.
+To create this context, qemu user must provide guest's security policy, guest
+owners public Diffie-Hellman key (P-256 defined in section D.1.2.3 of
+[FIPS 186-4]) and nonce. The guest security policy is a 4-byte data structure
+containing several flags that restrict what the hypervisor can do on the running
+SEV guest. The guest security policy should be provided by the guest owner, any
+changes in policy by hypervisor would result in the wrong measurement. The policy
+is applied to the lifetime of the guest. Guest owners public diffie-hellman (pdh)
+key is used to establish a cryptographic session with the guest owner to
+negotiate keys used for attestation. If the hypervisor requests this guest to
+share key with another SEV guest then hypervisor must set 'key-sharing' and
+'handle' in LAUNCH_START command. The key sharing is permitted only if guest
+policy allows it.
+
+LAUNCH_UPDATE 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_FINISH command finalizes the guest launch and generates measurement.
+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.
+
+SEV support can be enabled via 'memory-encryption' parameters defined in
+security-policy object. If memory-encryption is enabled, then hypervisor
+uses MemoryRegionReadWriteOps callbacks to access guest memory.
+
+Before vm_start, rom_reset copies boot images from internal rom to guest memory
+as shown below.
+
+ +----------------------+
+ | qemu_system_reset |
+ +----------------------+
+ |
+ |
+ V
+ +-----------------------------+
+ | rom_reset (loader.c) |
+ +-----------------------------+
+ | | |
+ +-------------------+ | +-----------------+
+ | | |
+ V V V
+ +--------------+ +------------------+ +----------------+
+ | LAUNCH_START | | memory_rom_write | | LAUNCH_FINISH |
+ +--------------+ +------------------+ +----------------+
+ |
+ |
+ V
+ +------------------+
+ | LAUNCH_UPDATE |
+ +------------------+
+
+Input to LAUNCH_START command can be provided through the properties defined in
+'sev-launch-info' object.
+
+e.g to launch SEV guest from unencrypted boot images
+
+# ${QEMU} \
+ -object sev-launch-info,id=launch0,dh-pub-qx=abcd,dh-pub-qy=1234,nonce=1234\
+ -object sev-guest,id=sev0\
+ -object security-policy,id=mypolicy,memory-encryption=sev0\
+ -machine ...,security-policy=mypolicy
+
+e.g launch this SEV guest using another SEV guest key (key sharing)
+
+# ${QEMU} \
+ -object sev-launch-info,id=launch0,key-sharing=on,handle=1234\
+ -object sev-guest,id=sev0\
+ -object security-policy,id=mypolicy,memory-encryption=sev0\
+ -machine ...,security-policy=mypolicy
+
+1.1.2 pre-encrypted
+
+1.2 Snapshot
+
+1.3 Restore
+
+1.4 Live Migration
+
+1.5 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 is allowed to access guest memory. Hypervisor can use DEBUG_DECRYPT
+command to decrypt guest memory region for debug purposes. Similarly hypervisor
+can use DEBUG_ENCRYPT command to write into guest memory.
+
+2. 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:
+http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf
+
+KVM Forum slides:
+http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
+
+AMD64 Architecture Programmer's Manual:
+ http://support.amd.com/TechDocs/24593.pdf
+ SME is section 7.10
+ SEV is section 15.34
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 0000000..5ca39d1
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,112 @@
+/*
+ * QEMU Secure Encrypted Virutualization (SEV) support
+ *
+ * Copyright: Advanced Micro Devices, 2016
+ *
+ * Authors:
+ * 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 <linux/kvm.h>
+
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "sysemu/kvm.h"
+
+#define TYPE_QSEV_LAUNCH_INFO "sev-launch-info"
+#define QSEV_LAUNCH_INFO(obj) \
+ OBJECT_CHECK(QSevLaunchInfo, (obj), TYPE_QSEV_LAUNCH_INFO)
+
+typedef struct QSevLaunchInfo QSevLaunchInfo;
+typedef struct QSevLaunchInfoClass QSevLaunchInfoClass;
+
+/**
+ * QSevLaunchInfo:
+ *
+ * The QSevLaunchInfo object provides parameters to launch a SEV
+ * guest from unnencrypted boot images. SEV will encrypt the boot images using
+ * guest owner's key before launching the guest.
+ *
+ * # $QEMU -object sev-launch-info,id=launch0,dh-pub-qx=abcd \
+ * ....
+ */
+struct QSevLaunchInfo {
+ Object parent_obj;
+ char *nonce;
+ char *dh_pub_qx;
+ char *dh_pub_qy;
+};
+
+struct QSevLaunchInfoClass {
+ ObjectClass parent_class;
+};
+
+#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.
+ *
+ * e.g to launch a SEV guest from unencrypted boot images
+ *
+ * # $QEMU -object sev-launch-info,id=launch0 \
+ * -object sev-guest,id=sev0 \
+ * -object security-policy,id=secure0,memory-encryption=sev0 \
+ * -machine ...security-policy=secure0
+ */
+struct QSevGuestInfo {
+ Object parent_obj;
+
+ QSevLaunchInfo *launch_info;
+};
+
+struct QSevGuestInfoClass {
+ ObjectClass parent_class;
+};
+
+struct SEVState {
+ uint8_t state;
+ QSevGuestInfo *sev_info;
+};
+
+typedef struct SEVState SEVState;
+
+enum {
+ INVALID_TYPE = 0,
+ USE_LAUNCH_INFO,
+ USE_RECEIVE_INFO
+};
+
+enum {
+ SEV_STATE_INVALID = 0,
+ SEV_STATE_LAUNCHING,
+ SEV_STATE_RECEIVING,
+ SEV_STATE_SENDING,
+ SEV_STATE_RUNNING
+};
+
+bool sev_enabled(void);
+void *sev_guest_init(const char *keyid);
+int sev_guest_launch_start(void *handle);
+int sev_guest_launch_finish(void *handle);
+void sev_guest_set_debug_ops(void *handle, MemoryRegion *mr);
+int sev_guest_mem_dec(void *handle, uint8_t *dst,
+ const uint8_t *src, uint32_t len);
+int sev_guest_mem_enc(void *handle, uint8_t *dst,
+ const uint8_t *src, uint32_t len);
+
+#endif
+
diff --git a/kvm-all.c b/kvm-all.c
index 86c810e..e712b96 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -37,6 +37,7 @@
#include "trace.h"
#include "hw/irq.h"
#include "sysemu/security-policy.h"
+#include "sysemu/sev.h"

#include "hw/boards.h"

@@ -1818,6 +1819,31 @@ static int kvm_init(MachineState *ms)

kvm_state = s;

+ if (ms->security_policy) {
+ char *id;
+
+ /* if security-policy is enabled then check whether memory encryption
+ * property is defined. If so, enable hardware memory encryption.
+ */
+ id = security_policy_get_memory_encryption_id(ms->security_policy);
+ if (id) {
+
+ /* check if its SEV guest policy */
+ kvm_state->ehandle = sev_guest_init(id);
+ if (!kvm_state->ehandle) {
+ fprintf(stderr,
+ "failed to initialize SEV guest\n");
+ goto err;
+ }
+ kvm_state->mem_encrypt_start = sev_guest_launch_start;
+ kvm_state->mem_encrypt_finish = sev_guest_launch_finish;
+ kvm_state->mem_encrypt_debug_ops = sev_guest_set_debug_ops;
+ kvm_state->mem_encrypt_dec = sev_guest_mem_dec;
+ kvm_state->mem_encrypt_enc = sev_guest_mem_enc;
+ g_free(id);
+ }
+ }
+
if (kvm_eventfds_allowed) {
s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
diff --git a/qemu-options.hx b/qemu-options.hx
index 7a65015..1c1f93d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4048,6 +4048,40 @@ can be set to the unquie ID of memory encryption object.

On AMD processor, memory encryption is supported via 'sev-guest' object.

+@item -object sev-guest,id=@var{id}
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which be used to
+provide the memory encryption support on AMD processors.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+ -object sev-launch-info,id=launch0 \
+ -object sev-guest-info,id=sev0 \
+ -object security-policy,id=secure0-guest,memory-encryption=sev0 \
+ -machine ...,security-policy=secure0
+@end example
+
+@item -object sev-launch-info,id=@var{id}[,nonce=@var{string}][,dh-pub-qx=@var{string}][,dh-pub-qy=@var{string}]
+
+Create a SEV launch info object, which can be used to pass various parameters
+required to boot SEV guest from unencrypted boot images.
+The id parameter is a unique ID that should be used in sev-guest-info object
+when creating a unencrypted SEV guest.
+
+The 'nonce' parameter should be set with a nonce generated by guest owner.
+
+The 'dh-pub-qx' and 'dh-pub-qy' parameters should be set with guest owners
+ECDH public key.
+
+e.g to launch SEV guest from unencrypted boot images
+@example
+ # $QEMU \
+ -object sev-launch-info,id=launch0,nonce=abcd \
+ -object sev-guest,id=sev0 \
+@end example
+
+@end table
ETEXI


diff --git a/sev.c b/sev.c
new file mode 100644
index 0000000..487dba6
--- /dev/null
+++ b/sev.c
@@ -0,0 +1,350 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016
+ *
+ * Author:
+ * 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"
+#include "trace.h"
+
+#define DEBUG_SEV
+#ifdef DEBUG_SEV
+#define DPRINTF(fmt, ...) \
+ do { fprintf(stdout, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+static MemoryRegionRAMReadWriteOps sev_ops;
+static bool sev_allowed;
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+}
+
+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;
+}
+
+static void
+qsev_guest_init(Object *obj)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ object_property_add_link(obj, "launch", TYPE_QSEV_LAUNCH_INFO,
+ (Object **)&sev->launch_info,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE, 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
+qsev_launch_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_launch_get_nonce(Object *obj, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ return g_strdup(launch->nonce);
+}
+
+static void
+qsev_launch_set_nonce(Object *obj, const char *value, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ launch->nonce = g_strdup(value);
+}
+
+static char *
+qsev_launch_get_dh_pub_qx(Object *obj, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ return g_strdup(launch->dh_pub_qx);
+}
+
+static void
+qsev_launch_set_dh_pub_qx(Object *obj, const char *value, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ launch->dh_pub_qx = g_strdup(value);
+}
+
+static char *
+qsev_launch_get_dh_pub_qy(Object *obj, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ return g_strdup(launch->dh_pub_qy);
+}
+
+static void
+qsev_launch_set_dh_pub_qy(Object *obj, const char *value, Error **errp)
+{
+ QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+ launch->dh_pub_qy = g_strdup(value);
+}
+
+static void
+qsev_launch_class_init(ObjectClass *oc, void *data)
+{
+ object_class_property_add_str(oc, "nonce",
+ qsev_launch_get_nonce,
+ qsev_launch_set_nonce,
+ NULL);
+ object_class_property_set_description(oc, "nonce",
+ "a nonce provided by guest owner", NULL);
+
+ object_class_property_add_str(oc, "dh-pub-qx",
+ qsev_launch_get_dh_pub_qx,
+ qsev_launch_set_dh_pub_qx,
+ NULL);
+ object_class_property_set_description(oc, "dh-pub-qx",
+ "Qx parameter of owner's ECDH public key", NULL);
+
+ object_class_property_add_str(oc, "dh-pub-qy",
+ qsev_launch_get_dh_pub_qy,
+ qsev_launch_set_dh_pub_qy,
+ NULL);
+ object_class_property_set_description(oc, "dh-pub-qy",
+ "Qy parameter of owner's ECDH public key", NULL);
+}
+
+static void
+qsev_launch_init(Object *obj)
+{
+}
+
+/* guest launch */
+static const TypeInfo qsev_launch_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_QSEV_LAUNCH_INFO,
+ .instance_size = sizeof(QSevLaunchInfo),
+ .instance_finalize = qsev_launch_finalize,
+ .class_size = sizeof(QSevLaunchInfoClass),
+ .class_init = qsev_launch_class_init,
+ .instance_init = qsev_launch_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static int
+sev_launch_start(SEVState *s)
+{
+ return 0;
+}
+
+static int
+sev_launch_finish(SEVState *s)
+{
+ return 0;
+}
+
+static int
+sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+ SEVState *s = kvm_memory_encryption_get_handle();
+
+ assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+ return 0;
+}
+
+static int
+sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+ SEVState *s = kvm_memory_encryption_get_handle();
+
+ assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+ return 0;
+}
+
+static int
+sev_get_launch_type(SEVState *s)
+{
+ QSevGuestInfo *sev_info = s->sev_info;
+
+ /* if <link>QSevLaunchInfo is set then we are configured to use
+ * launch_info object.
+ */
+ if (object_property_get_link(OBJECT(sev_info), "launch", &error_abort)) {
+ return USE_LAUNCH_INFO;
+ }
+
+ return INVALID_TYPE;
+}
+
+void *
+sev_guest_init(const char *id)
+{
+ Object *obj;
+ SEVState *s;
+
+ s = g_malloc0(sizeof(SEVState));
+ if (!s) {
+ return NULL;
+ }
+
+ s->sev_info = lookup_sev_guest_info(id);
+ if (!s->sev_info) {
+ fprintf(stderr, "'%s' not a valid '%s' object\n",
+ id, TYPE_QSEV_GUEST_INFO);
+ goto err;
+ }
+
+ obj = object_resolve_path_type("", TYPE_QSEV_LAUNCH_INFO, NULL);
+ if (obj) {
+ object_property_set_link(OBJECT(s->sev_info), obj, "launch",
+ &error_abort);
+ }
+
+ sev_allowed = true;
+ return s;
+err:
+ g_free(s);
+ return NULL;
+}
+
+int
+sev_guest_launch_start(void *handle)
+{
+ SEVState *s = (SEVState *)handle;
+
+ assert(s != NULL);
+
+ /* If we are in prelaunch state then create memory encryption context based
+ * on the sev launch object created by user.
+ */
+ if (runstate_check(RUN_STATE_PRELAUNCH)) {
+ if (sev_get_launch_type(s) == USE_LAUNCH_INFO) {
+ return sev_launch_start(s);
+ }
+ }
+
+ return 1;
+}
+
+int
+sev_guest_launch_finish(void *handle)
+{
+ SEVState *s = (SEVState *)handle;
+
+ assert(s != NULL);
+
+ if (s->state == SEV_STATE_LAUNCHING) {
+ return sev_launch_finish(s);
+ }
+
+ return 1;
+}
+
+void
+sev_guest_set_debug_ops(void *handle, MemoryRegion *mr)
+{
+ SEVState *s = (SEVState *)handle;
+
+ assert(s != NULL);
+
+ sev_ops.read = sev_mem_read;
+ sev_ops.write = sev_mem_write;
+
+ memory_region_set_ram_debug_ops(mr, &sev_ops);
+}
+
+int
+sev_guest_mem_dec(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ SEVState *s = (SEVState *)handle;
+
+ assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+ /* use SEV debug command to decrypt memory */
+ return 1;
+}
+
+int
+sev_guest_mem_enc(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ SEVState *s = (SEVState *)handle;
+
+ assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+ /* use SEV debug command to decrypt memory */
+ return 1;
+}
+
+bool
+sev_enabled(void)
+{
+ return sev_allowed;
+}
+
+static void
+sev_policy_register_types(void)
+{
+ type_register_static(&qsev_guest_info);
+ type_register_static(&qsev_launch_info);
+}
+
+type_init(sev_policy_register_types);
Brijesh Singh
2016-11-01 15:53:58 UTC
Permalink
The command is used to finalize the SEV guest launch process.

The command returns a measurement value of the data encrypted through
the LAUNCH_UPDATE command. This measurement can be handed to the guest
owner to verify that the guest was launched into SEV-enabled mode.

Signed-off-by: Brijesh Singh <***@amd.com>
---
sev.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/sev.c b/sev.c
index fafef6f..ff9266a 100644
--- a/sev.c
+++ b/sev.c
@@ -278,7 +278,30 @@ sev_launch_start(SEVState *s)
static int
sev_launch_finish(SEVState *s)
{
- return 0;
+ int ret;
+ struct kvm_sev_launch_finish *data;
+
+ assert(s->state == SEV_STATE_LAUNCHING);
+
+ data = g_malloc0(sizeof(*data));
+ if (!data) {
+ return 1;
+ }
+
+ ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, data);
+ if (ret) {
+ goto err;
+ }
+
+ DPRINTF("SEV: LAUNCH_FINISH ");
+ DPRINTF_U8_PTR(" measurement", data->measurement,
+ sizeof(data->measurement));
+
+ s->state = SEV_STATE_RUNNING;
+err:
+ g_free(data);
+
+ return ret;
}

static int
Brijesh Singh
2016-11-01 15:53:20 UTC
Permalink
During system boot, rom_reset copies bios binary from internal PC.BIOS
ROM to guest RAM (PC.RAM).

If memory encryption is enabled then we need to ensure that encryption
context is created before we start the copy process. When encryption is
enabled any data copy from PC.BIOS ROM to guest RAM will go through the
encryption routines which will encrypt the data as it copies into guest
memory. Similarly after we are done with copying destory the encryption
context.

Signed-off-by: Brijesh Singh <***@amd.com>
---
hw/core/loader.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 6e022b5..52c7e2c 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -55,6 +55,7 @@
#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "qemu/cutils.h"
+#include "sysemu/kvm.h"

#include <zlib.h>

@@ -1045,8 +1046,20 @@ int rom_add_option(const char *file, int32_t bootindex)

static void rom_reset(void *unused)
{
+ int ret;
Rom *rom;

+ /* create the memory encryption context before we copy any data
+ * from internal ROM to guest RAM.
+ */
+ if (kvm_memory_encryption_enabled()) {
+ ret = kvm_memory_encryption_start();
+ if (ret) {
+ fprintf(stderr, "failed to create memory encryption context\n");
+ return;
+ }
+ }
+
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->fw_file) {
continue;
@@ -1074,6 +1087,15 @@ static void rom_reset(void *unused)
*/
cpu_flush_icache_range(rom->addr, rom->datasize);
}
+
+ /* delete the memory encryption context after we are done with copying */
+ if (kvm_memory_encryption_enabled()) {
+ ret = kvm_memory_encryption_finish();
+ if (ret) {
+ fprintf(stderr, "failed to destory memory encryption context\n");
+ return;
+ }
+ }
}

int rom_check_and_register_reset(void)
Brijesh Singh
2016-11-01 15:54:56 UTC
Permalink
Snapshot, Restore and Migration is not implemented in first phase.

Return error when user tries to perform any of these operations.

Signed-off-by: Brijesh Singh <***@amd.com>
---
migration/migration.c | 7 +++++++
migration/savevm.c | 11 +++++++++++
2 files changed, 18 insertions(+)

diff --git a/migration/migration.c b/migration/migration.c
index e331f28..676c94c 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -37,6 +37,7 @@
#include "io/channel-buffer.h"
#include "io/channel-tls.h"
#include "migration/colo.h"
+#include "sysemu/sev.h"

#define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */

@@ -1150,6 +1151,12 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
error_setg(errp, QERR_MIGRATION_ACTIVE);
return;
}
+
+ if (sev_enabled()) {
+ error_setg(errp, "Migration is not implemented on SEV guest\n");
+ return;
+ }
+
if (runstate_check(RUN_STATE_INMIGRATE)) {
error_setg(errp, "Guest is waiting for an incoming migration");
return;
diff --git a/migration/savevm.c b/migration/savevm.c
index 0363372..f125716 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -54,6 +54,7 @@
#include "qemu/cutils.h"
#include "io/channel-buffer.h"
#include "io/channel-file.h"
+#include "sysemu/sev.h"

#ifndef ETH_P_RARP
#define ETH_P_RARP 0x8035
@@ -2027,6 +2028,11 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
Error *local_err = NULL;
AioContext *aio_context;

+ if (sev_enabled()) {
+ monitor_printf(mon, "savevm is not implemented on SEV guest\n");
+ return;
+ }
+
if (!bdrv_all_can_snapshot(&bs)) {
monitor_printf(mon, "Device '%s' is writable but does not "
"support snapshots.\n", bdrv_get_device_name(bs));
@@ -2176,6 +2182,11 @@ int load_vmstate(const char *name)
int ret;
AioContext *aio_context;

+ if (sev_enabled()) {
+ error_report("loadvm is not implemented on SEV guest\n");
+ return -ENOTSUP;
+ }
+
if (!bdrv_all_can_snapshot(&bs)) {
error_report("Device '%s' is writable but does not support snapshots.",
bdrv_get_device_name(bs));
Brijesh Singh
2016-11-01 15:53:48 UTC
Permalink
The command is used to encrypt a guest memory region using the VM Encryption
Key (VEK) created by LAUNCH_START command. The firmware will also update
the measurement with the contents of the memory region. This measurement
can be retrieved by calling LAUNCH_FINISH command.

Signed-off-by: Brijesh Singh <***@amd.com>
---
sev.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/sev.c b/sev.c
index 2fbab2f..fafef6f 100644
--- a/sev.c
+++ b/sev.c
@@ -282,12 +282,41 @@ sev_launch_finish(SEVState *s)
}

static int
+sev_launch_update(SEVState *s, uint8_t *addr, uint32_t len)
+{
+ int ret;
+ struct kvm_sev_launch_update *data;
+
+ data = g_malloc0(sizeof(*data));
+ if (!data) {
+ return 1;
+ }
+
+ data->address = (__u64)addr;
+ data->length = len;
+ ret = sev_ioctl(KVM_SEV_LAUNCH_UPDATE, data);
+ if (ret) {
+ goto err;
+ }
+
+ DPRINTF("SEV: LAUNCH_UPDATE %#lx+%#x\n", (unsigned long)addr, len);
+err:
+ g_free(data);
+ return ret;
+}
+
+static int
sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
{
SEVState *s = kvm_memory_encryption_get_handle();

assert(s != NULL && s->state != SEV_STATE_INVALID);

+ if (s->state == SEV_STATE_LAUNCHING) {
+ memcpy(dst, src, len);
+ return sev_launch_update(s, dst, len);
+ }
+
return 0;
}
Brijesh Singh
2016-11-01 15:54:06 UTC
Permalink
The command is used to decrypt a page of guest memory for debug.

The command will be used by qemu monitor dump and gdbserver to access
the guest memory for debug purposes. A typical usage look like:

cpu_physical_memory_rw_debug
cpu_physical_memory_rw_debug_internal
sev_debug_decrypt

Signed-off-by: Brijesh Singh <***@amd.com>
---
sev.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/sev.c b/sev.c
index ff9266a..f690a86 100644
--- a/sev.c
+++ b/sev.c
@@ -329,6 +329,28 @@ err:
}

static int
+sev_debug_decrypt(SEVState *s, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ int ret;
+ struct kvm_sev_dbg_decrypt *dbg;
+
+ dbg = g_malloc0(sizeof(*dbg));
+ if (!dbg) {
+ return 1;
+ }
+
+ dbg->src_addr = (unsigned long)src;
+ dbg->dst_addr = (unsigned long)dst;
+ dbg->length = len;
+
+ ret = sev_ioctl(KVM_SEV_DBG_DECRYPT, dbg);
+ DPRINTF("SEV: DBG_DECRYPT src %#lx dst %#lx len %#x\n",
+ (uint64_t)src, (uint64_t)dst, len);
+ g_free(dbg);
+ return ret;
+}
+
+static int
sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
{
SEVState *s = kvm_memory_encryption_get_handle();
@@ -348,9 +370,9 @@ sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
{
SEVState *s = kvm_memory_encryption_get_handle();

- assert(s != NULL && s->state != SEV_STATE_INVALID);
+ assert(attrs.debug || (s != NULL && s->state != SEV_STATE_INVALID));

- return 0;
+ return sev_debug_decrypt(s, dst, src, len);
}

static int
@@ -453,7 +475,7 @@ sev_guest_mem_dec(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
assert(s != NULL && s->state != SEV_STATE_INVALID);

/* use SEV debug command to decrypt memory */
- return 1;
+ return sev_debug_decrypt((SEVState *)handle, dst, src, len);
}

int
Brijesh Singh
2016-11-01 15:54:34 UTC
Permalink
Fn8000_001f cpuid provides the memory encryption (aka C-bit) location
in a page table for the SEV-enabled guest.

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

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 83998a8..9dc7b4f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -34,6 +34,7 @@
#include "qapi-visit.h"
#include "qapi/visitor.h"
#include "sysemu/arch_init.h"
+#include "sysemu/sev.h"

#if defined(CONFIG_KVM)
#include <linux/kvm_para.h>
@@ -2733,6 +2734,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = 0;
}
break;
+ case 0x8000001F:
+ if (sev_enabled()) {
+ host_cpuid(index, 0, eax, ebx, ecx, edx);
+ }
+ break;
case 0xC0000000:
*eax = env->cpuid_xlevel2;
*ebx = 0;
Brijesh Singh
2016-11-01 15:54:23 UTC
Permalink
If guest is launched with memory encryption enabled then register
PC.BIOS and PC.RAM memory regions with memory encryption handler.

Registering PC.BIOS memory region will ensure that memory encryption
routines will be used when rom_reset copies the BIOS image into guest memory.

A typical sequence look like:
qemy_system_reset
rom_reset
cpu_physical_memory_write_rom
cpu_phyiscal_memory_rw_debug_internal
memory_encryption->write


Similarly registering PC.RAM region will ensure that any debug accesses from
qemu monitor or gdbserver will go through the memory encryption routines to
decrypt/encrypt the guest RAM regions.

A sequence looks like:
cpu_phyiscal_memory_rw_debug
cpu_phyiscal_memory_rw_debug_internal
memory_encryption->write

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

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f56ea0f..1b76159 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1402,6 +1402,13 @@ void pc_memory_init(PCMachineState *pcms,
e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
}

+ /* if memory encryption is enabled then set the memory encryption
+ * ops so that any debug read and write to guest memory from hypervisor will
+ * go through encryption routines. */
+ if (kvm_memory_encryption_enabled()) {
+ kvm_memory_encryption_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 f915ad0..243beda 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -208,6 +208,9 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
}
g_free(filename);

+ if (kvm_memory_encryption_enabled()) {
+ kvm_memory_encryption_set_debug_ops(bios);
+ }
/* map the last 128KB of the BIOS in ISA space */
isa_bios_size = bios_size;
if (isa_bios_size > (128 * 1024)) {
@@ -228,6 +231,7 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
memory_region_add_subregion(rom_memory,
(uint32_t)(-bios_size),
bios);
+
}

void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
Brijesh Singh
2016-11-01 15:54:15 UTC
Permalink
The command is used to encrypt a region of guest memory for debug.

The command will be used by gdbserver when writing the data into guest
memory for debug purposes (e.g setting breakpoint)

A typical usage looks like:
cpu_memory_rw_debug
cpu_physical_memory_rw_debug_internal
sev_debug_encrypt

Signed-off-by: Brijesh Singh <***@amd.com>
---
sev.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/sev.c b/sev.c
index f690a86..1a579ca 100644
--- a/sev.c
+++ b/sev.c
@@ -351,18 +351,41 @@ sev_debug_decrypt(SEVState *s, uint8_t *dst, const uint8_t *src, uint32_t len)
}

static int
+sev_debug_encrypt(SEVState *s, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+ int ret;
+ struct kvm_sev_dbg_encrypt *dbg;
+
+ dbg = g_malloc0(sizeof(*dbg));
+ if (!dbg) {
+ return 1;
+ }
+
+ dbg->src_addr = (unsigned long)src;
+ dbg->dst_addr = (unsigned long)dst;
+ dbg->length = len;
+
+ ret = sev_ioctl(KVM_SEV_DBG_ENCRYPT, dbg);
+ DPRINTF("SEV: debug encrypt src %#lx dst %#lx len %#x\n",
+ (unsigned long)src, (unsigned long)dst, len);
+ g_free(dbg);
+
+ return ret;
+}
+
+static int
sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
{
SEVState *s = kvm_memory_encryption_get_handle();

- assert(s != NULL && s->state != SEV_STATE_INVALID);
+ assert(attrs.debug || (s != NULL && s->state != SEV_STATE_INVALID));

if (s->state == SEV_STATE_LAUNCHING) {
memcpy(dst, src, len);
return sev_launch_update(s, dst, len);
}

- return 0;
+ return sev_debug_encrypt(s, dst, src, len);
}

static int
@@ -486,7 +509,7 @@ sev_guest_mem_enc(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
assert(s != NULL && s->state != SEV_STATE_INVALID);

/* use SEV debug command to decrypt memory */
- return 1;
+ return sev_debug_encrypt((SEVState *)handle, dst, src, len);
}

bool
Brijesh Singh
2016-11-01 15:54:46 UTC
Permalink
In SEV-enabled guest the physical addresses in page table will
have C-bit set, we need to clear the C-bit when walking the page table.
The C-bit position should be available in cpuid Fn8000_001f[EBX]

Signed-off-by: Brijesh Singh <***@amd.com>
---
target-i386/helper.c | 37 ++++++++++++++++++++++++++++++-------
target-i386/monitor.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/target-i386/helper.c b/target-i386/helper.c
index e707350..cc5c37c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -22,6 +22,7 @@
#include "exec/exec-all.h"
#include "sysemu/kvm.h"
#include "kvm_i386.h"
+#include "sysemu/sev.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h"
#include "monitor/monitor.h"
@@ -1006,6 +1007,22 @@ do_check_protect_pse36:
return 1;
}

+static uint64_t get_me_mask(void)
+{
+ uint64_t me_mask = 0;
+
+ /* In SEV guest page tables addresses will have memory encryption bit set,
+ * C-bit should be cleared while doing the page table walk.
+ */
+ if (sev_enabled()) {
+ uint32_t pos;
+ pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+ me_mask = (1UL << pos);
+ }
+
+ return ~me_mask;
+}
+
hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
X86CPU *cpu = X86_CPU(cs);
@@ -1014,6 +1031,12 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
uint64_t pte;
uint32_t page_offset;
int page_size;
+ uint64_t me_mask;
+
+ me_mask = get_me_mask();
+
+ /* In SEV guest, CR3 will have memory encryption bit set, clear it */
+ env->cr[3] &= me_mask;

if (!(env->cr[0] & CR0_PG_MASK)) {
pte = addr & env->a20_mask;
@@ -1034,13 +1057,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
env->a20_mask;
- pml4e = 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)) & env->a20_mask;
- pdpe = ldq_phys_debug(cs, pdpe_addr);
+ pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
if (!(pdpe & PG_PRESENT_MASK)) {
return -1;
}
@@ -1055,14 +1078,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
env->a20_mask;
- pdpe = ldq_phys_debug(cs, pdpe_addr);
+ 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)) & env->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;
}
@@ -1075,7 +1098,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pte_addr = ((pde & PG_ADDRESS_MASK) +
(((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
page_size = 4096;
- pte = ldq_phys_debug(cs, pte_addr);
+ pte = ldq_phys_debug(cs, pte_addr) & me_mask;
}
if (!(pte & PG_PRESENT_MASK)) {
return -1;
@@ -1085,7 +1108,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)

/* page directory entry */
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
- pde = ldl_phys_debug(cs, pde_addr);
+ 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)) {
@@ -1094,7 +1117,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
} else {
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
- pte = 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 2d125c5..ffb0479 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -27,6 +27,7 @@
#include "monitor/hmp-target.h"
#include "hw/i386/pc.h"
#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
#include "hmp.h"


@@ -54,6 +55,22 @@ static void print_pte(Monitor *mon, hwaddr addr,
pte & PG_RW_MASK ? 'W' : '-');
}

+static uint64_t get_me_mask(void)
+{
+ uint64_t me_mask = 0;
+
+ /* In SEV guest page tables addresses will have memory encryption bit set,
+ * C-bit should be cleared while doing the page table walk.
+ */
+ if (sev_enabled()) {
+ uint32_t pos;
+ pos = kvm_arch_get_supported_cpuid(kvm_state, 0x8000001f, 0, R_EBX);
+ me_mask = (1UL << pos);
+ }
+
+ return ~me_mask;
+}
+
static void tlb_info_32(Monitor *mon, CPUArchState *env)
{
unsigned int l1, l2;
@@ -129,15 +146,21 @@ static void tlb_info_64(Monitor *mon, CPUState *cs)
uint64_t l1, l2, l3, l4;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr;
+ uint64_t me_mask;
+
+ me_mask = get_me_mask();

pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+ pml4_addr &= me_mask;
for (l1 = 0; l1 < 512; l1++) {
pml4e = ldq_phys_debug(cs, pml4_addr + l1 * 8);
+ pml4e &= me_mask;
pml4e = le64_to_cpu(pml4e);
if (pml4e & PG_PRESENT_MASK) {
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
pdpe = ldq_phys_debug(cs, pdp_addr + l2 * 8);
+ pdpe &= me_mask;
pdpe = le64_to_cpu(pdpe);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
@@ -148,6 +171,7 @@ static void tlb_info_64(Monitor *mon, CPUState *cs)
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
pde = ldq_phys_debug(cs, pd_addr + l3 * 8);
+ pde &= me_mask;
pde = le64_to_cpu(pde);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
@@ -160,6 +184,7 @@ static void tlb_info_64(Monitor *mon, CPUState *cs)
for (l4 = 0; l4 < 512; l4++) {
pte = ldq_phys_debug(cs,
pt_addr + l4 * 8);
+ pte &= me_mask;
pte = le64_to_cpu(pte);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, (l1 << 39) +
@@ -338,12 +363,17 @@ static void mem_info_64(Monitor *mon, CPUState *cs)
CPUArchState *env = &cpu->env;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+ uint64_t me_mask;
+
+ me_mask = get_me_mask();

pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+ pml4_addr &= me_mask;
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 512; l1++) {
pml4e = ldq_phys_debug(cs, pml4_addr + l1 * 8);
+ pml4e &= me_mask;
pml4e = le64_to_cpu(pml4e);
end = l1 << 39;
if (pml4e & PG_PRESENT_MASK) {
@@ -351,6 +381,7 @@ static void mem_info_64(Monitor *mon, CPUState *cs)
for (l2 = 0; l2 < 512; l2++) {
pdpe = ldq_phys_debug(cs, pdp_addr + l2 * 8);
pdpe = le64_to_cpu(pdpe);
+ pdpe &= me_mask;
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
@@ -362,6 +393,7 @@ static void mem_info_64(Monitor *mon, CPUState *cs)
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
pde = ldq_phys_debug(cs, pd_addr + l3 * 8);
+ pde &= me_mask;
pde = le64_to_cpu(pde);
end = (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
@@ -375,6 +407,7 @@ static void mem_info_64(Monitor *mon, CPUState *cs)
for (l4 = 0; l4 < 512; l4++) {
pte = ldq_phys_debug(cs,
pt_addr + l4 * 8);
+ pte &= me_mask;
pte = le64_to_cpu(pte);
end = (l1 << 39) + (l2 << 30) +
(l3 << 21) + (l4 << 12);
n***@patchew.org
2016-11-01 16:22:20 UTC
Permalink
Hi,

Your series seems to have some coding style problems. See output below for
more information:

Type: series
Subject: [Qemu-devel] [RFC PATCH v3 00/18] x86: Secure Encrypted Virtualization (AMD)
Message-id: ***@brijesh-build-machine

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
* [new tag] patchew/***@brijesh-build-machine -> patchew/***@brijesh-build-machine
Switched to a new branch 'test'
c628575 migration: disable save/restore and migration on SEV guest
bcc9622 i386: clear C-bit in SEV guest page table walk
13f1aec target-i386: add cpuid Fn8000_001f
e32e371 i386: register memory encryption ops
23d4ae8 sev: add DEBUG_ENCRYPT command
73d2734 sev: add DEBUG_DECRYPT command
ec4a4f5 sev: add LAUNCH_FINISH command
07766c2 sev: add LAUNCH_UPDATE command
60727f5 sev: add LAUNCH_START command
7fba3df core: loader: create memory encryption context before copying data
54a514a hmp: display memory encryption support in 'info kvm'
38fa75b sev: add Secure Encrypted Virtulization (SEV) support
54afe9f kvm: add memory encryption APIs
4c505a9 core: add new security-policy object
a2865ab monitor: use debug version of memory access apis
7725400 exec: add debug version of physical memory read and write apis
01aff50 exec: add guest RAM read and write ops
69f6122 memattrs: add debug attrs

=== OUTPUT BEGIN ===
fatal: unrecognized argument: --no-patch
Checking PATCH 1/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 2/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 3/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 4/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 5/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 6/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 7/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 8/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 9/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 10/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 11/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 12/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 13/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 14/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 15/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 16/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 17/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 18/18: ...
ERROR: Error messages should not contain newlines
#31: FILE: migration/migration.c:1156:
+ error_setg(errp, "Migration is not implemented on SEV guest\n");

ERROR: Error messages should not contain newlines
#67: FILE: migration/savevm.c:2186:
+ error_report("loadvm is not implemented on SEV guest\n");

total: 2 errors, 0 warnings, 48 lines checked

Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please
Peter Maydell
2016-11-01 16:31:02 UTC
Permalink
Post by n***@patchew.org
Hi,
Your series seems to have some coding style problems. See output below for
Fam, it looks like patchew's test script is assuming git arguments
Post by n***@patchew.org
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
=== OUTPUT BEGIN ===
fatal: unrecognized argument: --no-patch
Checking PATCH 1/18: ...
fatal: unrecognized argument: --no-patch
Checking PATCH 2/18: ...
fatal: unrecognized argument: --no-patch
[etc]

thanks
-- PMM

n***@patchew.org
2016-11-01 16:24:37 UTC
Permalink
Hi,

Your series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Type: series
Subject: [Qemu-devel] [RFC PATCH v3 00/18] x86: Secure Encrypted Virtualization (AMD)
Message-id: ***@brijesh-build-machine

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=16
make docker-test-***@centos6
make docker-test-***@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
c628575 migration: disable save/restore and migration on SEV guest
bcc9622 i386: clear C-bit in SEV guest page table walk
13f1aec target-i386: add cpuid Fn8000_001f
e32e371 i386: register memory encryption ops
23d4ae8 sev: add DEBUG_ENCRYPT command
73d2734 sev: add DEBUG_DECRYPT command
ec4a4f5 sev: add LAUNCH_FINISH command
07766c2 sev: add LAUNCH_UPDATE command
60727f5 sev: add LAUNCH_START command
7fba3df core: loader: create memory encryption context before copying data
54a514a hmp: display memory encryption support in 'info kvm'
38fa75b sev: add Secure Encrypted Virtulization (SEV) support
54afe9f kvm: add memory encryption APIs
4c505a9 core: add new security-policy object
a2865ab monitor: use debug version of memory access apis
7725400 exec: add debug version of physical memory read and write apis
01aff50 exec: add guest RAM read and write ops
69f6122 memattrs: add debug attrs

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 'dtc'...
Submodule path 'dtc': checked out '65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf'
BUILD centos6
make[1]: Entering directory `/var/tmp/patchew-tester-tmp-fw8uaplr/src'
ARCHIVE qemu.tgz
ARCHIVE dtc.tgz
COPY RUNNER
RUN test-quick in qemu:centos6
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=libfdt-devel ccache tar git make gcc g++ zlib-devel glib2-devel SDL-devel pixman-devel epel-release
HOSTNAME=5bc4d872dc8b
TERM=xterm
MAKEFLAGS= -j16
HISTSIZE=1000
J=16
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix /var/tmp/qemu-build/install
BIOS directory /var/tmp/qemu-build/install/share/qemu
binary directory /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory /var/tmp/qemu-build/install/etc
local state directory /var/tmp/qemu-build/install/var
Manual directory /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path /tmp/qemu-test/src
C compiler cc
Host C compiler cc
C++ compiler
Objective-C compiler cc
ARFLAGS rv
CFLAGS -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g
QEMU_CFLAGS -I/usr/include/pixman-1 -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all
LDFLAGS -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g
make make
install install
python python -B
smbd /usr/sbin/smbd
module support no
host CPU x86_64
host big endian no
target list x86_64-softmmu aarch64-softmmu
tcg debug enabled no
gprof enabled no
sparse enabled no
strip binaries yes
profiler no
static build no
pixman system
SDL support yes (1.2.14)
GTK support no
GTK GL support no
VTE support no
TLS priority NORMAL
GNUTLS support no
GNUTLS rnd no
libgcrypt no
libgcrypt kdf no
nettle no
nettle kdf no
libtasn1 no
curses support no
virgl support no
curl support no
mingw32 support no
Audio drivers oss
Block whitelist (rw)
Block whitelist (ro)
VirtFS support no
VNC support yes
VNC SASL support no
VNC JPEG support no
VNC PNG support no
xen support no
brlapi support no
bluez support no
Documentation no
PIE yes
vde support no
netmap support no
Linux AIO support no
ATTR/XATTR support yes
Install blobs yes
KVM support yes
COLO support yes
RDMA support no
TCG interpreter no
fdt support yes
preadv support yes
fdatasync yes
madvise yes
posix_madvise yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends log
spice support no
rbd support no
xfsctl support no
smartcard support no
libusb no
usb net redir no
OpenGL support no
OpenGL dmabufs no
libiscsi support no
libnfs support no
build guest agent yes
QGA VSS support no
QGA w32 disk info no
QGA MSI support no
seccomp support no
coroutine backend ucontext
coroutine pool yes
debug stack usage no
GlusterFS support no
Archipelago support no
gcov gcov
gcov enabled no
TPM support yes
libssh2 support no
TPM passthrough yes
QOM debugging yes
lzo support no
snappy support no
bzip2 support no
NUMA host support no
tcmalloc support no
jemalloc support no
avx2 optimization no
replication support yes
GEN x86_64-softmmu/config-devices.mak.tmp
GEN aarch64-softmmu/config-devices.mak.tmp
GEN config-host.h
GEN qemu-options.def
GEN qmp-commands.h
GEN qapi-types.h
GEN qapi-visit.h
GEN qmp-introspect.h
GEN qapi-event.h
GEN module_block.h
GEN tests/test-qapi-types.h
GEN tests/test-qapi-visit.h
GEN tests/test-qmp-commands.h
GEN tests/test-qapi-event.h
GEN tests/test-qmp-introspect.h
GEN trace/generated-tracers.h
GEN x86_64-softmmu/config-devices.mak
GEN aarch64-softmmu/config-devices.mak
GEN trace/generated-tcg-tracers.h
GEN trace/generated-helpers-wrappers.h
GEN trace/generated-helpers.h
GEN config-all-devices.mak
CC tests/qemu-iotests/socket_scm_helper.o
GEN qga/qapi-generated/qga-qapi-types.h
GEN qga/qapi-generated/qga-qapi-visit.h
GEN qga/qapi-generated/qga-qmp-commands.h
GEN qga/qapi-generated/qga-qapi-types.c
GEN qga/qapi-generated/qga-qapi-visit.c
GEN qga/qapi-generated/qga-qmp-marshal.c
GEN qmp-introspect.c
GEN qapi-types.c
GEN qapi-visit.c
GEN qapi-event.c
CC qapi/qapi-visit-core.o
CC qapi/qapi-dealloc-visitor.o
CC qapi/qobject-input-visitor.o
CC qapi/qobject-output-visitor.o
CC qapi/qmp-registry.o
CC qapi/qmp-dispatch.o
CC qapi/string-input-visitor.o
CC qapi/string-output-visitor.o
CC qapi/opts-visitor.o
CC qapi/qapi-clone-visitor.o
CC qapi/qmp-event.o
CC qapi/qapi-util.o
CC qobject/qnull.o
CC qobject/qint.o
CC qobject/qstring.o
CC qobject/qdict.o
CC qobject/qlist.o
CC qobject/qfloat.o
CC qobject/qbool.o
CC qobject/qjson.o
CC qobject/qobject.o
CC qobject/json-lexer.o
CC qobject/json-streamer.o
CC qobject/json-parser.o
GEN trace/generated-tracers.c
CC trace/qmp.o
CC trace/control.o
CC util/osdep.o
CC util/cutils.o
CC util/unicode.o
CC util/qemu-timer-common.o
CC util/bufferiszero.o
CC util/compatfd.o
CC util/event_notifier-posix.o
CC util/mmap-alloc.o
CC util/oslib-posix.o
CC util/qemu-openpty.o
CC util/qemu-thread-posix.o
CC util/memfd.o
CC util/envlist.o
CC util/path.o
CC util/module.o
CC util/bitmap.o
CC util/bitops.o
CC util/hbitmap.o
CC util/fifo8.o
CC util/error.o
CC util/acl.o
CC util/qemu-error.o
CC util/id.o
CC util/iov.o
CC util/qemu-config.o
CC util/qemu-sockets.o
CC util/uri.o
CC util/notify.o
CC util/qemu-option.o
CC util/qemu-progress.o
CC util/hexdump.o
CC util/uuid.o
CC util/crc32c.o
CC util/throttle.o
CC util/getauxval.o
CC util/readline.o
CC util/rcu.o
CC util/qemu-coroutine.o
CC util/qemu-coroutine-io.o
CC util/qemu-coroutine-lock.o
CC util/qemu-coroutine-sleep.o
CC util/coroutine-ucontext.o
CC util/buffer.o
CC util/timed-average.o
CC util/base64.o
CC util/log.o
CC util/qdist.o
CC util/qht.o
CC util/range.o
CC crypto/pbkdf-stub.o
CC stubs/arch-query-cpu-def.o
CC stubs/arch-query-cpu-model-expansion.o
CC stubs/arch-query-cpu-model-comparison.o
CC stubs/arch-query-cpu-model-baseline.o
CC stubs/bdrv-next-monitor-owned.o
CC stubs/blk-commit-all.o
CC stubs/blockdev-close-all-bdrv-states.o
CC stubs/clock-warp.o
CC stubs/cpu-get-clock.o
CC stubs/cpu-get-icount.o
CC stubs/dump.o
CC stubs/fdset-add-fd.o
CC stubs/fdset-find-fd.o
CC stubs/fdset-get-fd.o
CC stubs/fdset-remove-fd.o
CC stubs/gdbstub.o
CC stubs/get-fd.o
CC stubs/get-next-serial.o
CC stubs/get-vm-name.o
CC stubs/iothread.o
CC stubs/iothread-lock.o
CC stubs/is-daemonized.o
CC stubs/machine-init-done.o
CC stubs/migr-blocker.o
CC stubs/mon-is-qmp.o
CC stubs/mon-printf.o
CC stubs/monitor-init.o
CC stubs/notify-event.o
CC stubs/qtest.o
CC stubs/replay.o
CC stubs/replay-user.o
CC stubs/reset.o
CC stubs/runstate-check.o
CC stubs/set-fd-handler.o
CC stubs/slirp.o
CC stubs/sysbus.o
CC stubs/trace-control.o
CC stubs/uuid.o
CC stubs/vm-stop.o
CC stubs/vmstate.o
CC stubs/cpus.o
CC stubs/kvm.o
CC stubs/qmp_pc_dimm_device_list.o
CC stubs/target-monitor-defs.o
CC stubs/target-get-monitor-def.o
CC stubs/vhost.o
CC stubs/iohandler.o
CC stubs/smbios_type_38.o
CC stubs/ipmi.o
CC stubs/pc_madt_cpu_entry.o
CC stubs/migration-colo.o
CC contrib/ivshmem-client/ivshmem-client.o
CC contrib/ivshmem-client/main.o
CC contrib/ivshmem-server/ivshmem-server.o
CC contrib/ivshmem-server/main.o
CC qemu-nbd.o
CC async.o
CC thread-pool.o
CC block.o
CC blockjob.o
CC main-loop.o
CC iohandler.o
CC qemu-timer.o
CC aio-posix.o
CC qemu-io-cmds.o
CC replication.o
CC block/qcow.o
CC block/raw_bsd.o
CC block/vdi.o
CC block/vmdk.o
CC block/cloop.o
CC block/bochs.o
CC block/vpc.o
CC block/vvfat.o
CC block/qcow2.o
CC block/dmg.o
CC block/qcow2-refcount.o
CC block/qcow2-cluster.o
CC block/qcow2-snapshot.o
CC block/qcow2-cache.o
CC block/qed.o
CC block/qed-gencb.o
CC block/qed-l2-cache.o
CC block/qed-table.o
CC block/qed-cluster.o
CC block/qed-check.o
CC block/vhdx.o
CC block/vhdx-endian.o
CC block/vhdx-log.o
CC block/quorum.o
CC block/parallels.o
CC block/blkdebug.o
CC block/blkverify.o
CC block/blkreplay.o
CC block/block-backend.o
CC block/qapi.o
CC block/snapshot.o
CC block/null.o
CC block/raw-posix.o
CC block/mirror.o
CC block/commit.o
CC block/io.o
CC block/throttle-groups.o
CC block/nbd.o
CC block/nbd-client.o
CC block/sheepdog.o
CC block/accounting.o
CC block/dirty-bitmap.o
CC block/write-threshold.o
CC block/backup.o
CC block/replication.o
CC block/crypto.o
CC nbd/server.o
CC nbd/client.o
CC nbd/common.o
CC crypto/init.o
CC crypto/hash.o
CC crypto/hash-glib.o
CC crypto/aes.o
CC crypto/desrfb.o
CC crypto/cipher.o
CC crypto/tlscreds.o
CC crypto/tlscredsanon.o
CC crypto/tlscredsx509.o
CC crypto/tlssession.o
CC crypto/secret.o
CC crypto/random-platform.o
CC crypto/pbkdf.o
CC crypto/ivgen.o
CC crypto/ivgen-essiv.o
CC crypto/ivgen-plain.o
CC crypto/ivgen-plain64.o
CC crypto/afsplit.o
CC crypto/xts.o
CC crypto/block.o
CC crypto/block-qcow.o
CC crypto/block-luks.o
CC io/channel.o
CC io/channel-buffer.o
CC io/channel-command.o
CC io/channel-file.o
CC io/channel-tls.o
CC io/channel-socket.o
CC io/channel-watch.o
CC io/channel-websock.o
CC io/channel-util.o
CC io/task.o
CC qom/object.o
CC qom/container.o
CC qom/qom-qobject.o
CC qom/object_interfaces.o
GEN qemu-img-cmds.h
CC qemu-io.o
CC qemu-bridge-helper.o
CC blockdev.o
CC blockdev-nbd.o
CC iothread.o
CC qdev-monitor.o
CC device-hotplug.o
CC os-posix.o
CC qemu-char.o
CC page_cache.o
CC accel.o
CC bt-host.o
CC bt-vhci.o
CC dma-helpers.o
CC vl.o
CC tpm.o
GEN qmp-marshal.c
CC device_tree.o
CC qmp.o
CC hmp.o
CC cpus-common.o
CC audio/audio.o
CC audio/noaudio.o
CC audio/wavaudio.o
CC audio/mixeng.o
CC audio/sdlaudio.o
CC audio/ossaudio.o
CC audio/wavcapture.o
CC backends/rng.o
CC backends/rng-egd.o
CC backends/rng-random.o
CC backends/msmouse.o
CC backends/testdev.o
CC backends/tpm.o
CC backends/hostmem.o
CC backends/hostmem-ram.o
CC backends/hostmem-file.o
CC block/stream.o
CC disas/arm.o
CC disas/i386.o
CC fsdev/qemu-fsdev-dummy.o
CC fsdev/qemu-fsdev-opts.o
CC hw/acpi/core.o
CC hw/acpi/piix4.o
CC hw/acpi/pcihp.o
CC hw/acpi/ich9.o
CC hw/acpi/tco.o
CC hw/acpi/cpu_hotplug.o
CC hw/acpi/memory_hotplug.o
CC hw/acpi/memory_hotplug_acpi_table.o
CC hw/acpi/cpu.o
CC hw/acpi/acpi_interface.o
CC hw/acpi/bios-linker-loader.o
CC hw/acpi/aml-build.o
CC hw/acpi/ipmi.o
CC hw/audio/sb16.o
CC hw/audio/es1370.o
CC hw/audio/ac97.o
CC hw/audio/fmopl.o
CC hw/audio/adlib.o
CC hw/audio/gus.o
CC hw/audio/gusemu_hal.o
CC hw/audio/gusemu_mixer.o
CC hw/audio/cs4231a.o
CC hw/audio/intel-hda.o
CC hw/audio/hda-codec.o
CC hw/audio/pcspk.o
CC hw/audio/wm8750.o
CC hw/audio/pl041.o
CC hw/audio/lm4549.o
CC hw/audio/marvell_88w8618.o
CC hw/block/block.o
CC hw/block/cdrom.o
CC hw/block/hd-geometry.o
CC hw/block/fdc.o
CC hw/block/m25p80.o
CC hw/block/nand.o
CC hw/block/pflash_cfi01.o
CC hw/block/pflash_cfi02.o
CC hw/block/ecc.o
CC hw/block/onenand.o
CC hw/block/nvme.o
CC hw/bt/core.o
CC hw/bt/l2cap.o
CC hw/bt/sdp.o
CC hw/bt/hci.o
CC hw/bt/hid.o
CC hw/bt/hci-csr.o
CC hw/char/ipoctal232.o
CC hw/char/parallel.o
CC hw/char/pl011.o
CC hw/char/serial.o
CC hw/char/serial-isa.o
CC hw/char/serial-pci.o
CC hw/char/virtio-console.o
CC hw/char/cadence_uart.o
CC hw/char/debugcon.o
CC hw/char/imx_serial.o
CC hw/core/qdev.o
CC hw/core/qdev-properties.o
CC hw/core/bus.o
CC hw/core/fw-path-provider.o
CC hw/core/irq.o
CC hw/core/hotplug.o
CC hw/core/ptimer.o
CC hw/core/machine.o
CC hw/core/sysbus.o
CC hw/core/null-machine.o
CC hw/core/loader.o
CC hw/core/qdev-properties-system.o
CC hw/core/register.o
CC hw/core/or-irq.o
CC hw/core/platform-bus.o
CC hw/core/security-policy.o
CC hw/display/ads7846.o
CC hw/display/cirrus_vga.o
CC hw/display/pl110.o
CC hw/display/ssd0303.o
CC hw/display/ssd0323.o
CC hw/display/vga-pci.o
CC hw/display/vmware_vga.o
CC hw/display/vga-isa.o
CC hw/display/exynos4210_fimd.o
CC hw/display/blizzard.o
CC hw/display/framebuffer.o
CC hw/display/tc6393xb.o
CC hw/dma/pl080.o
CC hw/dma/pl330.o
CC hw/dma/i8257.o
CC hw/dma/xlnx-zynq-devcfg.o
CC hw/gpio/max7310.o
CC hw/gpio/pl061.o
CC hw/gpio/zaurus.o
CC hw/gpio/gpio_key.o
CC hw/i2c/core.o
CC hw/i2c/smbus.o
CC hw/i2c/smbus_eeprom.o
CC hw/i2c/i2c-ddc.o
CC hw/i2c/versatile_i2c.o
CC hw/i2c/smbus_ich9.o
CC hw/i2c/pm_smbus.o
CC hw/i2c/bitbang_i2c.o
CC hw/i2c/exynos4210_i2c.o
CC hw/i2c/imx_i2c.o
CC hw/i2c/aspeed_i2c.o
CC hw/ide/core.o
CC hw/ide/atapi.o
CC hw/ide/qdev.o
CC hw/ide/pci.o
CC hw/ide/isa.o
CC hw/ide/piix.o
CC hw/ide/microdrive.o
CC hw/ide/ahci.o
CC hw/ide/ich.o
CC hw/input/hid.o
CC hw/input/lm832x.o
CC hw/input/pckbd.o
CC hw/input/pl050.o
CC hw/input/ps2.o
CC hw/input/stellaris_input.o
CC hw/input/tsc2005.o
CC hw/input/vmmouse.o
CC hw/input/virtio-input.o
CC hw/input/virtio-input-hid.o
CC hw/input/virtio-input-host.o
CC hw/intc/i8259_common.o
CC hw/intc/i8259.o
CC hw/intc/pl190.o
CC hw/intc/imx_avic.o
CC hw/intc/realview_gic.o
CC hw/intc/ioapic_common.o
CC hw/intc/arm_gic_common.o
CC hw/intc/arm_gic.o
CC hw/intc/arm_gicv2m.o
CC hw/intc/arm_gicv3_common.o
CC hw/intc/arm_gicv3.o
CC hw/intc/arm_gicv3_dist.o
CC hw/intc/arm_gicv3_redist.o
CC hw/intc/arm_gicv3_its_common.o
CC hw/intc/intc.o
CC hw/ipack/ipack.o
CC hw/ipack/tpci200.o
CC hw/ipmi/ipmi.o
CC hw/ipmi/ipmi_bmc_sim.o
CC hw/ipmi/ipmi_bmc_extern.o
CC hw/ipmi/isa_ipmi_kcs.o
CC hw/ipmi/isa_ipmi_bt.o
CC hw/isa/isa-bus.o
CC hw/isa/apm.o
CC hw/mem/pc-dimm.o
CC hw/mem/nvdimm.o
CC hw/misc/applesmc.o
CC hw/misc/max111x.o
CC hw/misc/tmp105.o
CC hw/misc/debugexit.o
CC hw/misc/sga.o
CC hw/misc/pc-testdev.o
CC hw/misc/pci-testdev.o
CC hw/misc/arm_l2x0.o
CC hw/misc/arm_integrator_debug.o
CC hw/misc/a9scu.o
CC hw/misc/arm11scu.o
CC hw/net/ne2000.o
CC hw/net/eepro100.o
CC hw/net/pcnet-pci.o
CC hw/net/pcnet.o
CC hw/net/e1000.o
CC hw/net/e1000x_common.o
CC hw/net/net_tx_pkt.o
CC hw/net/net_rx_pkt.o
CC hw/net/e1000e.o
CC hw/net/e1000e_core.o
CC hw/net/rtl8139.o
CC hw/net/vmxnet3.o
CC hw/net/smc91c111.o
CC hw/net/lan9118.o
CC hw/net/ne2000-isa.o
CC hw/net/xgmac.o
CC hw/net/allwinner_emac.o
CC hw/net/imx_fec.o
CC hw/net/cadence_gem.o
CC hw/net/stellaris_enet.o
CC hw/net/rocker/rocker.o
CC hw/net/rocker/rocker_fp.o
CC hw/net/rocker/rocker_desc.o
CC hw/net/rocker/rocker_world.o
CC hw/net/rocker/rocker_of_dpa.o
CC hw/nvram/eeprom93xx.o
CC hw/nvram/fw_cfg.o
CC hw/nvram/chrp_nvram.o
CC hw/pci-bridge/pci_bridge_dev.o
CC hw/pci-bridge/pci_expander_bridge.o
CC hw/pci-bridge/xio3130_upstream.o
CC hw/pci-bridge/xio3130_downstream.o
CC hw/pci-bridge/ioh3420.o
CC hw/pci-bridge/i82801b11.o
CC hw/pci-host/pam.o
CC hw/pci-host/versatile.o
CC hw/pci-host/piix.o
CC hw/pci-host/q35.o
CC hw/pci-host/gpex.o
CC hw/pci/pci.o
CC hw/pci/pci_bridge.o
CC hw/pci/msix.o
CC hw/pci/msi.o
CC hw/pci/shpc.o
CC hw/pci/slotid_cap.o
CC hw/pci/pci_host.o
CC hw/pci/pcie_host.o
CC hw/pci/pcie.o
CC hw/pci/pcie_aer.o
CC hw/pci/pcie_port.o
CC hw/pci/pci-stub.o
CC hw/pcmcia/pcmcia.o
CC hw/scsi/scsi-disk.o
CC hw/scsi/scsi-generic.o
CC hw/scsi/scsi-bus.o
CC hw/scsi/lsi53c895a.o
/tmp/qemu-test/src/hw/nvram/fw_cfg.c: In function ‘fw_cfg_dma_transfer’:
/tmp/qemu-test/src/hw/nvram/fw_cfg.c:329: warning: ‘read’ may be used uninitialized in this function
CC hw/scsi/mptsas.o
CC hw/scsi/mptconfig.o
CC hw/scsi/mptendian.o
CC hw/scsi/megasas.o
CC hw/scsi/vmw_pvscsi.o
CC hw/scsi/esp.o
CC hw/scsi/esp-pci.o
CC hw/sd/pl181.o
CC hw/sd/ssi-sd.o
CC hw/sd/sd.o
CC hw/sd/core.o
CC hw/sd/sdhci.o
CC hw/smbios/smbios.o
CC hw/smbios/smbios_type_38.o
CC hw/ssi/pl022.o
CC hw/ssi/ssi.o
CC hw/ssi/xilinx_spips.o
CC hw/ssi/aspeed_smc.o
CC hw/ssi/stm32f2xx_spi.o
CC hw/timer/arm_timer.o
CC hw/timer/arm_mptimer.o
CC hw/timer/a9gtimer.o
CC hw/timer/cadence_ttc.o
CC hw/timer/ds1338.o
CC hw/timer/hpet.o
CC hw/timer/i8254_common.o
CC hw/timer/i8254.o
CC hw/timer/pl031.o
CC hw/timer/twl92230.o
CC hw/timer/imx_epit.o
CC hw/timer/imx_gpt.o
CC hw/timer/stm32f2xx_timer.o
CC hw/timer/aspeed_timer.o
CC hw/tpm/tpm_tis.o
CC hw/tpm/tpm_passthrough.o
CC hw/tpm/tpm_util.o
CC hw/usb/core.o
CC hw/usb/combined-packet.o
CC hw/usb/bus.o
CC hw/usb/libhw.o
CC hw/usb/desc.o
CC hw/usb/desc-msos.o
CC hw/usb/hcd-uhci.o
CC hw/usb/hcd-ohci.o
CC hw/usb/hcd-ehci.o
CC hw/usb/hcd-musb.o
CC hw/usb/hcd-ehci-pci.o
CC hw/usb/hcd-ehci-sysbus.o
CC hw/usb/hcd-xhci.o
CC hw/usb/dev-hub.o
CC hw/usb/dev-hid.o
CC hw/usb/dev-wacom.o
CC hw/usb/dev-storage.o
CC hw/usb/dev-uas.o
CC hw/usb/dev-audio.o
CC hw/usb/dev-serial.o
CC hw/usb/dev-network.o
CC hw/usb/dev-bluetooth.o
CC hw/usb/dev-smartcard-reader.o
CC hw/usb/dev-mtp.o
CC hw/usb/host-stub.o
CC hw/virtio/virtio-rng.o
CC hw/virtio/virtio-pci.o
CC hw/virtio/virtio-bus.o
CC hw/virtio/virtio-mmio.o
CC hw/watchdog/watchdog.o
CC hw/watchdog/wdt_i6300esb.o
CC hw/watchdog/wdt_ib700.o
CC migration/migration.o
CC migration/socket.o
CC migration/fd.o
CC migration/exec.o
CC migration/tls.o
CC migration/colo-comm.o
CC migration/colo.o
CC migration/colo-failover.o
CC migration/vmstate.o
CC migration/qemu-file.o
CC migration/qemu-file-channel.o
CC migration/xbzrle.o
CC migration/postcopy-ram.o
CC migration/qjson.o
CC migration/block.o
CC net/net.o
CC net/queue.o
CC net/checksum.o
CC net/util.o
CC net/hub.o
CC net/socket.o
CC net/dump.o
CC net/eth.o
CC net/l2tpv3.o
CC net/tap.o
CC net/vhost-user.o
CC net/tap-linux.o
CC net/slirp.o
CC net/filter.o
CC net/filter-buffer.o
CC net/filter-mirror.o
CC net/colo-compare.o
CC net/colo.o
CC net/filter-rewriter.o
CC qom/cpu.o
CC replay/replay.o
CC replay/replay-internal.o
CC replay/replay-events.o
CC replay/replay-time.o
CC replay/replay-input.o
CC replay/replay-char.o
CC replay/replay-snapshot.o
CC slirp/cksum.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
CC slirp/if.o
CC slirp/ip_icmp.o
CC slirp/ip6_icmp.o
CC slirp/ip6_input.o
CC slirp/ip_input.o
CC slirp/ip6_output.o
CC slirp/ip_output.o
CC slirp/slirp.o
CC slirp/dnssearch.o
CC slirp/dhcpv6.o
CC slirp/mbuf.o
CC slirp/misc.o
CC slirp/sbuf.o
CC slirp/socket.o
CC slirp/tcp_input.o
CC slirp/tcp_output.o
CC slirp/tcp_subr.o
CC slirp/tcp_timer.o
CC slirp/udp.o
CC slirp/udp6.o
CC slirp/bootp.o
CC slirp/tftp.o
CC slirp/arp_table.o
CC slirp/ndp_table.o
CC ui/keymaps.o
CC ui/console.o
CC ui/cursor.o
CC ui/qemu-pixman.o
CC ui/input.o
CC ui/input-keymap.o
CC ui/input-legacy.o
CC ui/input-linux.o
CC ui/sdl.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
CC ui/sdl_zoom.o
CC ui/x_keymap.o
CC ui/vnc.o
CC ui/vnc-enc-zlib.o
CC ui/vnc-enc-hextile.o
CC ui/vnc-enc-tight.o
CC ui/vnc-palette.o
CC ui/vnc-enc-zrle.o
CC ui/vnc-auth-vencrypt.o
CC ui/vnc-ws.o
CC ui/vnc-jobs.o
LINK tests/qemu-iotests/socket_scm_helper
CC qga/commands.o
AS optionrom/multiboot.o
AS optionrom/linuxboot.o
CC optionrom/linuxboot_dma.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
AS optionrom/kvmvapic.o
BUILD optionrom/multiboot.img
BUILD optionrom/linuxboot.img
BUILD optionrom/linuxboot_dma.img
BUILD optionrom/kvmvapic.img
BUILD optionrom/multiboot.raw
CC qga/guest-agent-command-state.o
BUILD optionrom/linuxboot.raw
BUILD optionrom/linuxboot_dma.raw
BUILD optionrom/kvmvapic.raw
CC qga/main.o
SIGN optionrom/multiboot.bin
SIGN optionrom/linuxboot.bin
CC qga/commands-posix.o
SIGN optionrom/linuxboot_dma.bin
SIGN optionrom/kvmvapic.bin
CC qga/channel-posix.o
CC qga/qapi-generated/qga-qapi-types.o
CC qga/qapi-generated/qga-qapi-visit.o
CC qga/qapi-generated/qga-qmp-marshal.o
CC qmp-introspect.o
CC qapi-types.o
CC qapi-visit.o
CC qapi-event.o
AR libqemustub.a
CC qemu-img.o
CC qmp-marshal.o
CC trace/generated-tracers.o
AR libqemuutil.a
LINK qemu-ga
LINK ivshmem-client
LINK ivshmem-server
LINK qemu-nbd
LINK qemu-img
LINK qemu-io
LINK qemu-bridge-helper
GEN aarch64-softmmu/hmp-commands.h
GEN aarch64-softmmu/hmp-commands-info.h
GEN aarch64-softmmu/config-target.h
GEN x86_64-softmmu/hmp-commands-info.h
GEN x86_64-softmmu/hmp-commands.h
GEN x86_64-softmmu/config-target.h
CC aarch64-softmmu/translate-common.o
CC aarch64-softmmu/exec.o
CC aarch64-softmmu/translate-all.o
CC aarch64-softmmu/tcg/tcg.o
CC aarch64-softmmu/cpu-exec.o
CC aarch64-softmmu/cpu-exec-common.o
CC aarch64-softmmu/tcg/tcg-op.o
CC aarch64-softmmu/tcg/optimize.o
CC aarch64-softmmu/tcg/tcg-common.o
CC aarch64-softmmu/fpu/softfloat.o
CC aarch64-softmmu/disas.o
CC aarch64-softmmu/tcg-runtime.o
GEN aarch64-softmmu/gdbstub-xml.c
CC aarch64-softmmu/kvm-stub.o
CC aarch64-softmmu/arch_init.o
CC aarch64-softmmu/cpus.o
CC x86_64-softmmu/exec.o
CC x86_64-softmmu/translate-all.o
CC aarch64-softmmu/monitor.o
CC aarch64-softmmu/gdbstub.o
CC aarch64-softmmu/balloon.o
CC aarch64-softmmu/ioport.o
CC x86_64-softmmu/cpu-exec.o
CC x86_64-softmmu/translate-common.o
CC x86_64-softmmu/cpu-exec-common.o
CC x86_64-softmmu/tcg/tcg.o
CC x86_64-softmmu/tcg/tcg-op.o
CC aarch64-softmmu/numa.o
CC x86_64-softmmu/tcg/optimize.o
CC aarch64-softmmu/qtest.o
CC x86_64-softmmu/tcg/tcg-common.o
CC x86_64-softmmu/fpu/softfloat.o
CC aarch64-softmmu/bootdevice.o
CC aarch64-softmmu/memory.o
CC x86_64-softmmu/disas.o
CC x86_64-softmmu/tcg-runtime.o
CC x86_64-softmmu/arch_init.o
CC aarch64-softmmu/cputlb.o
CC aarch64-softmmu/memory_mapping.o
CC aarch64-softmmu/dump.o
CC x86_64-softmmu/cpus.o
CC aarch64-softmmu/migration/ram.o
CC aarch64-softmmu/migration/savevm.o
CC aarch64-softmmu/xen-common-stub.o
CC aarch64-softmmu/xen-hvm-stub.o
CC aarch64-softmmu/hw/adc/stm32f2xx_adc.o
CC aarch64-softmmu/hw/block/virtio-blk.o
CC aarch64-softmmu/hw/block/dataplane/virtio-blk.o
CC aarch64-softmmu/hw/char/exynos4210_uart.o
CC x86_64-softmmu/monitor.o
CC x86_64-softmmu/gdbstub.o
CC x86_64-softmmu/balloon.o
CC x86_64-softmmu/ioport.o
CC x86_64-softmmu/numa.o
CC x86_64-softmmu/qtest.o
CC x86_64-softmmu/bootdevice.o
CC aarch64-softmmu/hw/char/omap_uart.o
CC x86_64-softmmu/kvm-all.o
CC aarch64-softmmu/hw/char/digic-uart.o
CC x86_64-softmmu/sev.o
CC aarch64-softmmu/hw/char/stm32f2xx_usart.o
CC x86_64-softmmu/memory.o
CC aarch64-softmmu/hw/char/bcm2835_aux.o
CC x86_64-softmmu/cputlb.o
CC x86_64-softmmu/memory_mapping.o
CC x86_64-softmmu/dump.o
CC x86_64-softmmu/migration/ram.o
CC x86_64-softmmu/migration/savevm.o
CC x86_64-softmmu/xen-common-stub.o
CC x86_64-softmmu/xen-hvm-stub.o
CC x86_64-softmmu/hw/acpi/nvdimm.o
CC aarch64-softmmu/hw/char/virtio-serial-bus.o
CC aarch64-softmmu/hw/core/nmi.o
CC aarch64-softmmu/hw/core/generic-loader.o
CC x86_64-softmmu/hw/block/virtio-blk.o
CC x86_64-softmmu/hw/block/dataplane/virtio-blk.o
/tmp/qemu-test/src/sev.c: In function ‘sev_ioctl’:
/tmp/qemu-test/src/sev.c:219: error: storage size of ‘input’ isn’t known
/tmp/qemu-test/src/sev.c:223: error: ‘KVM_SEV_ISSUE_CMD’ undeclared (first use in this function)
/tmp/qemu-test/src/sev.c:223: error: (Each undeclared identifier is reported only once
/tmp/qemu-test/src/sev.c:223: error: for each function it appears in.)
/tmp/qemu-test/src/sev.c:219: warning: unused variable ‘input’
/tmp/qemu-test/src/sev.c: In function ‘sev_launch_start’:
/tmp/qemu-test/src/sev.c:255: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:261: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:262: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:263: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:264: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:265: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:265: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:266: error: ‘KVM_SEV_LAUNCH_START’ undeclared (first use in this function)
/tmp/qemu-test/src/sev.c: In function ‘sev_launch_finish’:
/tmp/qemu-test/src/sev.c:286: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:291: error: ‘KVM_SEV_LAUNCH_FINISH’ undeclared (first use in this function)
/tmp/qemu-test/src/sev.c:297: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:298: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c: In function ‘sev_launch_update’:
/tmp/qemu-test/src/sev.c:313: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:318: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:319: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:320: error: ‘KVM_SEV_LAUNCH_UPDATE’ undeclared (first use in this function)
/tmp/qemu-test/src/sev.c: In function ‘sev_debug_decrypt’:
/tmp/qemu-test/src/sev.c:337: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:342: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:343: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:344: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:346: error: ‘KVM_SEV_DBG_DECRYPT’ undeclared (first use in this function)
/tmp/qemu-test/src/sev.c: In function ‘sev_debug_encrypt’:
/tmp/qemu-test/src/sev.c:359: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:364: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:365: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:366: error: dereferencing pointer to incomplete type
/tmp/qemu-test/src/sev.c:368: error: ‘KVM_SEV_DBG_ENCRYPT’ undeclared (first use in this function)
make[1]: *** [sev.o] Error 1
make[1]: *** Waiting for unfinished jobs....
CC aarch64-softmmu/hw/cpu/arm11mpcore.o
CC aarch64-softmmu/hw/cpu/realview_mpcore.o
CC aarch64-softmmu/hw/cpu/a9mpcore.o
CC aarch64-softmmu/hw/cpu/a15mpcore.o
CC aarch64-softmmu/hw/cpu/core.o
CC aarch64-softmmu/hw/display/omap_dss.o
CC aarch64-softmmu/hw/display/omap_lcdc.o
CC aarch64-softmmu/hw/display/pxa2xx_lcd.o
CC aarch64-softmmu/hw/display/bcm2835_fb.o
CC aarch64-softmmu/hw/display/vga.o
CC aarch64-softmmu/hw/display/virtio-gpu.o
CC aarch64-softmmu/hw/display/virtio-gpu-3d.o
CC aarch64-softmmu/hw/display/virtio-gpu-pci.o
CC aarch64-softmmu/hw/display/dpcd.o
CC aarch64-softmmu/hw/display/xlnx_dp.o
CC aarch64-softmmu/hw/dma/xlnx_dpdma.o
CC aarch64-softmmu/hw/dma/omap_dma.o
CC aarch64-softmmu/hw/dma/soc_dma.o
CC aarch64-softmmu/hw/dma/pxa2xx_dma.o
CC aarch64-softmmu/hw/dma/bcm2835_dma.o
CC aarch64-softmmu/hw/gpio/omap_gpio.o
CC aarch64-softmmu/hw/gpio/imx_gpio.o
CC aarch64-softmmu/hw/i2c/omap_i2c.o
CC aarch64-softmmu/hw/input/pxa2xx_keypad.o
CC aarch64-softmmu/hw/input/tsc210x.o
CC aarch64-softmmu/hw/intc/armv7m_nvic.o
CC aarch64-softmmu/hw/intc/exynos4210_gic.o
CC aarch64-softmmu/hw/intc/exynos4210_combiner.o
CC aarch64-softmmu/hw/intc/omap_intc.o
CC aarch64-softmmu/hw/intc/bcm2835_ic.o
CC aarch64-softmmu/hw/intc/bcm2836_control.o
make: *** [subdir-x86_64-softmmu] Error 2
make: *** Waiting for unfinished jobs....
CC aarch64-softmmu/hw/intc/allwinner-a10-pic.o
CC aarch64-softmmu/hw/intc/aspeed_vic.o
CC aarch64-softmmu/hw/intc/arm_gicv3_cpuif.o
CC aarch64-softmmu/hw/misc/ivshmem.o
CC aarch64-softmmu/hw/misc/arm_sysctl.o
CC aarch64-softmmu/hw/misc/cbus.o
CC aarch64-softmmu/hw/misc/exynos4210_pmu.o
CC aarch64-softmmu/hw/misc/imx_ccm.o
CC aarch64-softmmu/hw/misc/imx31_ccm.o
CC aarch64-softmmu/hw/misc/imx25_ccm.o
CC aarch64-softmmu/hw/misc/imx6_ccm.o
CC aarch64-softmmu/hw/misc/imx6_src.o
CC aarch64-softmmu/hw/misc/mst_fpga.o
CC aarch64-softmmu/hw/misc/omap_clk.o
CC aarch64-softmmu/hw/misc/omap_gpmc.o
CC aarch64-softmmu/hw/misc/omap_l4.o
CC aarch64-softmmu/hw/misc/omap_sdrc.o
CC aarch64-softmmu/hw/misc/omap_tap.o
CC aarch64-softmmu/hw/misc/bcm2835_mbox.o
CC aarch64-softmmu/hw/misc/bcm2835_property.o
CC aarch64-softmmu/hw/misc/zynq_slcr.o
CC aarch64-softmmu/hw/misc/zynq-xadc.o
CC aarch64-softmmu/hw/misc/stm32f2xx_syscfg.o
CC aarch64-softmmu/hw/misc/auxbus.o
CC aarch64-softmmu/hw/misc/edu.o
CC aarch64-softmmu/hw/misc/aspeed_scu.o
CC aarch64-softmmu/hw/misc/aspeed_sdmc.o
CC aarch64-softmmu/hw/net/virtio-net.o
CC aarch64-softmmu/hw/net/vhost_net.o
CC aarch64-softmmu/hw/pcmcia/pxa2xx.o
CC aarch64-softmmu/hw/scsi/virtio-scsi.o
CC aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
CC aarch64-softmmu/hw/scsi/vhost-scsi.o
CC aarch64-softmmu/hw/sd/omap_mmc.o
CC aarch64-softmmu/hw/sd/pxa2xx_mmci.o
CC aarch64-softmmu/hw/ssi/omap_spi.o
CC aarch64-softmmu/hw/ssi/imx_spi.o
CC aarch64-softmmu/hw/timer/exynos4210_mct.o
CC aarch64-softmmu/hw/timer/exynos4210_pwm.o
CC aarch64-softmmu/hw/timer/exynos4210_rtc.o
CC aarch64-softmmu/hw/timer/omap_gptimer.o
CC aarch64-softmmu/hw/timer/omap_synctimer.o
CC aarch64-softmmu/hw/timer/digic-timer.o
CC aarch64-softmmu/hw/timer/pxa2xx_timer.o
CC aarch64-softmmu/hw/timer/allwinner-a10-pit.o
CC aarch64-softmmu/hw/usb/tusb6010.o
CC aarch64-softmmu/hw/vfio/pci.o
CC aarch64-softmmu/hw/vfio/common.o
CC aarch64-softmmu/hw/vfio/pci-quirks.o
CC aarch64-softmmu/hw/vfio/platform.o
CC aarch64-softmmu/hw/vfio/calxeda-xgmac.o
CC aarch64-softmmu/hw/vfio/amd-xgbe.o
CC aarch64-softmmu/hw/vfio/spapr.o
CC aarch64-softmmu/hw/virtio/virtio.o
CC aarch64-softmmu/hw/virtio/virtio-balloon.o
CC aarch64-softmmu/hw/virtio/vhost.o
CC aarch64-softmmu/hw/virtio/vhost-backend.o
CC aarch64-softmmu/hw/virtio/vhost-user.o
CC aarch64-softmmu/hw/virtio/vhost-vsock.o
CC aarch64-softmmu/hw/arm/boot.o
CC aarch64-softmmu/hw/arm/collie.o
CC aarch64-softmmu/hw/arm/exynos4_boards.o
CC aarch64-softmmu/hw/arm/gumstix.o
CC aarch64-softmmu/hw/arm/highbank.o
CC aarch64-softmmu/hw/arm/digic_boards.o
CC aarch64-softmmu/hw/arm/integratorcp.o
CC aarch64-softmmu/hw/arm/mainstone.o
CC aarch64-softmmu/hw/arm/musicpal.o
CC aarch64-softmmu/hw/arm/nseries.o
CC aarch64-softmmu/hw/arm/omap_sx1.o
CC aarch64-softmmu/hw/arm/palm.o
CC aarch64-softmmu/hw/arm/realview.o
CC aarch64-softmmu/hw/arm/spitz.o
CC aarch64-softmmu/hw/arm/stellaris.o
CC aarch64-softmmu/hw/arm/tosa.o
CC aarch64-softmmu/hw/arm/versatilepb.o
CC aarch64-softmmu/hw/arm/vexpress.o
CC aarch64-softmmu/hw/arm/virt.o
CC aarch64-softmmu/hw/arm/xilinx_zynq.o
CC aarch64-softmmu/hw/arm/z2.o
CC aarch64-softmmu/hw/arm/virt-acpi-build.o
CC aarch64-softmmu/hw/arm/netduino2.o
CC aarch64-softmmu/hw/arm/sysbus-fdt.o
CC aarch64-softmmu/hw/arm/armv7m.o
CC aarch64-softmmu/hw/arm/exynos4210.o
CC aarch64-softmmu/hw/arm/pxa2xx.o
CC aarch64-softmmu/hw/arm/pxa2xx_gpio.o
CC aarch64-softmmu/hw/arm/pxa2xx_pic.o
CC aarch64-softmmu/hw/arm/digic.o
CC aarch64-softmmu/hw/arm/omap1.o
CC aarch64-softmmu/hw/arm/omap2.o
CC aarch64-softmmu/hw/arm/strongarm.o
CC aarch64-softmmu/hw/arm/allwinner-a10.o
CC aarch64-softmmu/hw/arm/cubieboard.o
CC aarch64-softmmu/hw/arm/bcm2835_peripherals.o
CC aarch64-softmmu/hw/arm/raspi.o
CC aarch64-softmmu/hw/arm/bcm2836.o
CC aarch64-softmmu/hw/arm/stm32f205_soc.o
CC aarch64-softmmu/hw/arm/xlnx-zynqmp.o
CC aarch64-softmmu/hw/arm/xlnx-ep108.o
CC aarch64-softmmu/hw/arm/fsl-imx25.o
CC aarch64-softmmu/hw/arm/imx25_pdk.o
CC aarch64-softmmu/hw/arm/fsl-imx31.o
CC aarch64-softmmu/hw/arm/kzm.o
CC aarch64-softmmu/hw/arm/fsl-imx6.o
CC aarch64-softmmu/hw/arm/sabrelite.o
CC aarch64-softmmu/hw/arm/aspeed_soc.o
CC aarch64-softmmu/hw/arm/aspeed.o
CC aarch64-softmmu/target-arm/arm-semi.o
CC aarch64-softmmu/target-arm/machine.o
CC aarch64-softmmu/target-arm/psci.o
CC aarch64-softmmu/target-arm/arch_dump.o
CC aarch64-softmmu/target-arm/monitor.o
CC aarch64-softmmu/target-arm/kvm-stub.o
CC aarch64-softmmu/target-arm/translate.o
CC aarch64-softmmu/target-arm/op_helper.o
CC aarch64-softmmu/target-arm/helper.o
CC aarch64-softmmu/target-arm/cpu.o
CC aarch64-softmmu/target-arm/neon_helper.o
CC aarch64-softmmu/target-arm/iwmmxt_helper.o
CC aarch64-softmmu/target-arm/gdbstub.o
CC aarch64-softmmu/target-arm/cpu64.o
CC aarch64-softmmu/target-arm/translate-a64.o
CC aarch64-softmmu/target-arm/helper-a64.o
CC aarch64-softmmu/target-arm/gdbstub64.o
CC aarch64-softmmu/target-arm/arm-powerctl.o
CC aarch64-softmmu/target-arm/crypto_helper.o
GEN trace/generated-helpers.c
CC aarch64-softmmu/trace/control-target.o
CC aarch64-softmmu/gdbstub-xml.o
CC aarch64-softmmu/trace/generated-helpers.o
/tmp/qemu-test/src/target-arm/translate-a64.c: In function ‘handle_shri_with_rndacc’:
/tmp/qemu-test/src/target-arm/translate-a64.c:6395: warning: ‘tcg_src_hi’ may be used uninitialized in this function
/tmp/qemu-test/src/target-arm/translate-a64.c: In function ‘disas_simd_scalar_two_reg_misc’:
/tmp/qemu-test/src/target-arm/translate-a64.c:8122: warning: ‘rmode’ may be used uninitialized in this function
LINK aarch64-softmmu/qemu-system-aarch64
migration/savevm.o: In function `load_vmstate':
/tmp/qemu-test/src/migration/savevm.c:2185: undefined reference to `sev_enabled'
migration/savevm.o: In function `hmp_savevm':
/tmp/qemu-test/src/migration/savevm.c:2031: undefined reference to `sev_enabled'
../qmp.o: In function `qmp_query_kvm':
/tmp/qemu-test/src/qmp.c:71: undefined reference to `kvm_memory_encryption_enabled'
../hw/core/loader.o: In function `rom_reset':
/tmp/qemu-test/src/hw/core/loader.c:1055: undefined reference to `kvm_memory_encryption_enabled'
/tmp/qemu-test/src/hw/core/loader.c:1092: undefined reference to `kvm_memory_encryption_enabled'
/tmp/qemu-test/src/hw/core/loader.c:1093: undefined reference to `kvm_memory_encryption_finish'
/tmp/qemu-test/src/hw/core/loader.c:1056: undefined reference to `kvm_memory_encryption_start'
../migration/migration.o: In function `qmp_migrate':
/tmp/qemu-test/src/migration/migration.c:1155: undefined reference to `sev_enabled'
collect2: ld returned 1 exit status
make[1]: *** [qemu-system-aarch64] Error 1
make: *** [subdir-aarch64-softmmu] Error 2
make[1]: *** [docker-run] Error 2
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-fw8uaplr/src'
make: *** [docker-run-test-***@centos6] Error 2
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please sen
Loading...