* [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:19 ` Eric Blake
2018-02-07 16:51 ` Paolo Bonzini
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 03/26] exec: add debug version of physical memory read and write API Brijesh Singh
` (22 subsequent siblings)
23 siblings, 2 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
Currently, the guest memory access for the debug purpose is performed
using the memcpy(). Lets extend the 'struct MemoryRegion' to include
ram_debug_ops callbacks. The ram_debug_ops can be used to override
memcpy() with something else.
The feature can be used by encrypted guest -- which can register
callbacks to override memcpy() with memory encryption/decryption APIs.
a typical usage:
mem_read(uint8_t *dst, uint8_t *src, uint32_t len, MemTxAttrs *attrs);
mem_write(uint8_t *dst, uint8_t *src, uint32_t len, MemTxAttrs *attrs);
MemoryRegionRAMReadWriteOps ops;
ops.read = mem_read;
ops.write = mem_write;
memory_region_init_ram(mem, NULL, "memory", size, NULL);
memory_region_set_ram_debug_ops(mem, ops);
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
exec.c | 66 ++++++++++++++++++++++++++++++++++++++-------------
include/exec/memory.h | 28 ++++++++++++++++++++++
2 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/exec.c b/exec.c
index 629a5083851d..1919052b7385 100644
--- a/exec.c
+++ b/exec.c
@@ -3050,7 +3050,11 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
} else {
/* RAM case */
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
- memcpy(ptr, buf, l);
+ if (attrs.debug && mr->ram_debug_ops) {
+ mr->ram_debug_ops->write(ptr, buf, l, attrs);
+ } else {
+ memcpy(ptr, buf, l);
+ }
invalidate_and_set_dirty(mr, addr1, l);
}
@@ -3148,7 +3152,11 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
} else {
/* RAM case */
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
- memcpy(buf, ptr, l);
+ if (attrs.debug && mr->ram_debug_ops) {
+ mr->ram_debug_ops->read(buf, ptr, l, attrs);
+ } else {
+ memcpy(buf, ptr, l);
+ }
}
if (release_lock) {
@@ -3218,11 +3226,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_internal(AddressSpace *as,
+ hwaddr addr, uint8_t *buf, int len, MemTxAttrs attrs,
+ enum write_rom_type type)
{
hwaddr l;
uint8_t *ptr;
@@ -3237,12 +3247,33 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
if (!(memory_region_is_ram(mr) ||
memory_region_is_romd(mr))) {
l = memory_access_size(mr, l, addr1);
+ /* Pass MMIO down to address address_space_rw */
+ switch (type) {
+ case READ_DATA:
+ case WRITE_DATA:
+ address_space_rw(as, addr1, attrs, buf, l,
+ type == WRITE_DATA);
+ break;
+ case FLUSH_CACHE:
+ break;
+ }
} else {
/* ROM/RAM case */
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (type) {
+ case READ_DATA:
+ if (mr->ram_debug_ops) {
+ mr->ram_debug_ops->read(buf, ptr, l, attrs);
+ } else {
+ memcpy(buf, ptr, l);
+ }
+ break;
case WRITE_DATA:
- memcpy(ptr, buf, l);
+ if (mr->ram_debug_ops) {
+ mr->ram_debug_ops->write(ptr, buf, l, attrs);
+ } else {
+ memcpy(ptr, buf, l);
+ }
invalidate_and_set_dirty(mr, addr1, l);
break;
case FLUSH_CACHE:
@@ -3261,7 +3292,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_internal(as, addr, (uint8_t *)buf, len,
+ MEMTXATTRS_UNSPECIFIED, WRITE_DATA);
}
void cpu_flush_icache_range(hwaddr start, int len)
@@ -3276,8 +3308,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_internal(&address_space_memory,
+ start, NULL, len,
+ MEMTXATTRS_UNSPECIFIED,
+ FLUSH_CACHE);
}
typedef struct {
@@ -3583,6 +3617,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
int l;
hwaddr phys_addr;
target_ulong page;
+ int type = is_write ? WRITE_DATA : READ_DATA;
cpu_synchronize_state(cpu);
while (len > 0) {
@@ -3592,6 +3627,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 attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
/* if no physical page mapped, return an error */
if (phys_addr == -1)
return -1;
@@ -3599,14 +3638,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_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 07c5d6d59796..43445cb9e45d 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -215,6 +215,18 @@ typedef struct IOMMUMemoryRegionClass {
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
+/* Memory Region RAM debug callback */
+typedef struct MemoryRegionRAMReadWriteOps MemoryRegionRAMReadWriteOps;
+
+struct MemoryRegionRAMReadWriteOps {
+ /* Write data into guest memory */
+ int (*write) (uint8_t *dest, const uint8_t *src,
+ uint32_t len, MemTxAttrs attrs);
+ /* Read data from guest memory */
+ int (*read) (uint8_t *dest, const uint8_t *src,
+ uint32_t len, MemTxAttrs attrs);
+};
+
struct MemoryRegion {
Object parent_obj;
@@ -254,6 +266,7 @@ struct MemoryRegion {
const char *name;
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
+ const MemoryRegionRAMReadWriteOps *ram_debug_ops;
};
struct IOMMUMemoryRegion {
@@ -623,6 +636,21 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
uint64_t size,
Error **errp);
+/**
+ * memory_region_set_ram_debug_ops: Set debug access ops for a given memory
+ * region.
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that will be used for when accessing @target region during
+ * debug
+ */
+static inline void
+memory_region_set_ram_debug_ops(MemoryRegion *mr,
+ const MemoryRegionRAMReadWriteOps *ops)
+{
+ mr->ram_debug_ops = ops;
+}
+
/**
* memory_region_init_reservation: Initialize a memory region that reserves
* I/O space.
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support Brijesh Singh
@ 2018-02-07 16:19 ` Eric Blake
2018-02-07 16:33 ` Brijesh Singh
2018-02-07 16:51 ` Paolo Bonzini
1 sibling, 1 reply; 39+ messages in thread
From: Eric Blake @ 2018-02-07 16:19 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, kvm, Marcel Apfelbaum,
Markus Armbruster, Paolo Bonzini, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov, Richard Henderson
On 02/07/2018 10:06 AM, Brijesh Singh wrote:
> Currently, the guest memory access for the debug purpose is performed
> using the memcpy(). Lets extend the 'struct MemoryRegion' to include
> ram_debug_ops callbacks. The ram_debug_ops can be used to override
> memcpy() with something else.
[meta-comment]
Your threading is off. This email was sent with the headers:
> In-Reply-To: <20180207160638.98872-1-brijesh.singh@amd.com>
> References: <20180207160638.98872-1-brijesh.singh@amd.com>
which ties it only to patch 1/26; in turn, that message has no
In-Reply-To header at all, making it a top-level thread. Meanwhile,
your 0/26 cover letter has:
> Message-Id: <20180207160324.98614-1-brijesh.singh@amd.com>
which nothing in the rest of the series refers to, making it a separate
thread. It would be helpful if you could the threading used in your
sending environment, although I don't have any specific suggestions on
what that fix would be.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:19 ` Eric Blake
@ 2018-02-07 16:33 ` Brijesh Singh
2018-02-07 16:46 ` Eric Blake
0 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:33 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: brijesh.singh, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov,
Richard Henderson
On 2/7/18 10:19 AM, Eric Blake wrote:
> On 02/07/2018 10:06 AM, Brijesh Singh wrote:
>> Currently, the guest memory access for the debug purpose is performed
>> using the memcpy(). Lets extend the 'struct MemoryRegion' to include
>> ram_debug_ops callbacks. The ram_debug_ops can be used to override
>> memcpy() with something else.
>
> [meta-comment]
>
> Your threading is off. This email was sent with the headers:
>
> > In-Reply-To: <20180207160638.98872-1-brijesh.singh@amd.com>
> > References: <20180207160638.98872-1-brijesh.singh@amd.com>
>
> which ties it only to patch 1/26; in turn, that message has no
> In-Reply-To header at all, making it a top-level thread. Meanwhile,
> your 0/26 cover letter has:
>
>> Message-Id: <20180207160324.98614-1-brijesh.singh@amd.com>
>
> which nothing in the rest of the series refers to, making it a
> separate thread. It would be helpful if you could the threading used
> in your sending environment, although I don't have any specific
> suggestions on what that fix would be.
>
I am just looking at the my git send email script log and it seems that
after sending the cover-letter patch, exchange server timeout and my
script restarting send from patch 02/.. hence threading got messed up.
sorry about that. If its an issue then I can resend the whole series.
-Brijesh
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:33 ` Brijesh Singh
@ 2018-02-07 16:46 ` Eric Blake
0 siblings, 0 replies; 39+ messages in thread
From: Eric Blake @ 2018-02-07 16:46 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, kvm, Marcel Apfelbaum,
Markus Armbruster, Paolo Bonzini, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov, Richard Henderson
On 02/07/2018 10:33 AM, Brijesh Singh wrote:
>> [meta-comment]
>>
>> Your threading is off. This email was sent with the headers:
>>
> I am just looking at the my git send email script log and it seems that
> after sending the cover-letter patch, exchange server timeout and my
> script restarting send from patch 02/.. hence threading got messed up.
> sorry about that. If its an issue then I can resend the whole series.
No need to resend for just that issue (we can deal with a one-off, and
there may be a v8 anyways depending on what reviewers find). Does your
server allow you to pre-specify message ids, or does it always ignore
your input and generate its own message ids?
If interruptions are a common issue, you can use 'git send-email
--in-reply-to=...' to forcefully (try and) thread a second batch of sent
mail to an earlier batch that was interrupted from completion. It may
also be possible to have 'git format-patch' pre-thread all mails,
although that may already match what you were doing (pre-specifying
message ids only works if your server preserves those requested message
ids from the input instead of blindly replacing it with its own ids)
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support Brijesh Singh
2018-02-07 16:19 ` Eric Blake
@ 2018-02-07 16:51 ` Paolo Bonzini
2018-02-07 20:26 ` Brijesh Singh
1 sibling, 1 reply; 39+ messages in thread
From: Paolo Bonzini @ 2018-02-07 16:51 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov, Richard Henderson
On 07/02/2018 17:06, Brijesh Singh wrote:
> @@ -3148,7 +3152,11 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
> } else {
> /* RAM case */
> ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
> - memcpy(buf, ptr, l);
> + if (attrs.debug && mr->ram_debug_ops) {
> + mr->ram_debug_ops->read(buf, ptr, l, attrs);
> + } else {
> + memcpy(buf, ptr, l);
> + }
> }
>
> if (release_lock) {
You also need to tweak flatview_read in include/exec/memory.h (probably
by adding an "&& !attrs.debug", which leaves the mr->ram_debug_ops->read
to the slow path in exec.c).
> @@ -3218,11 +3226,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_internal(AddressSpace *as,
> + hwaddr addr, uint8_t *buf, int len, MemTxAttrs attrs,
> + enum write_rom_type type)
> {
> hwaddr l;
> uint8_t *ptr;
I wonder if READ_DATA and WRITE_DATA still need to go down to
cpu_physical_memory_rw_internal. Maybe you can just call
address_space_rw with &address_space_memory as the address space, and
"(MemTxAttrs) { .debug = 1 }" as the attributes.
Paolo
> @@ -3237,12 +3247,33 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
> if (!(memory_region_is_ram(mr) ||
> memory_region_is_romd(mr))) {
> l = memory_access_size(mr, l, addr1);
> + /* Pass MMIO down to address address_space_rw */
> + switch (type) {
> + case READ_DATA:
> + case WRITE_DATA:
> + address_space_rw(as, addr1, attrs, buf, l,
> + type == WRITE_DATA);
> + break;
> + case FLUSH_CACHE:
> + break;
> + }
> } else {
> /* ROM/RAM case */
> ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> switch (type) {
> + case READ_DATA:
> + if (mr->ram_debug_ops) {
> + mr->ram_debug_ops->read(buf, ptr, l, attrs);
> + } else {
> + memcpy(buf, ptr, l);
> + }
> + break;
> case WRITE_DATA:
> - memcpy(ptr, buf, l);
> + if (mr->ram_debug_ops) {
> + mr->ram_debug_ops->write(ptr, buf, l, attrs);
> + } else {
> + memcpy(ptr, buf, l);
> + }
> invalidate_and_set_dirty(mr, addr1, l);
> break;
> case FLUSH_CACHE:
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support
2018-02-07 16:51 ` Paolo Bonzini
@ 2018-02-07 20:26 ` Brijesh Singh
0 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 20:26 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
Cc: brijesh.singh, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost,
Eric Blake, kvm, Marcel Apfelbaum, Markus Armbruster,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov,
Richard Henderson
On 02/07/2018 10:51 AM, Paolo Bonzini wrote:
> On 07/02/2018 17:06, Brijesh Singh wrote:
>> @@ -3148,7 +3152,11 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
>> } else {
>> /* RAM case */
>> ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
>> - memcpy(buf, ptr, l);
>> + if (attrs.debug && mr->ram_debug_ops) {
>> + mr->ram_debug_ops->read(buf, ptr, l, attrs);
>> + } else {
>> + memcpy(buf, ptr, l);
>> + }
>> }
>>
>> if (release_lock) {
>
> You also need to tweak flatview_read in include/exec/memory.h (probably
> by adding an "&& !attrs.debug", which leaves the mr->ram_debug_ops->read
> to the slow path in exec.c).
>
thanks, I will make the changes in flatview_read to take slow path when
debug is enabled.
>> @@ -3218,11 +3226,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_internal(AddressSpace *as,
>> + hwaddr addr, uint8_t *buf, int len, MemTxAttrs attrs,
>> + enum write_rom_type type)
>> {
>> hwaddr l;
>> uint8_t *ptr;
>
> I wonder if READ_DATA and WRITE_DATA still need to go down to
> cpu_physical_memory_rw_internal. Maybe you can just call
> address_space_rw with &address_space_memory as the address space, and
> "(MemTxAttrs) { .debug = 1 }" as the attributes.
>
I will take a look to see if I can remove passing down the READ_DATA and
WRITE_DATA.
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 03/26] exec: add debug version of physical memory read and write API
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 04/26] monitor/i386: use debug APIs when accessing guest memory Brijesh Singh
` (21 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
Adds the following new APIs
- cpu_physical_memory_read_debug
- cpu_physical_memory_write_debug
- cpu_physical_memory_rw_debug
- ldl_phys_debug
- ldq_phys_debug
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
exec.c | 41 +++++++++++++++++++++++++++++++++++++++++
include/exec/cpu-common.h | 15 +++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/exec.c b/exec.c
index 1919052b7385..49dabdbeecbd 100644
--- a/exec.c
+++ b/exec.c
@@ -3610,6 +3610,47 @@ void address_space_cache_destroy(MemoryRegionCache *cache)
#define RCU_READ_UNLOCK() rcu_read_unlock()
#include "memory_ldst.inc.c"
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr)
+{
+ MemTxAttrs attrs;
+ int asidx = cpu_asidx_from_attrs(cpu, attrs);
+ uint32_t val;
+
+ /* set debug attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
+ cpu_physical_memory_rw_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;
+ int asidx = cpu_asidx_from_attrs(cpu, attrs);
+ uint64_t val;
+
+ /* set debug attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
+ cpu_physical_memory_rw_internal(cpu->cpu_ases[asidx].as,
+ addr, (void *) &val,
+ 8, attrs, READ_DATA);
+ return val;
+}
+
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+ int len, int is_write)
+{
+ MemTxAttrs attrs;
+
+ /* set debug attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
+ address_space_rw(&address_space_memory, addr, attrs, buf, len, is_write);
+}
+
/* virtual memory access for debug (includes writing to ROM) */
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, int is_write)
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 74341b19d26a..fa01385d4f1b 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -77,11 +77,26 @@ size_t qemu_ram_pagesize_largest(void);
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
int len, int is_write);
+void cpu_physical_memory_rw_debug(hwaddr addr, uint8_t *buf,
+ int len, int is_write);
static inline void cpu_physical_memory_read(hwaddr addr,
void *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
+static inline void cpu_physical_memory_read_debug(hwaddr addr,
+ void *buf, int len)
+{
+ cpu_physical_memory_rw_debug(addr, buf, len, 0);
+}
+static inline void cpu_physical_memory_write_debug(hwaddr addr,
+ const void *buf, int len)
+{
+ cpu_physical_memory_rw_debug(addr, (void *)buf, len, 1);
+}
+uint32_t ldl_phys_debug(CPUState *cpu, hwaddr addr);
+uint64_t ldq_phys_debug(CPUState *cpu, hwaddr addr);
+
static inline void cpu_physical_memory_write(hwaddr addr,
const void *buf, int len)
{
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 04/26] monitor/i386: use debug APIs when accessing guest memory
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 02/26] exec: add ram_debug_ops support Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 03/26] exec: add debug version of physical memory read and write API Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:53 ` Paolo Bonzini
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support Brijesh Singh
` (20 subsequent siblings)
23 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
Updates HMP commands to use the debug version of APIs when accessing the
guest memory.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
cpus.c | 2 +-
disas.c | 2 +-
monitor.c | 8 ++++---
target/i386/helper.c | 14 ++++++------
target/i386/monitor.c | 60 +++++++++++++++++++++++++++------------------------
5 files changed, 46 insertions(+), 40 deletions(-)
diff --git a/cpus.c b/cpus.c
index 2cb0af9b2249..c50e5613bed8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2147,7 +2147,7 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
l = sizeof(buf);
if (l > size)
l = size;
- cpu_physical_memory_read(addr, buf, l);
+ cpu_physical_memory_read_debug(addr, buf, l);
if (fwrite(buf, 1, l, f) != l) {
error_setg(errp, QERR_IO_ERROR);
goto exit;
diff --git a/disas.c b/disas.c
index d4ad1089efb3..fcedbf263302 100644
--- a/disas.c
+++ b/disas.c
@@ -586,7 +586,7 @@ static int
physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info)
{
- cpu_physical_memory_read(memaddr, myaddr, length);
+ cpu_physical_memory_read_debug(memaddr, myaddr, length);
return 0;
}
diff --git a/monitor.c b/monitor.c
index b9da5e20d1e7..2c082d31549d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1358,7 +1358,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
if (l > line_size)
l = line_size;
if (is_physical) {
- cpu_physical_memory_read(addr, buf, l);
+ cpu_physical_memory_read_debug(addr, buf, l);
} else {
if (cpu_memory_rw_debug(cs, addr, buf, l, 0) < 0) {
monitor_printf(mon, " Cannot access memory\n");
@@ -1564,8 +1564,10 @@ static void hmp_sum(Monitor *mon, const QDict *qdict)
sum = 0;
for(addr = start; addr < (start + size); addr++) {
- uint8_t val = address_space_ldub(&address_space_memory, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ uint8_t buf[0];
+ uint8_t val;
+ cpu_physical_memory_read_debug(addr, buf, 1);
+ val = ldub_p(buf);
/* BSD sum algorithm ('sum' Unix command) */
sum = (sum >> 1) | (sum << 15);
sum += val;
diff --git a/target/i386/helper.c b/target/i386/helper.c
index f63eb3d3f4fb..5dc9e8839bc8 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -757,7 +757,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
if (la57) {
pml5e_addr = ((env->cr[3] & ~0xfff) +
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
- pml5e = x86_ldq_phys(cs, pml5e_addr);
+ pml5e = ldq_phys_debug(cs, pml5e_addr);
if (!(pml5e & PG_PRESENT_MASK)) {
return -1;
}
@@ -767,7 +767,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
- pml4e = x86_ldq_phys(cs, pml4e_addr);
+ pml4e = ldq_phys_debug(cs, pml4e_addr);
if (!(pml4e & PG_PRESENT_MASK)) {
return -1;
}
@@ -788,14 +788,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
+ pdpe = ldq_phys_debug(cs, pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
}
pde_addr = ((pdpe & PG_ADDRESS_MASK) +
(((addr >> 21) & 0x1ff) << 3)) & a20_mask;
- pde = x86_ldq_phys(cs, pde_addr);
+ pde = ldq_phys_debug(cs, pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
return -1;
}
@@ -808,7 +808,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pte_addr = ((pde & PG_ADDRESS_MASK) +
(((addr >> 12) & 0x1ff) << 3)) & a20_mask;
page_size = 4096;
- pte = x86_ldq_phys(cs, pte_addr);
+ pte = ldq_phys_debug(cs, pte_addr);
}
if (!(pte & PG_PRESENT_MASK)) {
return -1;
@@ -818,7 +818,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
/* page directory entry */
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
- pde = x86_ldl_phys(cs, pde_addr);
+ pde = ldl_phys_debug(cs, pde_addr);
if (!(pde & PG_PRESENT_MASK))
return -1;
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +827,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
} else {
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
- pte = x86_ldl_phys(cs, pte_addr);
+ pte = ldl_phys_debug(cs, pte_addr);
if (!(pte & PG_PRESENT_MASK)) {
return -1;
}
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 75e155ffb1c4..63f7125ba885 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -66,7 +66,7 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
pgd = env->cr[3] & ~0xfff;
for(l1 = 0; l1 < 1024; l1++) {
- cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+ cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
pde = le32_to_cpu(pde);
if (pde & PG_PRESENT_MASK) {
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -74,7 +74,8 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env)
print_pte(mon, env, (l1 << 22), pde, ~((1 << 21) - 1));
} else {
for(l2 = 0; l2 < 1024; l2++) {
- cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+ cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+ &pte, 4);
pte = le32_to_cpu(pte);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, env, (l1 << 22) + (l2 << 12),
@@ -95,12 +96,12 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
pdp_addr = env->cr[3] & ~0x1f;
for (l1 = 0; l1 < 4; l1++) {
- cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+ cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
pdpe = le64_to_cpu(pdpe);
if (pdpe & PG_PRESENT_MASK) {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+ cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
pde = le64_to_cpu(pde);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
@@ -110,7 +111,8 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
} else {
pt_addr = pde & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+ cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+ &pte, 8);
pte = le64_to_cpu(pte);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, env, (l1 << 30) + (l2 << 21)
@@ -135,7 +137,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
uint64_t pdp_addr, pd_addr, pt_addr;
for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+ cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
pml4e = le64_to_cpu(pml4e);
if (!(pml4e & PG_PRESENT_MASK)) {
continue;
@@ -143,7 +145,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+ cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
pdpe = le64_to_cpu(pdpe);
if (!(pdpe & PG_PRESENT_MASK)) {
continue;
@@ -158,7 +160,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+ cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
pde = le64_to_cpu(pde);
if (!(pde & PG_PRESENT_MASK)) {
continue;
@@ -173,9 +175,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
+ cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
pte = le64_to_cpu(pte);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, env, (l0 << 48) + (l1 << 39) +
@@ -196,7 +196,7 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
for (l0 = 0; l0 < 512; l0++) {
- cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+ cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
pml5e = le64_to_cpu(pml5e);
if (pml5e & PG_PRESENT_MASK) {
tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
@@ -271,7 +271,7 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
last_prot = 0;
start = -1;
for(l1 = 0; l1 < 1024; l1++) {
- cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
+ cpu_physical_memory_read_debug(pgd + l1 * 4, &pde, 4);
pde = le32_to_cpu(pde);
end = l1 << 22;
if (pde & PG_PRESENT_MASK) {
@@ -280,7 +280,8 @@ static void mem_info_32(Monitor *mon, CPUArchState *env)
mem_print(mon, &start, &last_prot, end, prot);
} else {
for(l2 = 0; l2 < 1024; l2++) {
- cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
+ cpu_physical_memory_read_debug((pde & ~0xfff) + l2 * 4,
+ &pte, 4);
pte = le32_to_cpu(pte);
end = (l1 << 22) + (l2 << 12);
if (pte & PG_PRESENT_MASK) {
@@ -313,13 +314,13 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 4; l1++) {
- cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
+ cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
pdpe = le64_to_cpu(pdpe);
end = l1 << 30;
if (pdpe & PG_PRESENT_MASK) {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
+ cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
pde = le64_to_cpu(pde);
end = (l1 << 30) + (l2 << 21);
if (pde & PG_PRESENT_MASK) {
@@ -330,7 +331,8 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
} else {
pt_addr = pde & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
+ cpu_physical_memory_read_debug(pt_addr + l3 * 8,
+ &pte, 8);
pte = le64_to_cpu(pte);
end = (l1 << 30) + (l2 << 21) + (l3 << 12);
if (pte & PG_PRESENT_MASK) {
@@ -369,13 +371,13 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+ cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
pml4e = le64_to_cpu(pml4e);
end = l1 << 39;
if (pml4e & PG_PRESENT_MASK) {
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+ cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
pdpe = le64_to_cpu(pdpe);
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
@@ -387,7 +389,8 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
} else {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+ cpu_physical_memory_read_debug(pd_addr + l3 * 8,
+ &pde, 8);
pde = le64_to_cpu(pde);
end = (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
@@ -399,9 +402,9 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
} else {
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
+ cpu_physical_memory_read_debug(pt_addr
+ + l4 * 8,
+ &pte, 8);
pte = le64_to_cpu(pte);
end = (l1 << 39) + (l2 << 30) +
(l3 << 21) + (l4 << 12);
@@ -446,7 +449,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
last_prot = 0;
start = -1;
for (l0 = 0; l0 < 512; l0++) {
- cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
+ cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
pml5e = le64_to_cpu(pml5e);
end = l0 << 48;
if (!(pml5e & PG_PRESENT_MASK)) {
@@ -457,7 +460,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pml4_addr = pml5e & 0x3fffffffff000ULL;
for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
+ cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
pml4e = le64_to_cpu(pml4e);
end = (l0 << 48) + (l1 << 39);
if (!(pml4e & PG_PRESENT_MASK)) {
@@ -468,7 +471,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
+ cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
pdpe = le64_to_cpu(pdpe);
end = (l0 << 48) + (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
@@ -487,7 +490,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
+ cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
pde = le64_to_cpu(pde);
end = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
@@ -506,7 +509,8 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr + l4 * 8, &pte, 8);
+ cpu_physical_memory_read_debug(pt_addr + l4 * 8,
+ &pte, 8);
pte = le64_to_cpu(pte);
end = (l0 << 48) + (l1 << 39) + (l2 << 30) +
(l3 << 21) + (l4 << 12);
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 04/26] monitor/i386: use debug APIs when accessing guest memory
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 04/26] monitor/i386: use debug APIs when accessing guest memory Brijesh Singh
@ 2018-02-07 16:53 ` Paolo Bonzini
0 siblings, 0 replies; 39+ messages in thread
From: Paolo Bonzini @ 2018-02-07 16:53 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov, Richard Henderson
On 07/02/2018 17:06, Brijesh Singh wrote:
>
> sum = 0;
> for(addr = start; addr < (start + size); addr++) {
> - uint8_t val = address_space_ldub(&address_space_memory, addr,
> - MEMTXATTRS_UNSPECIFIED, NULL);
> + uint8_t buf[0];
> + uint8_t val;
> + cpu_physical_memory_read_debug(addr, buf, 1);
> + val = ldub_p(buf);
This is a buffer overflow on "buf". All you need is
cpu_physical_memory_read_debug(addr, &val, 1);
Thanks,
Paolo
> /* BSD sum algorithm ('sum' Unix command) */
> sum = (sum >> 1) | (sum << 15);
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (2 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 04/26] monitor/i386: use debug APIs when accessing guest memory Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:54 ` Paolo Bonzini
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 06/26] machine: add -memory-encryption property Brijesh Singh
` (19 subsequent siblings)
23 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
AMD EPYC processors support memory encryption feature. The feature
is reported through CPUID 8000_001F[EAX].
Fn8000_001F [EAX]:
Bit 0 Secure Memory Encryption (SME) supported
Bit 1 Secure Encrypted Virtualization (SEV) supported
Bit 2 Page flush MSR supported
Bit 3 Ecrypted State (SEV-ES) support
when memory encryption feature is reported, CPUID 8000_001F[EBX] should
provide additional information regarding the feature (such as which page
table bit is used to mark pages as encrypted etc). The information in EBX
and ECX may vary from one family to another hence we use the host cpuid
to populate the EBX information.
The details for memory encryption CPUID is available in AMD APM
(https://support.amd.com/TechDocs/24594.pdf) Section E.4.17
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
target/i386/cpu.c | 36 ++++++++++++++++++++++++++++++++++++
target/i386/cpu.h | 6 ++++++
2 files changed, 42 insertions(+)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index a49d2221adc9..4147eb6e18a9 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -234,6 +234,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_EXT4_FEATURES 0
#define TCG_SVM_FEATURES 0
#define TCG_KVM_FEATURES 0
+#define TCG_MEM_ENCRYPT_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
@@ -545,6 +546,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.cpuid_reg = R_EDX,
.tcg_features = ~0U,
},
+ [FEAT_MEM_ENCRYPT] = {
+ .feat_names = {
+ "sme", "sev", "page-flush-msr", "sev-es",
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ },
+ .cpuid_eax = 0x8000001F, .cpuid_reg = R_EAX,
+ .tcg_features = TCG_MEM_ENCRYPT_FEATURES,
+ }
};
typedef struct X86RegisterInfo32 {
@@ -1965,6 +1980,9 @@ static X86CPUDefinition builtin_x86_defs[] = {
CPUID_XSAVE_XGETBV1,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
+ /* Missing: SEV_ES */
+ .features[FEAT_MEM_ENCRYPT] =
+ CPUID_8000_001F_EAX_SME | CPUID_8000_001F_EAX_SEV,
.xlevel = 0x8000000A,
.model_id = "AMD EPYC Processor",
},
@@ -3589,6 +3607,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = 0;
}
break;
+ case 0x8000001F:
+ if (env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV) {
+ *eax = env->features[FEAT_MEM_ENCRYPT];
+ host_cpuid(0x8000001F, 0, NULL, ebx, NULL, NULL);
+ *ecx = 0;
+ *edx = 0;
+ } else {
+ *eax = 0;
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
+ }
+ break;
case 0xC0000000:
*eax = env->cpuid_xlevel2;
*ebx = 0;
@@ -4036,10 +4067,15 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
+ x86_cpu_adjust_feat_level(cpu, FEAT_MEM_ENCRYPT);
/* SVM requires CPUID[0x8000000A] */
if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
}
+ /* SEV requires CPUID[0x8000001F] */
+ if ((env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV)) {
+ x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F);
+ }
}
/* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index f91e37d25dea..f7a0ab20fdd1 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -483,6 +483,7 @@ typedef enum FeatureWord {
FEAT_6_EAX, /* CPUID[6].EAX */
FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
+ FEAT_MEM_ENCRYPT, /* CPUID[8000_001F].EAX */
FEATURE_WORDS,
} FeatureWord;
@@ -679,6 +680,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_6_EAX_ARAT (1U << 2)
+#define CPUID_8000_001F_EAX_SME (1U << 0) /* SME */
+#define CPUID_8000_001F_EAX_SEV (1U << 1) /* SEV */
+#define CPUID_8000_001F_EAX_PAGE_FLUSH_MSR (1U << 2) /* Page flush MSR */
+#define CPUID_8000_001F_EAX_SEV_ES (1U << 3) /* SEV-ES */
+
/* CPUID[0x80000007].EDX flags: */
#define CPUID_APM_INVTSC (1U << 8)
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support Brijesh Singh
@ 2018-02-07 16:54 ` Paolo Bonzini
2018-02-07 18:28 ` Brijesh Singh
0 siblings, 1 reply; 39+ messages in thread
From: Paolo Bonzini @ 2018-02-07 16:54 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov, Richard Henderson
On 07/02/2018 17:06, Brijesh Singh wrote:
> AMD EPYC processors support memory encryption feature. The feature
> is reported through CPUID 8000_001F[EAX].
>
> Fn8000_001F [EAX]:
> Bit 0 Secure Memory Encryption (SME) supported
> Bit 1 Secure Encrypted Virtualization (SEV) supported
> Bit 2 Page flush MSR supported
> Bit 3 Ecrypted State (SEV-ES) support
>
> when memory encryption feature is reported, CPUID 8000_001F[EBX] should
> provide additional information regarding the feature (such as which page
> table bit is used to mark pages as encrypted etc). The information in EBX
> and ECX may vary from one family to another hence we use the host cpuid
> to populate the EBX information.
>
> The details for memory encryption CPUID is available in AMD APM
> (https://support.amd.com/TechDocs/24594.pdf) Section E.4.17
>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Richard Henderson <rth@twiddle.net>
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> target/i386/cpu.c | 36 ++++++++++++++++++++++++++++++++++++
> target/i386/cpu.h | 6 ++++++
> 2 files changed, 42 insertions(+)
>
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index a49d2221adc9..4147eb6e18a9 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -234,6 +234,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
> #define TCG_EXT4_FEATURES 0
> #define TCG_SVM_FEATURES 0
> #define TCG_KVM_FEATURES 0
> +#define TCG_MEM_ENCRYPT_FEATURES 0
> #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
> CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
> CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
> @@ -545,6 +546,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
> .cpuid_reg = R_EDX,
> .tcg_features = ~0U,
> },
> + [FEAT_MEM_ENCRYPT] = {
> + .feat_names = {
> + "sme", "sev", "page-flush-msr", "sev-es",
Why would sme ever be on in a guest? That is, would a guest care about
whether SME is on in the host?
Paolo
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL,
> + },
> + .cpuid_eax = 0x8000001F, .cpuid_reg = R_EAX,
> + .tcg_features = TCG_MEM_ENCRYPT_FEATURES,
> + }
> };
>
> typedef struct X86RegisterInfo32 {
> @@ -1965,6 +1980,9 @@ static X86CPUDefinition builtin_x86_defs[] = {
> CPUID_XSAVE_XGETBV1,
> .features[FEAT_6_EAX] =
> CPUID_6_EAX_ARAT,
> + /* Missing: SEV_ES */
> + .features[FEAT_MEM_ENCRYPT] =
> + CPUID_8000_001F_EAX_SME | CPUID_8000_001F_EAX_SEV,
> .xlevel = 0x8000000A,
> .model_id = "AMD EPYC Processor",
> },
> @@ -3589,6 +3607,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> *edx = 0;
> }
> break;
> + case 0x8000001F:
> + if (env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV) {
> + *eax = env->features[FEAT_MEM_ENCRYPT];
> + host_cpuid(0x8000001F, 0, NULL, ebx, NULL, NULL);
> + *ecx = 0;
> + *edx = 0;
> + } else {
> + *eax = 0;
> + *ebx = 0;
> + *ecx = 0;
> + *edx = 0;
> + }
> + break;
> case 0xC0000000:
> *eax = env->cpuid_xlevel2;
> *ebx = 0;
> @@ -4036,10 +4067,15 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
> x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
> x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
> x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
> + x86_cpu_adjust_feat_level(cpu, FEAT_MEM_ENCRYPT);
> /* SVM requires CPUID[0x8000000A] */
> if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
> x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
> }
> + /* SEV requires CPUID[0x8000001F] */
> + if ((env->features[FEAT_MEM_ENCRYPT] & CPUID_8000_001F_EAX_SEV)) {
> + x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F);
> + }
> }
>
> /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index f91e37d25dea..f7a0ab20fdd1 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -483,6 +483,7 @@ typedef enum FeatureWord {
> FEAT_6_EAX, /* CPUID[6].EAX */
> FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
> FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
> + FEAT_MEM_ENCRYPT, /* CPUID[8000_001F].EAX */
> FEATURE_WORDS,
> } FeatureWord;
>
> @@ -679,6 +680,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
>
> #define CPUID_6_EAX_ARAT (1U << 2)
>
> +#define CPUID_8000_001F_EAX_SME (1U << 0) /* SME */
> +#define CPUID_8000_001F_EAX_SEV (1U << 1) /* SEV */
> +#define CPUID_8000_001F_EAX_PAGE_FLUSH_MSR (1U << 2) /* Page flush MSR */
> +#define CPUID_8000_001F_EAX_SEV_ES (1U << 3) /* SEV-ES */
> +
> /* CPUID[0x80000007].EDX flags: */
> #define CPUID_APM_INVTSC (1U << 8)
>
>
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support
2018-02-07 16:54 ` Paolo Bonzini
@ 2018-02-07 18:28 ` Brijesh Singh
0 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 18:28 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
Cc: brijesh.singh, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost,
Eric Blake, kvm, Marcel Apfelbaum, Markus Armbruster,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov,
Richard Henderson
On 02/07/2018 10:54 AM, Paolo Bonzini wrote:
> On 07/02/2018 17:06, Brijesh Singh wrote:
>> AMD EPYC processors support memory encryption feature. The feature
>> is reported through CPUID 8000_001F[EAX].
>>
>> Fn8000_001F [EAX]:
>> Bit 0 Secure Memory Encryption (SME) supported
>> Bit 1 Secure Encrypted Virtualization (SEV) supported
>> Bit 2 Page flush MSR supported
>> Bit 3 Ecrypted State (SEV-ES) support
>>
>> when memory encryption feature is reported, CPUID 8000_001F[EBX] should
>> provide additional information regarding the feature (such as which page
>> table bit is used to mark pages as encrypted etc). The information in EBX
>> and ECX may vary from one family to another hence we use the host cpuid
>> to populate the EBX information.
>>
>> The details for memory encryption CPUID is available in AMD APM
>> (https://support.amd.com/TechDocs/24594.pdf) Section E.4.17
>>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Richard Henderson <rth@twiddle.net>
>> Cc: Eduardo Habkost <ehabkost@redhat.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>> target/i386/cpu.c | 36 ++++++++++++++++++++++++++++++++++++
>> target/i386/cpu.h | 6 ++++++
>> 2 files changed, 42 insertions(+)
>>
>> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
>> index a49d2221adc9..4147eb6e18a9 100644
>> --- a/target/i386/cpu.c
>> +++ b/target/i386/cpu.c
>> @@ -234,6 +234,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
>> #define TCG_EXT4_FEATURES 0
>> #define TCG_SVM_FEATURES 0
>> #define TCG_KVM_FEATURES 0
>> +#define TCG_MEM_ENCRYPT_FEATURES 0
>> #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
>> CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
>> CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
>> @@ -545,6 +546,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>> .cpuid_reg = R_EDX,
>> .tcg_features = ~0U,
>> },
>> + [FEAT_MEM_ENCRYPT] = {
>> + .feat_names = {
>> + "sme", "sev", "page-flush-msr", "sev-es",
>
> Why would sme ever be on in a guest? That is, would a guest care about
> whether SME is on in the host?
Guest does not need the SME feature bit exposed and it does not care
whether SME is enabled on the host. Since I was defining the bit fields
from 8000_001F EAX hence I tried to list them all. In next version, I
will update the MEM_ENCRYPT feature to expose just SEV.
Thanks
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 06/26] machine: add -memory-encryption property
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (3 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 05/26] target/i386: add memory encryption feature cpuid support Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 07/26] kvm: update kvm.h to include memory encryption ioctls Brijesh Singh
` (18 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
When CPU supports memory encryption feature, the property can be used to
specify the encryption object to use when launching an encrypted guest.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcel Apfelbaum <marcel@redhat.com>
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
hw/core/machine.c | 22 ++++++++++++++++++++++
include/hw/boards.h | 1 +
qemu-options.hx | 2 ++
3 files changed, 25 insertions(+)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cdc1163dc6fb..e9940e58ad65 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -334,6 +334,22 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp)
return ms->enforce_config_section;
}
+static char *machine_get_memory_encryption(Object *obj, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ return g_strdup(ms->memory_encryption);
+}
+
+static void machine_set_memory_encryption(Object *obj, const char *value,
+ Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ g_free(ms->memory_encryption);
+ ms->memory_encryption = g_strdup(value);
+}
+
void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
{
strList *item = g_new0(strList, 1);
@@ -612,6 +628,12 @@ static void machine_class_init(ObjectClass *oc, void *data)
&error_abort);
object_class_property_set_description(oc, "enforce-config-section",
"Set on to enforce configuration section migration", &error_abort);
+
+ object_class_property_add_str(oc, "memory-encryption",
+ machine_get_memory_encryption, machine_set_memory_encryption,
+ &error_abort);
+ object_class_property_set_description(oc, "memory-encryption",
+ "Set memory encyption object to use", &error_abort);
}
static void machine_class_base_init(ObjectClass *oc, void *data)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index efb0a9edfdf1..8ce9a7a21d3d 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -243,6 +243,7 @@ struct MachineState {
bool suppress_vmdesc;
bool enforce_config_section;
bool enable_graphics;
+ char *memory_encryption;
ram_addr_t ram_size;
ram_addr_t maxram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index 8ce427da7880..7defd929caa4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -110,6 +110,8 @@ code to send configuration section even if the machine-type sets the
@option{migration.send-configuration} property to @var{off}.
NOTE: this parameter is deprecated. Please use @option{-global}
@option{migration.send-configuration}=@var{on|off} instead.
+@item memory-encryption=@var{}
+Memory encryption object to use. The default is none.
@end table
ETEXI
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 07/26] kvm: update kvm.h to include memory encryption ioctls
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (4 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 06/26] machine: add -memory-encryption property Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 08/26] docs: add AMD Secure Encrypted Virtualization (SEV) Brijesh Singh
` (17 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
Updates kmv.h to include memory encryption ioctls and SEV commands.
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
| 90 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index d92c9b2f0ed2..aed22309950d 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1362,6 +1362,96 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_S390_CMMA_MIGRATION */
#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
+/* Memory Encryption Commands */
+#define KVM_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0xba, unsigned long)
+
+struct kvm_enc_region {
+ __u64 addr;
+ __u64 size;
+};
+
+#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region)
+#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region)
+
+/* Secure Encrypted Virtualization command */
+enum sev_cmd_id {
+ /* Guest initialization commands */
+ KVM_SEV_INIT = 0,
+ KVM_SEV_ES_INIT,
+ /* Guest launch commands */
+ KVM_SEV_LAUNCH_START,
+ KVM_SEV_LAUNCH_UPDATE_DATA,
+ KVM_SEV_LAUNCH_UPDATE_VMSA,
+ KVM_SEV_LAUNCH_SECRET,
+ KVM_SEV_LAUNCH_MEASURE,
+ KVM_SEV_LAUNCH_FINISH,
+ /* Guest migration commands (outgoing) */
+ KVM_SEV_SEND_START,
+ KVM_SEV_SEND_UPDATE_DATA,
+ KVM_SEV_SEND_UPDATE_VMSA,
+ KVM_SEV_SEND_FINISH,
+ /* Guest migration commands (incoming) */
+ KVM_SEV_RECEIVE_START,
+ KVM_SEV_RECEIVE_UPDATE_DATA,
+ KVM_SEV_RECEIVE_UPDATE_VMSA,
+ KVM_SEV_RECEIVE_FINISH,
+ /* Guest status and debug commands */
+ KVM_SEV_GUEST_STATUS,
+ KVM_SEV_DBG_DECRYPT,
+ KVM_SEV_DBG_ENCRYPT,
+ /* Guest certificates commands */
+ KVM_SEV_CERT_EXPORT,
+
+ KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_cmd {
+ __u32 id;
+ __u64 data;
+ __u32 error;
+ __u32 sev_fd;
+};
+
+struct kvm_sev_launch_start {
+ __u32 handle;
+ __u32 policy;
+ __u64 dh_uaddr;
+ __u32 dh_len;
+ __u64 session_uaddr;
+ __u32 session_len;
+};
+
+struct kvm_sev_launch_update_data {
+ __u64 uaddr;
+ __u32 len;
+};
+
+
+struct kvm_sev_launch_secret {
+ __u64 hdr_uaddr;
+ __u32 hdr_len;
+ __u64 guest_uaddr;
+ __u32 guest_len;
+ __u64 trans_uaddr;
+ __u32 trans_len;
+};
+
+struct kvm_sev_launch_measure {
+ __u64 uaddr;
+ __u32 len;
+};
+
+struct kvm_sev_guest_status {
+ __u32 handle;
+ __u32 policy;
+ __u32 state;
+};
+
+struct kvm_sev_dbg {
+ __u64 src_uaddr;
+ __u64 dst_uaddr;
+ __u32 len;
+};
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 08/26] docs: add AMD Secure Encrypted Virtualization (SEV)
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (5 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 07/26] kvm: update kvm.h to include memory encryption ioctls Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 09/26] accel: add Secure Encrypted Virtulization (SEV) object Brijesh Singh
` (16 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
Create a documentation entry to describe the AMD Secure Encrypted
Virtualization (SEV) feature.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
docs/amd-memory-encryption.txt | 92 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 docs/amd-memory-encryption.txt
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
new file mode 100644
index 000000000000..72a92b6c6353
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,92 @@
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+SEV is an extension to the AMD-V architecture which supports running encrypted
+virtual machine (VMs) under the control of KVM. Encrypted VMs have their pages
+(code and data) secured such that only the guest itself has access to the
+unencrypted version. Each encrypted VM is associated with a unique encryption
+key; if its data is accessed to a different entity using a different key the
+encrypted guests data will be incorrectly decrypted, leading to unintelligible
+data.
+
+The key management of this feature is handled by separate processor known as
+AMD secure processor (AMD-SP) which is present in AMD SOCs. Firmware running
+inside the AMD-SP provide commands to support common VM lifecycle. This
+includes commands for launching, snapshotting, migrating and debugging the
+encrypted guest. Those SEV command can be issued via KVM_MEMORY_ENCRYPT_OP
+ioctls.
+
+Launching
+---------
+Boot images (such as bios) must be encrypted before guest can be booted.
+MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images :LAUNCH_START,
+LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
+together generate a fresh memory encryption key for the VM, encrypt the boot
+images and provide a measurement than can be used as an attestation of the
+successful launch.
+
+LAUNCH_START is called first to create a cryptographic launch context within
+the firmware. To create this context, guest owner must provides guest policy,
+its public Diffie-Hellman key (PDH) and session parameters. These inputs
+should be treated as binary blob and must be passed as-is to the SEV firmware.
+
+The guest policy is passed as plaintext and hypervisor may able to read it
+but should not modify it (any modification of the policy bits will result
+in bad measurement). The guest policy is a 4-byte data structure containing
+several flags that restricts what can be done on running SEV guest.
+See KM Spec section 3 and 6.2 for more details.
+
+Guest owners provided DH certificate and session parameters will be used to
+establish a cryptographic session with the guest owner to negotiate keys used
+for the attestation.
+
+LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
+created via LAUNCH_START command. If required, this command can be called
+multiple times to encrypt different memory regions. The command also calculates
+the measurement of the memory contents as it encrypts.
+
+LAUNCH_MEASURE command can be used to retrieve the measurement of encrypted
+memory. This measurement is a signature of the memory contents that can be
+sent to the guest owner as an attestation that the memory was encrypted
+correctly by the firmware. The guest owner may wait to provide the guest
+confidential information until it can verify the attestation measurement.
+Since the guest owner knows the initial contents of the guest at boot, the
+attestation measurement can be verified by comparing it to what the guest owner
+expects.
+
+LAUNCH_FINISH command finalizes the guest launch and destroy's the cryptographic
+context.
+
+See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
+complete flow chart.
+
+Debugging
+-----------
+Since memory contents of SEV guest is encrypted hence hypervisor access to the
+guest memory will get a cipher text. If guest policy allows debugging, then
+hypervisor can use DEBUG_DECRYPT and DEBUG_ENCRYPT commands access the guest
+memory region for debug purposes.
+
+Snapshot/Restore
+-----------------
+TODO
+
+Live Migration
+----------------
+TODO
+
+References
+-----------------
+
+AMD Memory Encryption whitepaper:
+http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+
+Secure Encrypted Virutualization Key Management:
+[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
+
+KVM Forum slides:
+http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
+
+AMD64 Architecture Programmer's Manual:
+ http://support.amd.com/TechDocs/24593.pdf
+ SME is section 7.10
+ SEV is section 15.34
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 09/26] accel: add Secure Encrypted Virtulization (SEV) object
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (6 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 08/26] docs: add AMD Secure Encrypted Virtualization (SEV) Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 10/26] sev: add command to initialize the memory encryption context Brijesh Singh
` (15 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
Add a new memory encryption object 'sev-guest'. The object will be used
to create enrypted VMs on AMD EPYC CPU. The object provides the properties
to pass guest owner's public Diffie-hellman key, guest policy and session
information required to create the memory encryption context within the
SEV firmware.
e.g to launch SEV guest
# $QEMU \
-object sev-guest,id=sev0 \
-machine ....,memory-encryption=sev0
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/Makefile.objs | 2 +-
accel/kvm/sev.c | 214 +++++++++++++++++++++++++++++++++++++++++
docs/amd-memory-encryption.txt | 17 ++++
include/sysemu/sev.h | 54 +++++++++++
qemu-options.hx | 36 +++++++
5 files changed, 322 insertions(+), 1 deletion(-)
create mode 100644 accel/kvm/sev.c
create mode 100644 include/sysemu/sev.h
diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs
index 85351e7de7e8..666ceef3dae3 100644
--- a/accel/kvm/Makefile.objs
+++ b/accel/kvm/Makefile.objs
@@ -1 +1 @@
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
new file mode 100644
index 000000000000..57e092a0bddd
--- /dev/null
+++ b/accel/kvm/sev.c
@@ -0,0 +1,214 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016-2018
+ *
+ * Author:
+ * Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "qemu/base64.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
+#include "sysemu/sysemu.h"
+
+#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
+#define DEFAULT_SEV_DEVICE "/dev/sev"
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_guest_get_session_file(Object *obj, Error **errp)
+{
+ QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+ return s->session_file ? g_strdup(s->session_file) : NULL;
+}
+
+static void
+qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
+{
+ QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+ s->session_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
+{
+ QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+ return g_strdup(s->dh_cert_file);
+}
+
+static void
+qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
+{
+ QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
+
+ s->dh_cert_file = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_sev_device(Object *obj, Error **errp)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ return g_strdup(sev->sev_device);
+}
+
+static void
+qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ sev->sev_device = g_strdup(value);
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+ object_class_property_add_str(oc, "sev-device",
+ qsev_guest_get_sev_device,
+ qsev_guest_set_sev_device,
+ NULL);
+ object_class_property_set_description(oc, "sev-device",
+ "SEV device to use", NULL);
+ object_class_property_add_str(oc, "dh-cert-file",
+ qsev_guest_get_dh_cert_file,
+ qsev_guest_set_dh_cert_file,
+ NULL);
+ object_class_property_set_description(oc, "dh-cert-file",
+ "guest owners DH certificate (encoded with base64)", NULL);
+ object_class_property_add_str(oc, "session-file",
+ qsev_guest_get_session_file,
+ qsev_guest_set_session_file,
+ NULL);
+ object_class_property_set_description(oc, "session-file",
+ "guest owners session parameters (encoded with base64)", NULL);
+}
+
+static void
+qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, errp);
+ sev->handle = value;
+}
+
+static void
+qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, errp);
+ sev->policy = value;
+}
+
+static void
+qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, errp);
+ sev->cbitpos = value;
+}
+
+static void
+qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ uint32_t value;
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ value = sev->policy;
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ uint32_t value;
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ value = sev->handle;
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ uint32_t value;
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ value = sev->cbitpos;
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static uint32_t
+sev_get_host_cbitpos(void)
+{
+ uint32_t ebx;
+
+ host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
+
+ return ebx & 0x3f;
+}
+
+static void
+qsev_guest_init(Object *obj)
+{
+ QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+ sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
+ sev->policy = DEFAULT_GUEST_POLICY;
+ sev->cbitpos = sev_get_host_cbitpos();
+ object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
+ qsev_guest_set_policy, NULL, NULL, NULL);
+ object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
+ qsev_guest_set_handle, NULL, NULL, NULL);
+ object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
+ qsev_guest_set_cbitpos, NULL, NULL, NULL);
+}
+
+/* sev guest info */
+static const TypeInfo qsev_guest_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_QSEV_GUEST_INFO,
+ .instance_size = sizeof(QSevGuestInfo),
+ .instance_finalize = qsev_guest_finalize,
+ .class_size = sizeof(QSevGuestInfoClass),
+ .class_init = qsev_guest_class_init,
+ .instance_init = qsev_guest_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void
+sev_register_types(void)
+{
+ type_register_static(&qsev_guest_info);
+}
+
+type_init(sev_register_types);
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
index 72a92b6c6353..1527f603ea2a 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/amd-memory-encryption.txt
@@ -35,10 +35,21 @@ in bad measurement). The guest policy is a 4-byte data structure containing
several flags that restricts what can be done on running SEV guest.
See KM Spec section 3 and 6.2 for more details.
+The guest policy can be provided via the 'policy' property (see below)
+
+# ${QEMU} \
+ sev-guest,id=sev0,policy=0x1...\
+
Guest owners provided DH certificate and session parameters will be used to
establish a cryptographic session with the guest owner to negotiate keys used
for the attestation.
+The DH certificate and session blob can be provided via 'dh-cert-file' and
+'session-file' property (see below
+
+# ${QEMU} \
+ sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
+
LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
created via LAUNCH_START command. If required, this command can be called
multiple times to encrypt different memory regions. The command also calculates
@@ -59,6 +70,12 @@ context.
See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
complete flow chart.
+To launch a SEV guest
+
+# ${QEMU} \
+ -machine ...,memory-encryption=sev0 \
+ -object sev-guest,id=sev0
+
Debugging
-----------
Since memory contents of SEV guest is encrypted hence hypervisor access to the
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 000000000000..eed679653dbc
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,54 @@
+/*
+ * QEMU Secure Encrypted Virutualization (SEV) support
+ *
+ * Copyright: Advanced Micro Devices, 2016-2018
+ *
+ * Authors:
+ * Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_SEV_H
+#define QEMU_SEV_H
+
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "sysemu/kvm.h"
+#include "qemu/error-report.h"
+
+#define TYPE_QSEV_GUEST_INFO "sev-guest"
+#define QSEV_GUEST_INFO(obj) \
+ OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO)
+
+typedef struct QSevGuestInfo QSevGuestInfo;
+typedef struct QSevGuestInfoClass QSevGuestInfoClass;
+
+/**
+ * QSevGuestInfo:
+ *
+ * The QSevGuestInfo object is used for creating a SEV guest.
+ *
+ * # $QEMU \
+ * -object sev-guest,id=sev0 \
+ * -machine ...,memory-encryption=sev0
+ */
+struct QSevGuestInfo {
+ Object parent_obj;
+
+ char *sev_device;
+ uint32_t policy;
+ uint32_t handle;
+ char *dh_cert_file;
+ char *session_file;
+ uint32_t cbitpos;
+};
+
+struct QSevGuestInfoClass {
+ ObjectClass parent_class;
+};
+
+#endif
+
diff --git a/qemu-options.hx b/qemu-options.hx
index 7defd929caa4..f34305de0d9a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4282,6 +4282,42 @@ contents of @code{iv.b64} to the second secret
data=$SECRET,iv=$(<iv.b64)
@end example
+@item -object sev-guest,id=@var{id},sev-device=@var{string}[cbitpos=@var{cbitpos},policy=@var{policy},handle=@var{handle},dh-cert-file=@var{file},session-file=@var{file}]
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which can be used
+to provide the guest memory encryption support on AMD processors.
+
+The @option{sev-device} provides the device file to use for communicating with
+the SEV firmware running inside AMD Secure Processor. The default device is
+'/dev/sev'. If hardware supports memory encryption then /dev/sev devices are
+created by CCP driver.
+
+The @option{cbitpos} provide the C-bit location in guest page table entry to use.
+
+The @option{policy} provides the guest policy to be enforced by the SEV firmware
+and restrict what configuration and operational commands can be performed on this
+guest by the hypervisor. The policy should be provided by the guest owner and is
+bound to the guest and cannot be changed throughout the lifetime of the guest.
+The default is 0.
+
+If guest @option{policy} allows sharing the key with another SEV guest then
+@option{handle} can be use to provide handle of the guest from which to share
+the key.
+
+The @option{dh-cert-file} and @option{session-file} provides the guest owner's
+Public Diffie-Hillman key defined in SEV spec. The PDH and session parameters
+are used for establishing a cryptographic session with the guest owner to
+negotiate keys used for attestation. The file must be encoded in base64.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+ ......
+ -object sev-guest,id=sev0 \
+ -machine ...,memory-encryption=sev0
+ .....
+
+@end example
@end table
ETEXI
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 10/26] sev: add command to initialize the memory encryption context
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (7 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 09/26] accel: add Secure Encrypted Virtulization (SEV) object Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 11/26] sev: register the guest memory range which may contain encrypted data Brijesh Singh
` (14 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
When memory encryption is enabled, KVM_SEV_INIT command is used to
initialize the platform. The command loads the SEV related persistent
data from non-volatile storage and initializes the platform context.
This command should be first issued before invoking any other guest
commands provided by the SEV firmware.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/kvm-all.c | 15 +++++
accel/kvm/sev.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 2 +
accel/stubs/kvm-stub.c | 28 +++++++++
include/sysemu/sev.h | 16 +++++
5 files changed, 222 insertions(+)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f290f487a573..6e5f3fd65066 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -38,6 +38,7 @@
#include "qemu/event_notifier.h"
#include "trace.h"
#include "hw/irq.h"
+#include "sysemu/sev.h"
#include "hw/boards.h"
@@ -103,6 +104,9 @@ struct KVMState
#endif
KVMMemoryListener memory_listener;
QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
+
+ /* memory encryption */
+ void *memcrypt_handle;
};
KVMState *kvm_state;
@@ -1632,6 +1636,17 @@ static int kvm_init(MachineState *ms)
kvm_state = s;
+ /*
+ * if memory encryption object is specified then initialize the memory
+ * encryption context.
+ */
+ if (ms->memory_encryption) {
+ kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption);
+ if (!kvm_state->memcrypt_handle) {
+ goto err;
+ }
+ }
+
ret = kvm_arch_init(ms, s);
if (ret < 0) {
goto err;
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 57e092a0bddd..d5fd975792b8 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -18,10 +18,74 @@
#include "sysemu/kvm.h"
#include "sysemu/sev.h"
#include "sysemu/sysemu.h"
+#include "trace.h"
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
#define DEFAULT_SEV_DEVICE "/dev/sev"
+static uint64_t me_mask;
+static bool sev_active;
+static int sev_fd;
+
+#define SEV_FW_MAX_ERROR 0x17
+
+static const char *const sev_fw_errlist[] = {
+ "",
+ "Platform state is invalid",
+ "Guest state is invalid",
+ "Platform configuration is invalid",
+ "Buffer too small",
+ "Platform is already owned",
+ "Certificate is invalid",
+ "Policy is not allowed",
+ "Guest is not active",
+ "Invalid address",
+ "Bad signature",
+ "Bad measurement",
+ "Asid is already owned",
+ "Invalid ASID",
+ "WBINVD is required",
+ "DF_FLUSH is required",
+ "Guest handle is invalid",
+ "Invalid command",
+ "Guest is active",
+ "Hardware error",
+ "Hardware unsafe",
+ "Feature not supported",
+ "Invalid parameter"
+};
+
+static int
+sev_ioctl(int cmd, void *data, int *error)
+{
+ int r;
+ struct kvm_sev_cmd input;
+
+ memset(&input, 0x0, sizeof(input));
+
+ input.id = cmd;
+ input.sev_fd = sev_fd;
+ input.data = (__u64)data;
+
+ r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
+
+ if (error) {
+ *error = input.error;
+ }
+
+ return r;
+}
+
+static const char *
+fw_error_to_str(int code)
+{
+ if (code >= SEV_FW_MAX_ERROR) {
+ return "unknown error";
+ }
+
+ return sev_fw_errlist[code];
+}
+
static void
qsev_guest_finalize(Object *obj)
{
@@ -205,6 +269,103 @@ static const TypeInfo qsev_guest_info = {
}
};
+static QSevGuestInfo *
+lookup_sev_guest_info(const char *id)
+{
+ Object *obj;
+ QSevGuestInfo *info;
+
+ obj = object_resolve_path_component(object_get_objects_root(), id);
+ if (!obj) {
+ return NULL;
+ }
+
+ info = (QSevGuestInfo *)
+ object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
+ if (!info) {
+ return NULL;
+ }
+
+ return info;
+}
+
+uint64_t
+sev_get_me_mask(void)
+{
+ return ~me_mask;
+}
+
+void
+sev_get_current_state(char **state)
+{
+}
+
+bool
+sev_enabled(void)
+{
+ return sev_active;
+}
+
+void
+sev_get_fw_version(uint8_t *major, uint8_t *minor, uint8_t *build)
+{
+}
+
+void
+sev_get_policy(uint32_t *policy)
+{
+}
+
+void *
+sev_guest_init(const char *id)
+{
+ SEVState *s;
+ char *devname;
+ int ret, fw_error;
+ uint32_t host_cbitpos, cbitpos;
+
+ s = g_new0(SEVState, 1);
+ s->sev_info = lookup_sev_guest_info(id);
+ if (!s->sev_info) {
+ error_report("%s: '%s' is not a valid '%s' object",
+ __func__, id, TYPE_QSEV_GUEST_INFO);
+ goto err;
+ }
+
+ host_cbitpos = sev_get_host_cbitpos();
+ cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL);
+ if (host_cbitpos != cbitpos) {
+ error_report("%s: cbitpos check failed, host '%d' request '%d'",
+ __func__, host_cbitpos, cbitpos);
+ goto err;
+ }
+
+ me_mask = (1UL << cbitpos);
+
+ devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
+ sev_fd = open(devname, O_RDWR);
+ if (sev_fd < 0) {
+ error_report("%s: Failed to open %s '%s'", __func__,
+ devname, strerror(errno));
+ goto err;
+ }
+ g_free(devname);
+
+ trace_kvm_sev_init();
+ ret = sev_ioctl(KVM_SEV_INIT, NULL, &fw_error);
+ if (ret) {
+ error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
+ goto err;
+ }
+
+ sev_active = true;
+ return s;
+err:
+ g_free(s);
+ return NULL;
+}
+
static void
sev_register_types(void)
{
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index f89ba5578dc1..ea487e5a5913 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -13,3 +13,5 @@ kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d vi
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
kvm_irqchip_release_virq(int virq) "virq %d"
+# sev.c
+kvm_sev_init(void) ""
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index c964af3e1c97..bb78a1f1b950 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -14,6 +14,7 @@
#include "qemu-common.h"
#include "cpu.h"
#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
#ifndef CONFIG_USER_ONLY
#include "hw/pci/msi.h"
@@ -33,6 +34,11 @@ bool kvm_readonly_mem_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
+bool sev_allowed;
+uint8_t sev_fw_major;
+uint8_t sev_fw_minor;
+uint8_t sev_fw_build;
+
int kvm_destroy_vcpu(CPUState *cpu)
{
return -ENOSYS;
@@ -105,6 +111,28 @@ int kvm_on_sigbus(int code, void *addr)
return 1;
}
+void sev_get_current_state(char **state)
+{
+}
+
+bool sev_enabled(void)
+{
+ return false;
+}
+
+uint64_t sev_get_me_mask(void)
+{
+ return ~0UL;
+}
+
+void sev_get_fw_version(uint8_t *major, uint8_t *minor, uint8_t *build)
+{
+}
+
+void sev_get_policy(uint32_t *policy)
+{
+}
+
#ifndef CONFIG_USER_ONLY
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index eed679653dbc..121e7e4aa44c 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -14,6 +14,8 @@
#ifndef QEMU_SEV_H
#define QEMU_SEV_H
+#include <linux/kvm.h>
+
#include "qom/object.h"
#include "qapi/error.h"
#include "sysemu/kvm.h"
@@ -23,6 +25,12 @@
#define QSEV_GUEST_INFO(obj) \
OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO)
+extern bool sev_enabled(void);
+extern uint64_t sev_get_me_mask(void);
+extern void sev_get_current_state(char **state);
+extern void sev_get_fw_version(uint8_t *major, uint8_t *minor, uint8_t *build);
+extern void sev_get_policy(uint32_t *policy);
+
typedef struct QSevGuestInfo QSevGuestInfo;
typedef struct QSevGuestInfoClass QSevGuestInfoClass;
@@ -50,5 +58,13 @@ struct QSevGuestInfoClass {
ObjectClass parent_class;
};
+struct SEVState {
+ QSevGuestInfo *sev_info;
+};
+
+typedef struct SEVState SEVState;
+
+void *sev_guest_init(const char *id);
+
#endif
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 11/26] sev: register the guest memory range which may contain encrypted data
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (8 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 10/26] sev: add command to initialize the memory encryption context Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 12/26] kvm: introduce memory encryption APIs Brijesh Singh
` (13 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
When SEV is enabled, the hardware encryption engine uses a tweak such
that the two identical plaintext at different location will have a
different ciphertexts. So swapping or moving a ciphertexts of two guest
pages will not result in plaintexts being swapped. Hence relocating
a physical backing pages of the SEV guest will require some additional
steps in KVM driver. The KVM_MEMORY_ENCRYPT_{UN,}REG_REGION ioctl can be
used to register/unregister the guest memory region which may contain the
encrypted data. KVM driver will internally handle the relocating physical
backing pages of registered memory regions.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/sev.c | 41 +++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 2 ++
2 files changed, 43 insertions(+)
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index d5fd975792b8..2c4bbba3c367 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -86,6 +86,45 @@ fw_error_to_str(int code)
return sev_fw_errlist[code];
}
+static void
+sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
+{
+ int r;
+ struct kvm_enc_region range;
+
+ range.addr = (__u64)host;
+ range.size = size;
+
+ trace_kvm_memcrypt_register_region(host, size);
+ r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
+ if (r) {
+ error_report("%s: failed to register region (%p+%#lx)",
+ __func__, host, size);
+ }
+}
+
+static void
+sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
+{
+ int r;
+ struct kvm_enc_region range;
+
+ range.addr = (__u64)host;
+ range.size = size;
+
+ trace_kvm_memcrypt_unregister_region(host, size);
+ r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
+ if (r) {
+ error_report("%s: failed to unregister region (%p+%#lx)",
+ __func__, host, size);
+ }
+}
+
+static struct RAMBlockNotifier sev_ram_notifier = {
+ .ram_block_added = sev_ram_block_added,
+ .ram_block_removed = sev_ram_block_removed,
+};
+
static void
qsev_guest_finalize(Object *obj)
{
@@ -360,6 +399,8 @@ sev_guest_init(const char *id)
}
sev_active = true;
+ ram_block_notifier_add(&sev_ram_notifier);
+
return s;
err:
g_free(s);
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index ea487e5a5913..364c84bd7a73 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -15,3 +15,5 @@ kvm_irqchip_release_virq(int virq) "virq %d"
# sev.c
kvm_sev_init(void) ""
+kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%lu"
+kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%lu"
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 12/26] kvm: introduce memory encryption APIs
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (9 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 11/26] sev: register the guest memory range which may contain encrypted data Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command Brijesh Singh
` (12 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
Inorder to integerate the Secure Encryption Virtualization (SEV) support
add few high-level memory encryption APIs which can be used for encrypting
the guest memory region.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/kvm-all.c | 30 ++++++++++++++++++++++++++++++
accel/stubs/kvm-stub.c | 14 ++++++++++++++
include/sysemu/kvm.h | 25 +++++++++++++++++++++++++
3 files changed, 69 insertions(+)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 6e5f3fd65066..f1fb826f0648 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -107,6 +107,8 @@ struct KVMState
/* memory encryption */
void *memcrypt_handle;
+ int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
+ void (*memcrypt_debug_ops)(void *handle, MemoryRegion *mr);
};
KVMState *kvm_state;
@@ -142,6 +144,34 @@ int kvm_get_max_memslots(void)
return s->nr_slots;
}
+bool kvm_memcrypt_enabled(void)
+{
+ if (kvm_state && kvm_state->memcrypt_handle) {
+ return true;
+ }
+
+ return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+ if (kvm_state->memcrypt_handle &&
+ kvm_state->memcrypt_encrypt_data) {
+ return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle,
+ ptr, len);
+ }
+
+ return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+ if (kvm_state->memcrypt_handle &&
+ kvm_state->memcrypt_debug_ops) {
+ kvm_state->memcrypt_debug_ops(kvm_state->memcrypt_handle, mr);
+ }
+}
+
static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
{
KVMState *s = kvm_state;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index bb78a1f1b950..e7d579e3e54f 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -133,6 +133,20 @@ void sev_get_policy(uint32_t *policy)
{
}
+bool kvm_memcrypt_enabled(void)
+{
+ return false;
+}
+
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
+{
+ return 1;
+}
+
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr)
+{
+}
+
#ifndef CONFIG_USER_ONLY
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bbf12a172339..4a5db5dde390 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -231,6 +231,31 @@ int kvm_destroy_vcpu(CPUState *cpu);
*/
bool kvm_arm_supports_user_irq(void);
+/**
+ * kvm_memcrypt_enabled - return boolean indicating whether memory encryption
+ * is enabled
+ * Returns: 1 memory encryption is enabled
+ * 0 memory encryption is disabled
+ */
+bool kvm_memcrypt_enabled(void);
+
+/**
+ * kvm_memcrypt_encrypt_data: encrypt the memory range
+ *
+ * Return: 1 failed to encrypt the range
+ * 0 succesfully encrypted memory region
+ */
+int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len);
+
+/**
+ * kvm_memcrypt_set_debug_ram_ops: set debug_ram_ops callback
+ *
+ * When debug_ram_ops is set, debug access to this memory region will use
+ * memory encryption APIs.
+ */
+void kvm_memcrypt_set_debug_ops(MemoryRegion *mr);
+
+
#ifdef NEED_CPU_H
#include "cpu.h"
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (10 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 12/26] kvm: introduce memory encryption APIs Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:22 ` Eric Blake
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 14/26] hmp: add 'info sev' command Brijesh Singh
` (11 subsequent siblings)
23 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The QMP query command can used to retrieve the SEV information when
memory encryption is enabled on AMD platform.
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
qapi-schema.json | 47 +++++++++++++++++++++++++++++++++++++++++++++++
qmp.c | 16 ++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/qapi-schema.json b/qapi-schema.json
index 5c06745c7927..447ebb15266e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3189,3 +3189,50 @@
# Since: 2.11
##
{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
+##
+# @SevInfo:
+#
+# Information about SEV support
+#
+# @enabled: true if SEV is active
+#
+# @api_major: SEV API major version
+#
+# @api_minor: SEV API minor version
+#
+# @build_id: SEV FW build id
+#
+# @policy: SEV policy value
+#
+# @state: SEV guest state
+#
+# Since: 2.12
+##
+{ 'struct': 'SevInfo',
+ 'data': { 'enabled': 'bool',
+ 'api_major': 'uint8',
+ 'api_minor' : 'uint8',
+ 'build_id' : 'uint8',
+ 'policy' : 'uint32',
+ 'state' : 'str'
+ }
+}
+
+##
+# @query-sev:
+#
+# Returns information about SEV
+#
+# Returns: @SevInfo
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev" }
+# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
+# "build-id" : 0, "policy" : 0, "state" : "running" } }
+#
+##
+{ 'command': 'query-sev', 'returns': 'SevInfo' }
diff --git a/qmp.c b/qmp.c
index 52cfd2d81c0f..1a5cfad09dd0 100644
--- a/qmp.c
+++ b/qmp.c
@@ -37,6 +37,7 @@
#include "qom/object_interfaces.h"
#include "hw/mem/pc-dimm.h"
#include "hw/acpi/acpi_dev_interface.h"
+#include "sysemu/sev.h"
NameInfo *qmp_query_name(Error **errp)
{
@@ -717,3 +718,18 @@ MemoryInfo *qmp_query_memory_size_summary(Error **errp)
return mem_info;
}
+
+SevInfo *qmp_query_sev(Error **errp)
+{
+ SevInfo *info = g_malloc0(sizeof(*info));
+
+ info->enabled = sev_enabled();
+ if (info->enabled) {
+ sev_get_fw_version(&info->api_major,
+ &info->api_minor, &info->build_id);
+ sev_get_policy(&info->policy);
+ sev_get_current_state(&info->state);
+ }
+
+ return info;
+}
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command Brijesh Singh
@ 2018-02-07 16:22 ` Eric Blake
2018-02-07 16:36 ` Brijesh Singh
0 siblings, 1 reply; 39+ messages in thread
From: Eric Blake @ 2018-02-07 16:22 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, kvm, Marcel Apfelbaum,
Markus Armbruster, Paolo Bonzini, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov
On 02/07/2018 10:06 AM, Brijesh Singh wrote:
> The QMP query command can used to retrieve the SEV information when
> memory encryption is enabled on AMD platform.
>
> Cc: "Daniel P. Berrangé" <berrange@redhat.com>
> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> Cc: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> +##
> +# @SevInfo:
> +#
> +# Information about SEV support
> +#
> +# @enabled: true if SEV is active
> +#
> +# @api_major: SEV API major version
New QMP structures should prefer '-' over '_'; this should be 'api-major'.
> +#
> +# @api_minor: SEV API minor version
> +#
> +# @build_id: SEV FW build id
and so on.
> +#
> +# @policy: SEV policy value
> +#
> +# @state: SEV guest state
> +#
> +# Since: 2.12
> +##
> +{ 'struct': 'SevInfo',
> + 'data': { 'enabled': 'bool',
> + 'api_major': 'uint8',
> + 'api_minor' : 'uint8',
> + 'build_id' : 'uint8',
> + 'policy' : 'uint32',
> + 'state' : 'str'
> + }
> +}
> +
> +##
> +# @query-sev:
> +#
> +# Returns information about SEV
It would be worth expanding the acronym here, for someone that is
reading the documentation but not familiar with the term.
> +#
> +# Returns: @SevInfo
> +#
> +# Since: 2.12
> +#
> +# Example:
> +#
> +# -> { "execute": "query-sev" }
> +# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0,
> +# "build-id" : 0, "policy" : 0, "state" : "running" } }
This example does not match the spelling you used in the struct above,
but DOES match what the spelling should be.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command
2018-02-07 16:22 ` Eric Blake
@ 2018-02-07 16:36 ` Brijesh Singh
0 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:36 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: brijesh.singh, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov
On 2/7/18 10:22 AM, Eric Blake wrote:
>> +#
>> +# @enabled: true if SEV is active
>> +#
>> +# @api_major: SEV API major version
>
> New QMP structures should prefer '-' over '_'; this should be
> 'api-major'.
I will fix it. thanks
....
>> +##
>> +# @query-sev:
>> +#
>> +# Returns information about SEV
>
> It would be worth expanding the acronym here, for someone that is
> reading the documentation but not familiar with the term.
>
Will do.
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 14/26] hmp: add 'info sev' command
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (11 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 13/26] qmp: add query-sev command Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 15/26] sev: add command to create launch memory encryption context Brijesh Singh
` (10 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The command can be used to show the SEV information when memory
encryption is enabled on AMD platform.
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
hmp-commands-info.hx | 14 ++++++++++++++
hmp.c | 19 +++++++++++++++++++
hmp.h | 1 +
3 files changed, 34 insertions(+)
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index ad590a4ffb2b..236811c465d2 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -865,6 +865,20 @@ STEXI
@findex info memory_size_summary
Display the amount of initially allocated and present hotpluggable (if
enabled) memory in bytes.
+ETEXI
+
+ {
+ .name = "sev",
+ .args_type = "",
+ .params = "",
+ .help = "show SEV information",
+ .cmd = hmp_info_sev,
+ },
+
+STEXI
+@item info sev
+@findex info sev
+Show SEV information.
ETEXI
STEXI
diff --git a/hmp.c b/hmp.c
index b3de32d219b5..8d5aa33a022f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2922,3 +2922,22 @@ void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict)
}
hmp_handle_error(mon, &err);
}
+
+void hmp_info_sev(Monitor *mon, const QDict *qdict)
+{
+ SevInfo *info;
+
+ info = qmp_query_sev(NULL);
+ monitor_printf(mon, "sev support: ");
+ monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
+
+ if (info->enabled) {
+ monitor_printf(mon, "state: %s\n", info->state);
+ monitor_printf(mon, "policy: 0x%x\n", info->policy);
+ monitor_printf(mon, "build id: %u\n", info->build_id);
+ monitor_printf(mon, "api version: %u.%u\n",
+ info->api_major, info->api_minor);
+ }
+
+ qapi_free_SevInfo(info);
+}
diff --git a/hmp.h b/hmp.h
index 536cb91caa4b..802e0619551d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -148,5 +148,6 @@ void hmp_info_ramblock(Monitor *mon, const QDict *qdict);
void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict);
void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict);
+void hmp_info_sev(Monitor *mon, const QDict *qdict);
#endif
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 15/26] sev: add command to create launch memory encryption context
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (12 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 14/26] hmp: add 'info sev' command Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 16/26] sev: add command to encrypt guest memory region Brijesh Singh
` (9 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The KVM_SEV_LAUNCH_START command creates a new VM encryption key (VEK).
The encryption key created with the command will be used for encrypting
the bootstrap images (such as guest bios).
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/sev.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 2 +
include/sysemu/sev.h | 10 +++++
3 files changed, 111 insertions(+)
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 2c4bbba3c367..2ecc6a1d1ad3 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -29,6 +29,17 @@ static int sev_fd;
#define SEV_FW_MAX_ERROR 0x17
+static SevGuestState current_sev_guest_state = SEV_STATE_UNINIT;
+
+static const char *const sev_state_str[] = {
+ "uninit",
+ "lupdate",
+ "secret",
+ "running",
+ "supdate",
+ "rupdate",
+};
+
static const char *const sev_fw_errlist[] = {
"",
"Platform state is invalid",
@@ -86,6 +97,16 @@ fw_error_to_str(int code)
return sev_fw_errlist[code];
}
+static void
+sev_set_guest_state(SevGuestState new_state)
+{
+ assert(new_state < SEV_STATE_MAX);
+
+ trace_kvm_sev_change_state(sev_state_str[current_sev_guest_state],
+ sev_state_str[new_state]);
+ current_sev_guest_state = new_state;
+}
+
static void
sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
{
@@ -337,6 +358,7 @@ sev_get_me_mask(void)
void
sev_get_current_state(char **state)
{
+ *state = g_strdup(sev_state_str[current_sev_guest_state]);
}
bool
@@ -355,6 +377,76 @@ sev_get_policy(uint32_t *policy)
{
}
+static int
+sev_read_file_base64(const char *filename, guchar **data, gsize *len)
+{
+ gsize sz;
+ gchar *base64;
+ GError *error = NULL;
+
+ if (!g_file_get_contents(filename, &base64, &sz, &error)) {
+ error_report("failed to read '%s' (%s)", filename, error->message);
+ return -1;
+ }
+
+ *data = g_base64_decode(base64, len);
+ return 0;
+}
+
+static int
+sev_launch_start(SEVState *s)
+{
+ gsize sz;
+ int ret = 1;
+ int fw_error;
+ QSevGuestInfo *sev = s->sev_info;
+ struct kvm_sev_launch_start *start;
+ guchar *session = NULL, *dh_cert = NULL;
+
+ start = g_malloc0(sizeof(*start));
+ if (!start) {
+ return 1;
+ }
+
+ start->handle = object_property_get_int(OBJECT(sev), "handle",
+ &error_abort);
+ start->policy = object_property_get_int(OBJECT(sev), "policy",
+ &error_abort);
+ if (sev->session_file) {
+ if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
+ return 1;
+ }
+ start->session_uaddr = (unsigned long)session;
+ start->session_len = sz;
+ }
+
+ if (sev->dh_cert_file) {
+ if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
+ return 1;
+ }
+ start->dh_uaddr = (unsigned long)dh_cert;
+ start->dh_len = sz;
+ }
+
+ trace_kvm_sev_launch_start(start->policy, session, dh_cert);
+ ret = sev_ioctl(KVM_SEV_LAUNCH_START, start, &fw_error);
+ if (ret < 0) {
+ error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
+ return 1;
+ }
+
+ object_property_set_int(OBJECT(sev), start->handle, "handle",
+ &error_abort);
+ sev_set_guest_state(SEV_STATE_LUPDATE);
+
+ g_free(start);
+ g_free(session);
+ g_free(dh_cert);
+
+ return 0;
+}
+
void *
sev_guest_init(const char *id)
{
@@ -398,6 +490,13 @@ sev_guest_init(const char *id)
goto err;
}
+ ret = sev_launch_start(s);
+ if (ret) {
+ error_report("%s: failed to create encryption context", __func__);
+ goto err;
+ }
+
+
sev_active = true;
ram_block_notifier_add(&sev_ram_notifier);
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index 364c84bd7a73..5d993ca08e5f 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -17,3 +17,5 @@ kvm_irqchip_release_virq(int virq) "virq %d"
kvm_sev_init(void) ""
kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%lu"
kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%lu"
+kvm_sev_change_state(const char *old, const char *new) "%s -> %s"
+kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 121e7e4aa44c..08014a9c94ff 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -58,6 +58,16 @@ struct QSevGuestInfoClass {
ObjectClass parent_class;
};
+typedef enum {
+ SEV_STATE_UNINIT = 0,
+ SEV_STATE_LUPDATE,
+ SEV_STATE_SECRET,
+ SEV_STATE_RUNNING,
+ SEV_STATE_SUPDATE,
+ SEV_STATE_RUPDATE,
+ SEV_STATE_MAX
+} SevGuestState;
+
struct SEVState {
QSevGuestInfo *sev_info;
};
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 16/26] sev: add command to encrypt guest memory region
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (13 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 15/26] sev: add command to create launch memory encryption context Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom Brijesh Singh
` (8 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The KVM_SEV_LAUNCH_UPDATE_DATA command is used to encrypt a guest memory
region using the VM Encryption Key created using LAUNCH_START.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/kvm-all.c | 2 ++
accel/kvm/sev.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 1 +
include/sysemu/sev.h | 1 +
4 files changed, 53 insertions(+)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f1fb826f0648..37f7c442dc3f 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1675,6 +1675,8 @@ static int kvm_init(MachineState *ms)
if (!kvm_state->memcrypt_handle) {
goto err;
}
+
+ kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
}
ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 2ecc6a1d1ad3..4414bda25509 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -97,6 +97,12 @@ fw_error_to_str(int code)
return sev_fw_errlist[code];
}
+static bool
+sev_check_state(SevGuestState state)
+{
+ return current_sev_guest_state == state ? true : false;
+}
+
static void
sev_set_guest_state(SevGuestState new_state)
{
@@ -447,6 +453,36 @@ sev_launch_start(SEVState *s)
return 0;
}
+static int
+sev_launch_update_data(uint8_t *addr, uint64_t len)
+{
+ int ret, fw_error;
+ struct kvm_sev_launch_update_data *update;
+
+ if (addr == NULL || len <= 0) {
+ return 1;
+ }
+
+ update = g_malloc0(sizeof(*update));
+ if (!update) {
+ return 1;
+ }
+
+ update->uaddr = (__u64)addr;
+ update->len = len;
+ trace_kvm_sev_launch_update_data(addr, len);
+ ret = sev_ioctl(KVM_SEV_LAUNCH_UPDATE_DATA, update, &fw_error);
+ if (ret) {
+ error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
+ goto err;
+ }
+
+err:
+ g_free(update);
+ return ret;
+}
+
void *
sev_guest_init(const char *id)
{
@@ -506,6 +542,19 @@ err:
return NULL;
}
+int
+sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
+{
+ assert(handle);
+
+ /* if SEV is in update state then encrypt the data else do nothing */
+ if (sev_check_state(SEV_STATE_LUPDATE)) {
+ return sev_launch_update_data(ptr, len);
+ }
+
+ return 0;
+}
+
static void
sev_register_types(void)
{
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index 5d993ca08e5f..bd92f868b73a 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -19,3 +19,4 @@ kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%lu"
kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%lu"
kvm_sev_change_state(const char *old, const char *new) "%s -> %s"
kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
+kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 08014a9c94ff..f7af1a00c510 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -75,6 +75,7 @@ struct SEVState {
typedef struct SEVState SEVState;
void *sev_guest_init(const char *id);
+int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
#endif
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (14 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 16/26] sev: add command to encrypt guest memory region Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-09 18:28 ` Dr. David Alan Gilbert
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 18/26] sev: add support to LAUNCH_MEASURE command Brijesh Singh
` (7 subsequent siblings)
23 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
SEV requires that guest bios must be encrypted before booting the guest.
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
hw/i386/pc_sysfw.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 6b183747fcea..8ddbbf74d330 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -112,6 +112,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
pflash_t *system_flash;
MemoryRegion *flash_mem;
char name[64];
+ void *flash_ptr;
+ int ret, flash_size;
sector_bits = 12;
sector_size = 1 << sector_bits;
@@ -168,6 +170,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
if (unit == 0) {
flash_mem = pflash_cfi01_get_memory(system_flash);
pc_isa_bios_init(rom_memory, flash_mem, size);
+
+ /* Encrypt the pflash boot ROM */
+ if (kvm_memcrypt_enabled()) {
+ flash_ptr = memory_region_get_ram_ptr(flash_mem);
+ flash_size = memory_region_size(flash_mem);
+ ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
+ if (ret) {
+ error_report("failed to encrypt pflash rom");
+ exit(1);
+ }
+ }
}
}
}
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom Brijesh Singh
@ 2018-02-09 18:28 ` Dr. David Alan Gilbert
2018-02-09 20:49 ` Brijesh Singh
0 siblings, 1 reply; 39+ messages in thread
From: Dr. David Alan Gilbert @ 2018-02-09 18:28 UTC (permalink / raw)
To: Brijesh Singh
Cc: qemu-devel, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov,
Richard Henderson
* Brijesh Singh (brijesh.singh@amd.com) wrote:
> SEV requires that guest bios must be encrypted before booting the guest.
I'm curious; is it just the main BIOS that needs encryption - what about
things like device/PXE rom images?
Dave
>
> Cc: "Michael S. Tsirkin" <mst@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Richard Henderson <rth@twiddle.net>
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> hw/i386/pc_sysfw.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> index 6b183747fcea..8ddbbf74d330 100644
> --- a/hw/i386/pc_sysfw.c
> +++ b/hw/i386/pc_sysfw.c
> @@ -112,6 +112,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
> pflash_t *system_flash;
> MemoryRegion *flash_mem;
> char name[64];
> + void *flash_ptr;
> + int ret, flash_size;
>
> sector_bits = 12;
> sector_size = 1 << sector_bits;
> @@ -168,6 +170,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
> if (unit == 0) {
> flash_mem = pflash_cfi01_get_memory(system_flash);
> pc_isa_bios_init(rom_memory, flash_mem, size);
> +
> + /* Encrypt the pflash boot ROM */
> + if (kvm_memcrypt_enabled()) {
> + flash_ptr = memory_region_get_ram_ptr(flash_mem);
> + flash_size = memory_region_size(flash_mem);
> + ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
> + if (ret) {
> + error_report("failed to encrypt pflash rom");
> + exit(1);
> + }
> + }
> }
> }
> }
> --
> 2.14.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom
2018-02-09 18:28 ` Dr. David Alan Gilbert
@ 2018-02-09 20:49 ` Brijesh Singh
0 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-09 20:49 UTC (permalink / raw)
To: Dr. David Alan Gilbert
Cc: brijesh.singh, qemu-devel, Alistair Francis,
Christian Borntraeger, Cornelia Huck, Daniel P . Berrange,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost,
Eric Blake, kvm, Marcel Apfelbaum, Markus Armbruster,
Paolo Bonzini, Peter Crosthwaite, Peter Maydell,
Richard Henderson, Stefan Hajnoczi, Thomas Lendacky,
Borislav Petkov, Richard Henderson
On 2/9/18 12:28 PM, Dr. David Alan Gilbert wrote:
> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>> SEV requires that guest bios must be encrypted before booting the guest.
> I'm curious; is it just the main BIOS that needs encryption - what about
> things like device/PXE rom images?
SEV feature is available in OVMF BIOS only. EDKII core contains UEFI
firmware driver for several things including PXE and most of time we
don't need ROMs. If we do, I think typically ROMs from which the guest
firmware reads the binaries are not guest RAM, they are MMIO. Guest
BIOSes copies the ROM from MMIO to guest RAM -- it will get encrypted
during copy (because MMIO is mapped with C=0 and guest RAM is mapped
with C=1). In other words, I don't see any need for encrypting the ROM
images during the launch flow. But passing an arbitrary option ROM can
be security concerns hence I believe a guest owner wanting to pass a
option ROM will use secure boot, then option roms can be verified before
executing.
> Dave
>
>> Cc: "Michael S. Tsirkin" <mst@redhat.com>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Richard Henderson <rth@twiddle.net>
>> Cc: Eduardo Habkost <ehabkost@redhat.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>> hw/i386/pc_sysfw.c | 13 +++++++++++++
>> 1 file changed, 13 insertions(+)
>>
>> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
>> index 6b183747fcea..8ddbbf74d330 100644
>> --- a/hw/i386/pc_sysfw.c
>> +++ b/hw/i386/pc_sysfw.c
>> @@ -112,6 +112,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
>> pflash_t *system_flash;
>> MemoryRegion *flash_mem;
>> char name[64];
>> + void *flash_ptr;
>> + int ret, flash_size;
>>
>> sector_bits = 12;
>> sector_size = 1 << sector_bits;
>> @@ -168,6 +170,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
>> if (unit == 0) {
>> flash_mem = pflash_cfi01_get_memory(system_flash);
>> pc_isa_bios_init(rom_memory, flash_mem, size);
>> +
>> + /* Encrypt the pflash boot ROM */
>> + if (kvm_memcrypt_enabled()) {
>> + flash_ptr = memory_region_get_ram_ptr(flash_mem);
>> + flash_size = memory_region_size(flash_mem);
>> + ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size);
>> + if (ret) {
>> + error_report("failed to encrypt pflash rom");
>> + exit(1);
>> + }
>> + }
>> }
>> }
>> }
>> --
>> 2.14.3
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 18/26] sev: add support to LAUNCH_MEASURE command
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (15 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 17/26] target/i386: encrypt bios rom Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 19/26] sev: Finalize the SEV guest launch flow Brijesh Singh
` (6 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
During machine creation we encrypted the guest bios image, the
LAUNCH_MEASURE command can be used to retrieve the measurement of
the encrypted memory region. 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.
VM management tools like libvirt can query the measurement using
query-launch-measure QMP command.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/sev.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 1 +
accel/stubs/kvm-stub.c | 5 ++++
include/sysemu/sev.h | 2 ++
4 files changed, 75 insertions(+)
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 4414bda25509..8d99c6cda4d2 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -19,6 +19,7 @@
#include "sysemu/sev.h"
#include "sysemu/sysemu.h"
#include "trace.h"
+#include "qapi-event.h"
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
#define DEFAULT_SEV_DEVICE "/dev/sev"
@@ -26,6 +27,7 @@
static uint64_t me_mask;
static bool sev_active;
static int sev_fd;
+static SEVState *sev_state;
#define SEV_FW_MAX_ERROR 0x17
@@ -483,6 +485,68 @@ err:
return ret;
}
+static void
+sev_launch_get_measure(Notifier *notifier, void *unused)
+{
+ int ret, error;
+ guchar *data;
+ SEVState *s = sev_state;
+ struct kvm_sev_launch_measure *measurement;
+
+ if (!sev_check_state(SEV_STATE_LUPDATE)) {
+ return;
+ }
+
+ measurement = g_malloc0(sizeof(*measurement));
+ if (!measurement) {
+ return;
+ }
+
+ /* query the measurement blob length */
+ ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+ if (!measurement->len) {
+ error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+ __func__, ret, error, fw_error_to_str(errno));
+ goto free_measurement;
+ }
+
+ data = g_malloc(measurement->len);
+ if (s->measurement) {
+ goto free_data;
+ }
+
+ measurement->uaddr = (unsigned long)data;
+
+ /* get the measurement blob */
+ ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error);
+ if (ret) {
+ error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
+ __func__, ret, error, fw_error_to_str(errno));
+ goto free_data;
+ }
+
+ sev_set_guest_state(SEV_STATE_SECRET);
+
+ /* encode the measurement value and emit the event */
+ s->measurement = g_base64_encode(data, measurement->len);
+ trace_kvm_sev_launch_measurement(s->measurement);
+
+free_data:
+ g_free(data);
+free_measurement:
+ g_free(measurement);
+}
+
+char *
+sev_get_launch_measurement(void)
+{
+ return g_strdup(sev_state->measurement);
+}
+
+static Notifier sev_machine_done_notify = {
+ .notify = sev_launch_get_measure,
+};
+
void *
sev_guest_init(const char *id)
{
@@ -535,6 +599,9 @@ sev_guest_init(const char *id)
sev_active = true;
ram_block_notifier_add(&sev_ram_notifier);
+ qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+
+ sev_state = s;
return s;
err:
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index bd92f868b73a..19742bf9dd30 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -20,3 +20,4 @@ kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%lu"
kvm_sev_change_state(const char *old, const char *new) "%s -> %s"
kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64
+kvm_sev_launch_measurement(const char *value) "data %s"
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index e7d579e3e54f..d0f1aa6d6f9a 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -133,6 +133,11 @@ void sev_get_policy(uint32_t *policy)
{
}
+char *sev_get_launch_measurement(void)
+{
+ return NULL;
+}
+
bool kvm_memcrypt_enabled(void)
{
return false;
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index f7af1a00c510..c173ad33f8bb 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -30,6 +30,7 @@ extern uint64_t sev_get_me_mask(void);
extern void sev_get_current_state(char **state);
extern void sev_get_fw_version(uint8_t *major, uint8_t *minor, uint8_t *build);
extern void sev_get_policy(uint32_t *policy);
+extern char *sev_get_launch_measurement(void);
typedef struct QSevGuestInfo QSevGuestInfo;
typedef struct QSevGuestInfoClass QSevGuestInfoClass;
@@ -70,6 +71,7 @@ typedef enum {
struct SEVState {
QSevGuestInfo *sev_info;
+ gchar *measurement;
};
typedef struct SEVState SEVState;
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 19/26] sev: Finalize the SEV guest launch flow
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (16 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 18/26] sev: add support to LAUNCH_MEASURE command Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 20/26] hw: i386: set ram_debug_ops when memory encryption is enabled Brijesh Singh
` (5 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
SEV launch flow requires us to issue LAUNCH_FINISH command before guest
is ready to run.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/sev.c | 29 +++++++++++++++++++++++++++++
accel/kvm/trace-events | 1 +
2 files changed, 30 insertions(+)
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 8d99c6cda4d2..e422f43caa0b 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -547,6 +547,34 @@ static Notifier sev_machine_done_notify = {
.notify = sev_launch_get_measure,
};
+static void
+sev_launch_finish(SEVState *s)
+{
+ int ret, error;
+
+ trace_kvm_sev_launch_finish();
+ ret = sev_ioctl(KVM_SEV_LAUNCH_FINISH, 0, &error);
+ if (ret) {
+ error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
+ __func__, ret, error, fw_error_to_str(error));
+ exit(1);
+ }
+
+ sev_set_guest_state(SEV_STATE_RUNNING);
+}
+
+static void
+sev_vm_state_change(void *opaque, int running, RunState state)
+{
+ SEVState *s = opaque;
+
+ if (running) {
+ if (!sev_check_state(SEV_STATE_RUNNING)) {
+ sev_launch_finish(s);
+ }
+ }
+}
+
void *
sev_guest_init(const char *id)
{
@@ -600,6 +628,7 @@ sev_guest_init(const char *id)
sev_active = true;
ram_block_notifier_add(&sev_ram_notifier);
qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
+ qemu_add_vm_change_state_handler(sev_vm_state_change, s);
sev_state = s;
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index 19742bf9dd30..e810d75ea1b3 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -21,3 +21,4 @@ kvm_sev_change_state(const char *old, const char *new) "%s -> %s"
kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64
kvm_sev_launch_measurement(const char *value) "data %s"
+kvm_sev_launch_finish(void) ""
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 20/26] hw: i386: set ram_debug_ops when memory encryption is enabled
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (17 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 19/26] sev: Finalize the SEV guest launch flow Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 21/26] sev: add debug encrypt and decrypt commands Brijesh Singh
` (4 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
When memory encryption is enabled, the guest RAM and boot flash ROM will
contain the encrypted data. By setting the debug ops allow us to invoke
encryption APIs when accessing the memory for the debug purposes.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
hw/i386/pc.c | 9 +++++++++
hw/i386/pc_sysfw.c | 6 ++++++
2 files changed, 15 insertions(+)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ccc50baa85e0..ba451c0dc520 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1357,6 +1357,15 @@ void pc_memory_init(PCMachineState *pcms,
e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
}
+ /*
+ * When memory encryption is enabled, the guest RAM will be encrypted with
+ * a guest unique key. Set the debug ops so that any debug access to the
+ * guest RAM will go through the memory encryption APIs.
+ */
+ if (kvm_memcrypt_enabled()) {
+ kvm_memcrypt_set_debug_ops(ram);
+ }
+
if (!pcmc->has_reserved_memory &&
(machine->ram_slots ||
(machine->maxram_size > machine->ram_size))) {
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 8ddbbf74d330..3d149b1c9f3c 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -180,6 +180,12 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
error_report("failed to encrypt pflash rom");
exit(1);
}
+
+ /*
+ * The pflash ROM is encrypted, set the debug ops so that any
+ * debug accesses will use memory encryption APIs.
+ */
+ kvm_memcrypt_set_debug_ops(flash_mem);
}
}
}
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 21/26] sev: add debug encrypt and decrypt commands
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (18 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 20/26] hw: i386: set ram_debug_ops when memory encryption is enabled Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 22/26] target/i386: clear C-bit when walking SEV guest page table Brijesh Singh
` (3 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
KVM_SEV_DBG_DECRYPT and KVM_SEV_DBG_ENCRYPT commands are used for
decrypting and encrypting guest memory region. The command works only if
the guest policy allows the debugging.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/kvm-all.c | 1 +
accel/kvm/sev.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
accel/kvm/trace-events | 1 +
include/sysemu/sev.h | 1 +
4 files changed, 75 insertions(+)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 37f7c442dc3f..7d3b7b4107eb 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1677,6 +1677,7 @@ static int kvm_init(MachineState *ms)
}
kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
+ kvm_state->memcrypt_debug_ops = sev_set_debug_ops;
}
ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index e422f43caa0b..7b57575e2f93 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -23,11 +23,13 @@
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
#define DEFAULT_SEV_DEVICE "/dev/sev"
+#define GUEST_POLICY_DBG_BIT 0x1
static uint64_t me_mask;
static bool sev_active;
static int sev_fd;
static SEVState *sev_state;
+static MemoryRegionRAMReadWriteOps sev_ops;
#define SEV_FW_MAX_ERROR 0x17
@@ -575,6 +577,51 @@ sev_vm_state_change(void *opaque, int running, RunState state)
}
}
+static int
+sev_dbg_enc_dec(uint8_t *dst, const uint8_t *src, uint32_t len, bool write)
+{
+ int ret, error;
+ struct kvm_sev_dbg *dbg;
+
+ dbg = g_malloc0(sizeof(*dbg));
+ if (!dbg) {
+ return 1;
+ }
+
+ dbg->src_uaddr = (unsigned long)src;
+ dbg->dst_uaddr = (unsigned long)dst;
+ dbg->len = len;
+
+ trace_kvm_sev_debug(write ? "encrypt" : "decrypt", src, dst, len);
+ ret = sev_ioctl(write ? KVM_SEV_DBG_ENCRYPT : KVM_SEV_DBG_DECRYPT,
+ dbg, &error);
+ if (ret) {
+ error_report("%s (%s) %#llx->%#llx+%#x ret=%d fw_error=%d '%s'",
+ __func__, write ? "write" : "read", dbg->src_uaddr,
+ dbg->dst_uaddr, dbg->len, ret, error,
+ fw_error_to_str(error));
+ }
+
+ g_free(dbg);
+ return ret;
+}
+
+static int
+sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+ assert(attrs.debug);
+
+ return sev_dbg_enc_dec(dst, src, len, false);
+}
+
+static int
+sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+ assert(attrs.debug);
+
+ return sev_dbg_enc_dec(dst, src, len, true);
+}
+
void *
sev_guest_init(const char *id)
{
@@ -651,6 +698,31 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
return 0;
}
+void
+sev_set_debug_ops(void *handle, MemoryRegion *mr)
+{
+ int policy;
+ SEVState *s = (SEVState *)handle;
+
+ policy = object_property_get_int(OBJECT(s->sev_info),
+ "policy", &error_abort);
+
+ /*
+ * Check if guest policy supports debugging
+ * Bit 0 :
+ * 0 - debug allowed
+ * 1 - debug is not allowed
+ */
+ if (policy & GUEST_POLICY_DBG_BIT) {
+ return;
+ }
+
+ sev_ops.read = sev_mem_read;
+ sev_ops.write = sev_mem_write;
+
+ memory_region_set_ram_debug_ops(mr, &sev_ops);
+}
+
static void
sev_register_types(void)
{
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index e810d75ea1b3..de6a12c51e06 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -22,3 +22,4 @@ kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session
kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64
kvm_sev_launch_measurement(const char *value) "data %s"
kvm_sev_launch_finish(void) ""
+kvm_sev_debug(const char *op, const uint8_t *src, uint8_t *dst, int len) "(%s) src %p dst %p len %d"
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index c173ad33f8bb..186ebca0f945 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -78,6 +78,7 @@ typedef struct SEVState SEVState;
void *sev_guest_init(const char *id);
int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
+void sev_set_debug_ops(void *handle, MemoryRegion *mr);
#endif
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 22/26] target/i386: clear C-bit when walking SEV guest page table
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (19 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 21/26] sev: add debug encrypt and decrypt commands Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 23/26] include: add psp-sev.h header file Brijesh Singh
` (2 subsequent siblings)
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh,
Richard Henderson
In SEV-enabled guest the pte entry will have C-bit set, we need to
clear the C-bit when walking the page table.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
target/i386/helper.c | 31 +++++++++++++----------
target/i386/monitor.c | 69 +++++++++++++++++++++++++++++++++------------------
2 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 5dc9e8839bc8..999154e21e80 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -21,6 +21,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
#include "kvm_i386.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h"
@@ -732,6 +733,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
int32_t a20_mask;
uint32_t page_offset;
int page_size;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
a20_mask = x86_get_a20_mask(env);
if (!(env->cr[0] & CR0_PG_MASK)) {
@@ -755,25 +759,25 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
if (la57) {
- pml5e_addr = ((env->cr[3] & ~0xfff) +
+ pml5e_addr = ((env->cr[3] & ~0xfff & me_mask) +
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
- pml5e = ldq_phys_debug(cs, pml5e_addr);
+ pml5e = ldq_phys_debug(cs, pml5e_addr) & me_mask;
if (!(pml5e & PG_PRESENT_MASK)) {
return -1;
}
} else {
- pml5e = env->cr[3];
+ pml5e = env->cr[3] & me_mask;
}
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
- pml4e = ldq_phys_debug(cs, pml4e_addr);
+ pml4e = ldq_phys_debug(cs, pml4e_addr) & me_mask;
if (!(pml4e & PG_PRESENT_MASK)) {
return -1;
}
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
(((addr >> 30) & 0x1ff) << 3)) & a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
+ pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
if (!(pdpe & PG_PRESENT_MASK)) {
return -1;
}
@@ -786,16 +790,16 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
} else
#endif
{
- pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
- a20_mask;
- pdpe = ldq_phys_debug(cs, pdpe_addr);
+ pdpe_addr = ((env->cr[3] & ~0x1f & me_mask) + ((addr >> 27) & 0x18))
+ & a20_mask;
+ pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
if (!(pdpe & PG_PRESENT_MASK))
return -1;
}
pde_addr = ((pdpe & PG_ADDRESS_MASK) +
(((addr >> 21) & 0x1ff) << 3)) & a20_mask;
- pde = ldq_phys_debug(cs, pde_addr);
+ pde = ldq_phys_debug(cs, pde_addr) & me_mask;
if (!(pde & PG_PRESENT_MASK)) {
return -1;
}
@@ -808,7 +812,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pte_addr = ((pde & PG_ADDRESS_MASK) +
(((addr >> 12) & 0x1ff) << 3)) & a20_mask;
page_size = 4096;
- pte = ldq_phys_debug(cs, pte_addr);
+ pte = ldq_phys_debug(cs, pte_addr) & me_mask;
}
if (!(pte & PG_PRESENT_MASK)) {
return -1;
@@ -817,8 +821,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
uint32_t pde;
/* page directory entry */
- pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
- pde = ldl_phys_debug(cs, pde_addr);
+ pde_addr = ((env->cr[3] & ~0xfff & me_mask) + ((addr >> 20) & 0xffc))
+ & a20_mask;
+ pde = ldl_phys_debug(cs, pde_addr) & me_mask;
if (!(pde & PG_PRESENT_MASK))
return -1;
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -827,7 +832,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
} else {
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
- pte = ldl_phys_debug(cs, pte_addr);
+ pte = ldl_phys_debug(cs, pte_addr) & me_mask;
if (!(pte & PG_PRESENT_MASK)) {
return -1;
}
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 63f7125ba885..44ae31d13bfa 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"
@@ -93,16 +94,20 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
unsigned int l1, l2, l3;
uint64_t pdpe, pde, pte;
uint64_t pdp_addr, pd_addr, pt_addr;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
pdp_addr = env->cr[3] & ~0x1f;
+ pdp_addr &= me_mask;
for (l1 = 0; l1 < 4; l1++) {
cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
+ pdpe = le64_to_cpu(pdpe & me_mask);
if (pdpe & PG_PRESENT_MASK) {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
+ pde = le64_to_cpu(pde & me_mask);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
/* 2M pages with PAE, CR4.PSE is ignored */
@@ -113,7 +118,7 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
for (l3 = 0; l3 < 512; l3++) {
cpu_physical_memory_read_debug(pt_addr + l3 * 8,
&pte, 8);
- pte = le64_to_cpu(pte);
+ pte = le64_to_cpu(pte & me_mask);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, env, (l1 << 30) + (l2 << 21)
+ (l3 << 12),
@@ -135,10 +140,13 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
uint64_t l1, l2, l3, l4;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pdp_addr, pd_addr, pt_addr;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
for (l1 = 0; l1 < 512; l1++) {
cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
+ pml4e = le64_to_cpu(pml4e & me_mask);
if (!(pml4e & PG_PRESENT_MASK)) {
continue;
}
@@ -146,7 +154,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
+ pdpe = le64_to_cpu(pdpe & me_mask);
if (!(pdpe & PG_PRESENT_MASK)) {
continue;
}
@@ -161,7 +169,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
+ pde = le64_to_cpu(pde & me_mask);
if (!(pde & PG_PRESENT_MASK)) {
continue;
}
@@ -176,7 +184,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env,
pt_addr = pde & 0x3fffffffff000ULL;
for (l4 = 0; l4 < 512; l4++) {
cpu_physical_memory_read_debug(pt_addr + l4 * 8, &pte, 8);
- pte = le64_to_cpu(pte);
+ pte = le64_to_cpu(pte & me_mask);
if (pte & PG_PRESENT_MASK) {
print_pte(mon, env, (l0 << 48) + (l1 << 39) +
(l2 << 30) + (l3 << 21) + (l4 << 12),
@@ -193,11 +201,14 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env)
uint64_t l0;
uint64_t pml5e;
uint64_t pml5_addr;
+ uint64_t me_mask;
- pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+ me_mask = sev_get_me_mask();
+
+ pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
for (l0 = 0; l0 < 512; l0++) {
cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
- pml5e = le64_to_cpu(pml5e);
+ pml5e = le64_to_cpu(pml5e & me_mask);
if (pml5e & PG_PRESENT_MASK) {
tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
}
@@ -225,7 +236,8 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
if (env->cr[4] & CR4_LA57_MASK) {
tlb_info_la57(mon, env);
} else {
- tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL);
+ tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL &
+ sev_get_me_mask());
}
} else
#endif
@@ -309,19 +321,22 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
uint64_t pdpe, pde, pte;
uint64_t pdp_addr, pd_addr, pt_addr;
hwaddr start, end;
+ uint64_t me_mask;
- pdp_addr = env->cr[3] & ~0x1f;
+ me_mask = sev_get_me_mask();
+
+ pdp_addr = env->cr[3] & ~0x1f & me_mask;
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 4; l1++) {
cpu_physical_memory_read_debug(pdp_addr + l1 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
+ pdpe = le64_to_cpu(pdpe & me_mask);
end = l1 << 30;
if (pdpe & PG_PRESENT_MASK) {
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
cpu_physical_memory_read_debug(pd_addr + l2 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
+ pde = le64_to_cpu(pde & me_mask);
end = (l1 << 30) + (l2 << 21);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
@@ -333,7 +348,7 @@ static void mem_info_pae32(Monitor *mon, CPUArchState *env)
for (l3 = 0; l3 < 512; l3++) {
cpu_physical_memory_read_debug(pt_addr + l3 * 8,
&pte, 8);
- pte = le64_to_cpu(pte);
+ pte = le64_to_cpu(pte & me_mask);
end = (l1 << 30) + (l2 << 21) + (l3 << 12);
if (pte & PG_PRESENT_MASK) {
prot = pte & pde & (PG_USER_MASK | PG_RW_MASK |
@@ -366,19 +381,22 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
uint64_t l1, l2, l3, l4;
uint64_t pml4e, pdpe, pde, pte;
uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
- pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+ pml4_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
last_prot = 0;
start = -1;
for (l1 = 0; l1 < 512; l1++) {
cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
+ pml4e = le64_to_cpu(pml4e & me_mask);
end = l1 << 39;
if (pml4e & PG_PRESENT_MASK) {
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
+ pdpe = le64_to_cpu(pdpe & me_mask);
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
@@ -391,7 +409,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
for (l3 = 0; l3 < 512; l3++) {
cpu_physical_memory_read_debug(pd_addr + l3 * 8,
&pde, 8);
- pde = le64_to_cpu(pde);
+ pde = le64_to_cpu(pde & me_mask);
end = (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
if (pde & PG_PSE_MASK) {
@@ -405,7 +423,7 @@ static void mem_info_la48(Monitor *mon, CPUArchState *env)
cpu_physical_memory_read_debug(pt_addr
+ l4 * 8,
&pte, 8);
- pte = le64_to_cpu(pte);
+ pte = le64_to_cpu(pte & me_mask);
end = (l1 << 39) + (l2 << 30) +
(l3 << 21) + (l4 << 12);
if (pte & PG_PRESENT_MASK) {
@@ -444,13 +462,16 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
uint64_t l0, l1, l2, l3, l4;
uint64_t pml5e, pml4e, pdpe, pde, pte;
uint64_t pml5_addr, pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
- pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
+ pml5_addr = env->cr[3] & 0x3fffffffff000ULL & me_mask;
last_prot = 0;
start = -1;
for (l0 = 0; l0 < 512; l0++) {
cpu_physical_memory_read_debug(pml5_addr + l0 * 8, &pml5e, 8);
- pml5e = le64_to_cpu(pml5e);
+ pml5e = le64_to_cpu(pml5e & me_mask);
end = l0 << 48;
if (!(pml5e & PG_PRESENT_MASK)) {
prot = 0;
@@ -461,7 +482,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pml4_addr = pml5e & 0x3fffffffff000ULL;
for (l1 = 0; l1 < 512; l1++) {
cpu_physical_memory_read_debug(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
+ pml4e = le64_to_cpu(pml4e & me_mask);
end = (l0 << 48) + (l1 << 39);
if (!(pml4e & PG_PRESENT_MASK)) {
prot = 0;
@@ -472,7 +493,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pdp_addr = pml4e & 0x3fffffffff000ULL;
for (l2 = 0; l2 < 512; l2++) {
cpu_physical_memory_read_debug(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
+ pdpe = le64_to_cpu(pdpe & me_mask);
end = (l0 << 48) + (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
prot = 0;
@@ -491,7 +512,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
pd_addr = pdpe & 0x3fffffffff000ULL;
for (l3 = 0; l3 < 512; l3++) {
cpu_physical_memory_read_debug(pd_addr + l3 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
+ pde = le64_to_cpu(pde & me_mask);
end = (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21);
if (pde & PG_PRESENT_MASK) {
prot = 0;
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 23/26] include: add psp-sev.h header file
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (20 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 22/26] target/i386: clear C-bit when walking SEV guest page table Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 25/26] sev: add support to KVM_SEV_GUEST_STATUS Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command Brijesh Singh
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The header file provide the ioctl command and structure to communicate
with /dev/sev device.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
| 142 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 142 insertions(+)
create mode 100644 linux-headers/linux/psp-sev.h
--git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h
new file mode 100644
index 000000000000..33e247471ae0
--- /dev/null
+++ b/linux-headers/linux/psp-sev.h
@@ -0,0 +1,142 @@
+/*
+ * Userspace interface for AMD Secure Encrypted Virtualization (SEV)
+ * platform management commands.
+ *
+ * Copyright (C) 2016-2017 Advanced Micro Devices, Inc.
+ *
+ * Author: Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * SEV spec 0.14 is available at:
+ * http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PSP_SEV_USER_H__
+#define __PSP_SEV_USER_H__
+
+#include <linux/types.h>
+
+/**
+ * SEV platform commands
+ */
+enum {
+ SEV_FACTORY_RESET = 0,
+ SEV_PLATFORM_STATUS,
+ SEV_PEK_GEN,
+ SEV_PEK_CSR,
+ SEV_PDH_GEN,
+ SEV_PDH_CERT_EXPORT,
+ SEV_PEK_CERT_IMPORT,
+
+ SEV_MAX,
+};
+
+/**
+ * SEV Firmware status code
+ */
+typedef enum {
+ SEV_RET_SUCCESS = 0,
+ SEV_RET_INVALID_PLATFORM_STATE,
+ SEV_RET_INVALID_GUEST_STATE,
+ SEV_RET_INAVLID_CONFIG,
+ SEV_RET_INVALID_LEN,
+ SEV_RET_ALREADY_OWNED,
+ SEV_RET_INVALID_CERTIFICATE,
+ SEV_RET_POLICY_FAILURE,
+ SEV_RET_INACTIVE,
+ SEV_RET_INVALID_ADDRESS,
+ SEV_RET_BAD_SIGNATURE,
+ SEV_RET_BAD_MEASUREMENT,
+ SEV_RET_ASID_OWNED,
+ SEV_RET_INVALID_ASID,
+ SEV_RET_WBINVD_REQUIRED,
+ SEV_RET_DFFLUSH_REQUIRED,
+ SEV_RET_INVALID_GUEST,
+ SEV_RET_INVALID_COMMAND,
+ SEV_RET_ACTIVE,
+ SEV_RET_HWSEV_RET_PLATFORM,
+ SEV_RET_HWSEV_RET_UNSAFE,
+ SEV_RET_UNSUPPORTED,
+ SEV_RET_MAX,
+} sev_ret_code;
+
+/**
+ * struct sev_user_data_status - PLATFORM_STATUS command parameters
+ *
+ * @major: major API version
+ * @minor: minor API version
+ * @state: platform state
+ * @flags: platform config flags
+ * @build: firmware build id for API version
+ * @guest_count: number of active guests
+ */
+struct sev_user_data_status {
+ __u8 api_major; /* Out */
+ __u8 api_minor; /* Out */
+ __u8 state; /* Out */
+ __u32 flags; /* Out */
+ __u8 build; /* Out */
+ __u32 guest_count; /* Out */
+} __attribute__((packed));
+
+/**
+ * struct sev_user_data_pek_csr - PEK_CSR command parameters
+ *
+ * @address: PEK certificate chain
+ * @length: length of certificate
+ */
+struct sev_user_data_pek_csr {
+ __u64 address; /* In */
+ __u32 length; /* In/Out */
+} __attribute__((packed));
+
+/**
+ * struct sev_user_data_cert_import - PEK_CERT_IMPORT command parameters
+ *
+ * @pek_address: PEK certificate chain
+ * @pek_len: length of PEK certificate
+ * @oca_address: OCA certificate chain
+ * @oca_len: length of OCA certificate
+ */
+struct sev_user_data_pek_cert_import {
+ __u64 pek_cert_address; /* In */
+ __u32 pek_cert_len; /* In */
+ __u64 oca_cert_address; /* In */
+ __u32 oca_cert_len; /* In */
+} __attribute__((packed));
+
+/**
+ * struct sev_user_data_pdh_cert_export - PDH_CERT_EXPORT command parameters
+ *
+ * @pdh_address: PDH certificate address
+ * @pdh_len: length of PDH certificate
+ * @cert_chain_address: PDH certificate chain
+ * @cert_chain_len: length of PDH certificate chain
+ */
+struct sev_user_data_pdh_cert_export {
+ __u64 pdh_cert_address; /* In */
+ __u32 pdh_cert_len; /* In/Out */
+ __u64 cert_chain_address; /* In */
+ __u32 cert_chain_len; /* In/Out */
+} __attribute__((packed));
+
+/**
+ * struct sev_issue_cmd - SEV ioctl parameters
+ *
+ * @cmd: SEV commands to execute
+ * @opaque: pointer to the command structure
+ * @error: SEV FW return code on failure
+ */
+struct sev_issue_cmd {
+ __u32 cmd; /* In */
+ __u64 data; /* In */
+ __u32 error; /* Out */
+} __attribute__((packed));
+
+#define SEV_IOC_TYPE 'S'
+#define SEV_ISSUE_CMD _IOWR(SEV_IOC_TYPE, 0x0, struct sev_issue_cmd)
+
+#endif /* __PSP_USER_SEV_H */
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 25/26] sev: add support to KVM_SEV_GUEST_STATUS
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (21 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 23/26] include: add psp-sev.h header file Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command Brijesh Singh
23 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The command is used to query the current SEV guest status. We use this
command to query the guest policy for QMP query-sev command.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
accel/kvm/sev.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c
index 186834364eed..b149f4ae6441 100644
--- a/accel/kvm/sev.c
+++ b/accel/kvm/sev.c
@@ -418,6 +418,18 @@ sev_get_fw_version(uint8_t *major, uint8_t *minor, uint8_t *build)
void
sev_get_policy(uint32_t *policy)
{
+ struct kvm_sev_guest_status status = {};
+ int r, err;
+
+ r = sev_ioctl(KVM_SEV_GUEST_STATUS, &status, &err);
+ if (r) {
+ error_report("%s: failed to get platform status ret=%d "
+ "fw_error='%d: %s'", __func__, r, err,
+ fw_error_to_str(err));
+ return;
+ }
+
+ *policy = status.policy;
}
static int
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command
2018-02-07 16:06 [Qemu-devel] [PATCH v7 01/26] memattrs: add debug attribute Brijesh Singh
` (22 preceding siblings ...)
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 25/26] sev: add support to KVM_SEV_GUEST_STATUS Brijesh Singh
@ 2018-02-07 16:06 ` Brijesh Singh
2018-02-07 16:29 ` Eric Blake
23 siblings, 1 reply; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, Eric Blake, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov, Brijesh Singh
The command can be used by libvirt to retrieve the measurement of SEV guest.
This measurement is a signature of the memory contents that was encrypted
through the LAUNCH_UPDATE_DATA.
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
qapi-schema.json | 30 ++++++++++++++++++++++++++++++
qmp.c | 14 ++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/qapi-schema.json b/qapi-schema.json
index 447ebb15266e..19331bff8883 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3236,3 +3236,33 @@
#
##
{ 'command': 'query-sev', 'returns': 'SevInfo' }
+
+##
+# @SevLaunchMeasureInfo:
+#
+# SEV Guest Launch measurement information
+#
+# @data: the measurement value encoded in base64
+#
+# Since: 2.12
+#
+# Notes: If measurement is not available then a null measurement is returned.
+##
+{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} }
+
+##
+# @query-sev-launch-measure:
+#
+# Query the SEV guest launch information.
+#
+# Returns: The @SevLaunchMeasureInfo for the guest
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-sev-launch-measure" }
+# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+#
+##
+{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo' }
diff --git a/qmp.c b/qmp.c
index 1a5cfad09dd0..5fb19b9d0db3 100644
--- a/qmp.c
+++ b/qmp.c
@@ -733,3 +733,17 @@ SevInfo *qmp_query_sev(Error **errp)
return info;
}
+
+SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
+{
+ SevLaunchMeasureInfo *info = NULL;
+
+ if (sev_enabled()) {
+ info = g_malloc0(sizeof(*info));
+ info->data = sev_get_launch_measurement();
+ } else {
+ error_setg(errp, "SEV is not enabled");
+ }
+
+ return info;
+}
--
2.14.3
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command
2018-02-07 16:06 ` [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command Brijesh Singh
@ 2018-02-07 16:29 ` Eric Blake
2018-02-07 18:12 ` Brijesh Singh
0 siblings, 1 reply; 39+ messages in thread
From: Eric Blake @ 2018-02-07 16:29 UTC (permalink / raw)
To: Brijesh Singh, qemu-devel
Cc: Alistair Francis, Christian Borntraeger, Cornelia Huck,
Daniel P . Berrange, Dr. David Alan Gilbert, Michael S. Tsirkin,
Edgar E. Iglesias, Eduardo Habkost, kvm, Marcel Apfelbaum,
Markus Armbruster, Paolo Bonzini, Peter Crosthwaite,
Peter Maydell, Richard Henderson, Stefan Hajnoczi,
Thomas Lendacky, Borislav Petkov
On 02/07/2018 10:06 AM, Brijesh Singh wrote:
> The command can be used by libvirt to retrieve the measurement of SEV guest.
> This measurement is a signature of the memory contents that was encrypted
> through the LAUNCH_UPDATE_DATA.
>
> Cc: "Daniel P. Berrangé" <berrange@redhat.com>
> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> Cc: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> qapi-schema.json | 30 ++++++++++++++++++++++++++++++
> qmp.c | 14 ++++++++++++++
> 2 files changed, 44 insertions(+)
>
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 447ebb15266e..19331bff8883 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3236,3 +3236,33 @@
> #
> ##
> { 'command': 'query-sev', 'returns': 'SevInfo' }
> +
> +##
> +# @SevLaunchMeasureInfo:
> +#
> +# SEV Guest Launch measurement information
> +#
> +# @data: the measurement value encoded in base64
> +#
> +# Since: 2.12
> +#
> +# Notes: If measurement is not available then a null measurement is returned.
Null measurement, as in empty string? Would it be better to have
query-sev-launch-measure return an error instead of an
SevLaunchMeasureInfo with a null measurement in that case?
> +##
> +{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} }
> +
> +##
> +# @query-sev-launch-measure:
> +#
> +# Query the SEV guest launch information.
> +#
> +# Returns: The @SevLaunchMeasureInfo for the guest
> +#
> +# Since: 2.12
> +#
> +# Example:
> +#
> +# -> { "execute": "query-sev-launch-measure" }
> +# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
> +#
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH v7 26/26] qmp: add query-sev-launch-measure command
2018-02-07 16:29 ` Eric Blake
@ 2018-02-07 18:12 ` Brijesh Singh
0 siblings, 0 replies; 39+ messages in thread
From: Brijesh Singh @ 2018-02-07 18:12 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: brijesh.singh, Alistair Francis, Christian Borntraeger,
Cornelia Huck, Daniel P . Berrange, Dr. David Alan Gilbert,
Michael S. Tsirkin, Edgar E. Iglesias, Eduardo Habkost, kvm,
Marcel Apfelbaum, Markus Armbruster, Paolo Bonzini,
Peter Crosthwaite, Peter Maydell, Richard Henderson,
Stefan Hajnoczi, Thomas Lendacky, Borislav Petkov
On 02/07/2018 10:29 AM, Eric Blake wrote:
...
>> +#
>> +# Since: 2.12
>> +#
>> +# Notes: If measurement is not available then a null measurement is
>> returned.
>
> Null measurement, as in empty string? Would it be better to have
> query-sev-launch-measure return an error instead of an
> SevLaunchMeasureInfo with a null measurement in that case?
>
Yes, an empty string when measurement is not available. I can certainly
change it to return an error when measurement is not available.
>> +##
>> +{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} }
>> +
>> +##
>> +# @query-sev-launch-measure:
>> +#
>> +# Query the SEV guest launch information.
>> +#
>> +# Returns: The @SevLaunchMeasureInfo for the guest
>> +#
>> +# Since: 2.12
>> +#
>> +# Example:
>> +#
>> +# -> { "execute": "query-sev-launch-measure" }
>> +# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
>> +#
>
>
^ permalink raw reply [flat|nested] 39+ messages in thread