f3c3b22dd7
- Add AMD SEV (Secure Encrypted Virtualization) support by taking the v7 series of the patches posted to qemu ml. (fate#322124) - Update python3 related patches now that they are upstream OBS-URL: https://build.opensuse.org/request/show/574394 OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=390
231 lines
8.4 KiB
Diff
231 lines
8.4 KiB
Diff
From faf4862946a9e236e8e4fb956adad2dc11577fe0 Mon Sep 17 00:00:00 2001
|
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
|
Date: Tue, 6 Feb 2018 19:08:07 -0600
|
|
Subject: [PATCH] exec: add ram_debug_ops support
|
|
|
|
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>
|
|
[BR: FATE#322124]
|
|
Signed-off-by: Bruce Rogers <brogers@suse.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 1ca0f9e0ab..5da6a782e1 100644
|
|
--- a/exec.c
|
|
+++ b/exec.c
|
|
@@ -2983,7 +2983,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);
|
|
}
|
|
|
|
@@ -3081,7 +3085,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) {
|
|
@@ -3151,11 +3159,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;
|
|
@@ -3170,12 +3180,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:
|
|
@@ -3194,7 +3225,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)
|
|
@@ -3209,8 +3241,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 {
|
|
@@ -3516,6 +3550,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) {
|
|
@@ -3525,6 +3560,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;
|
|
@@ -3532,14 +3571,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 5ed4042f87..557f75c7ae 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 {
|
|
@@ -620,6 +633,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.
|