2018-02-22 23:01:24 +01:00
|
|
|
From a8955ac9aa33e2d3edb4ea948d74cf52fc9771a2 Mon Sep 17 00:00:00 2001
|
2018-02-08 20:55:31 +01:00
|
|
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
2018-02-22 23:01:24 +01:00
|
|
|
Date: Thu, 15 Feb 2018 09:03:19 -0600
|
2018-02-08 20:55:31 +01:00
|
|
|
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>
|
|
|
|
---
|
2018-02-22 23:01:24 +01:00
|
|
|
exec.c | 43 ++++++++++++++++++++++++++++++++-----------
|
|
|
|
include/exec/memory.h | 30 +++++++++++++++++++++++++++++-
|
|
|
|
2 files changed, 61 insertions(+), 12 deletions(-)
|
2018-02-08 20:55:31 +01:00
|
|
|
|
|
|
|
diff --git a/exec.c b/exec.c
|
2018-02-22 23:01:24 +01:00
|
|
|
index 1ca0f9e0ab..fe49807f58 100644
|
2018-02-08 20:55:31 +01:00
|
|
|
--- 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) {
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3155,7 +3163,8 @@ enum write_rom_type {
|
2018-02-08 20:55:31 +01:00
|
|
|
};
|
|
|
|
|
2018-02-22 23:01:24 +01:00
|
|
|
static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
|
2018-02-08 20:55:31 +01:00
|
|
|
- hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
|
2018-02-22 23:01:24 +01:00
|
|
|
+ hwaddr addr, const uint8_t *buf, int len, MemTxAttrs attrs,
|
2018-02-08 20:55:31 +01:00
|
|
|
+ enum write_rom_type type)
|
|
|
|
{
|
|
|
|
hwaddr l;
|
|
|
|
uint8_t *ptr;
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3175,7 +3184,11 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
|
2018-02-08 20:55:31 +01:00
|
|
|
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
|
|
switch (type) {
|
|
|
|
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:
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3194,7 +3207,9 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
|
2018-02-08 20:55:31 +01:00
|
|
|
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);
|
2018-02-22 23:01:24 +01:00
|
|
|
+ cpu_physical_memory_write_rom_internal(as, addr, buf, len,
|
|
|
|
+ MEMTXATTRS_UNSPECIFIED,
|
|
|
|
+ WRITE_DATA);
|
2018-02-08 20:55:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_flush_icache_range(hwaddr start, int len)
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3209,8 +3224,9 @@ void cpu_flush_icache_range(hwaddr start, int len)
|
2018-02-08 20:55:31 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- cpu_physical_memory_write_rom_internal(&address_space_memory,
|
|
|
|
- start, NULL, len, FLUSH_CACHE);
|
2018-02-22 23:01:24 +01:00
|
|
|
+ cpu_physical_memory_write_rom_internal(&address_space_memory, start, NULL,
|
|
|
|
+ len, MEMTXATTRS_UNSPECIFIED,
|
|
|
|
+ FLUSH_CACHE);
|
2018-02-08 20:55:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3525,6 +3541,10 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
2018-02-08 20:55:31 +01:00
|
|
|
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;
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -3533,13 +3553,14 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
2018-02-08 20:55:31 +01:00
|
|
|
l = len;
|
|
|
|
phys_addr += (addr & ~TARGET_PAGE_MASK);
|
2018-02-22 23:01:24 +01:00
|
|
|
if (is_write) {
|
2018-02-08 20:55:31 +01:00
|
|
|
- cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
|
|
|
|
- phys_addr, buf, l);
|
2018-02-22 23:01:24 +01:00
|
|
|
+ cpu_physical_memory_write_rom_internal(cpu->cpu_ases[asidx].as,
|
|
|
|
+ phys_addr, buf, l, attrs,
|
|
|
|
+ WRITE_DATA);
|
|
|
|
} else {
|
|
|
|
address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
|
2018-02-08 20:55:31 +01:00
|
|
|
- MEMTXATTRS_UNSPECIFIED,
|
|
|
|
- buf, l, 0);
|
2018-02-22 23:01:24 +01:00
|
|
|
+ attrs, buf, l, 0);
|
|
|
|
}
|
|
|
|
+
|
2018-02-08 20:55:31 +01:00
|
|
|
len -= l;
|
|
|
|
buf += l;
|
|
|
|
addr += l;
|
|
|
|
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
2018-02-22 23:01:24 +01:00
|
|
|
index 5ed4042f87..8d3b99cba8 100644
|
2018-02-08 20:55:31 +01:00
|
|
|
--- 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.
|
2018-02-22 23:01:24 +01:00
|
|
|
@@ -1928,7 +1956,7 @@ MemTxResult flatview_read(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
|
|
|
|
void *ptr;
|
|
|
|
MemoryRegion *mr;
|
|
|
|
|
|
|
|
- if (__builtin_constant_p(len)) {
|
|
|
|
+ if (__builtin_constant_p(len) && !attrs.debug) {
|
|
|
|
if (len) {
|
|
|
|
rcu_read_lock();
|
|
|
|
l = len;
|