From: Damien Hedde <damien.hedde@greensocs.com>
To: qemu-devel@nongnu.org
Cc: Damien Hedde <damien.hedde@greensocs.com>,
ehabkost@redhat.com, mark.burton@greensocs.com,
armbru@redhat.com, sakisp@xilinx.com, edgari@xilinx.com,
crosa@redhat.com, pbonzini@redhat.com, luc.michel@greensocs.com,
rth@twiddle.net
Subject: [Qemu-devel] [RFC PATCH 1/5] introduce [p]mem(read|write) qmp commands
Date: Fri, 28 Jun 2019 14:45:30 +0200 [thread overview]
Message-ID: <20190628124534.10679-2-damien.hedde@greensocs.com> (raw)
In-Reply-To: <20190628124534.10679-1-damien.hedde@greensocs.com>
This introduces memread, memwrite, pmemread and pmemwrite qmp commands.
The memread and memwrite read virtual memory from a given cpu point of
view. If no cpu index is specified, the cpu-id 0 is used.
The pmemread and pmemwrite directly read physical memory.
The data is passed/returned in a list of bytes. The maximum length is set to 8, they can be used to 64bits.
This is based on the work of Frederic Konrad.
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
cpus.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++
qapi/misc.json | 119 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 245 insertions(+)
diff --git a/cpus.c b/cpus.c
index 1af51b73dd..7aae35c098 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2484,3 +2484,129 @@ void dump_drift_info(void)
qemu_printf("Max guest advance NA\n");
}
}
+
+static Bytes *memread(int64_t addr, int64_t size, CPUState *cpu, Error **errp)
+{
+ uint32_t l = 0;
+ uint8List *prev = NULL;
+ Bytes *res;
+ uint8_t buf[8];
+
+ if (size <= 0 || size > sizeof(buf)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "size",
+ "out of range");
+ return NULL;
+ }
+
+ if (cpu) {
+ if (cpu_memory_rw_debug(cpu, addr, buf, size, 0) != 0) {
+ error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64
+ " specified", addr, size);
+ return NULL;
+ }
+ } else {
+ MemTxResult r = address_space_read(&address_space_memory, addr,
+ MEMTXATTRS_UNSPECIFIED, buf, l);
+ if (r != MEMTX_OK) {
+ error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64
+ " specified", addr, size);
+ return NULL;
+ }
+ }
+
+ res = g_new0(Bytes, 1);
+ while (l < size) {
+ uint8List *cur = g_new0(uint8List, 1);
+ cur->value = buf[l++];
+ if (!prev) {
+ res->bytes = cur;
+ } else {
+ prev->next = cur;
+ }
+ prev = cur;
+ }
+
+ return res;
+
+}
+
+Bytes *qmp_memread(int64_t addr, int64_t size,
+ bool has_cpu, int64_t cpu_index, Error **errp)
+{
+ CPUState *cpu;
+
+ if (!has_cpu) {
+ cpu_index = 0;
+ }
+
+ cpu = qemu_get_cpu(cpu_index);
+ if (cpu == NULL) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+ "a CPU number");
+ return NULL;
+ }
+
+ return memread(addr, size, cpu, errp);
+}
+
+Bytes *qmp_pmemread(int64_t addr, int64_t size, Error **errp)
+{
+ return memread(addr, size, NULL, errp);
+}
+
+static void memwrite(int64_t addr, uint8List *bytes, CPUState *cpu,
+ Error **errp)
+{
+ uint32_t l = 0;
+ uint8_t buf[8];
+
+ while (bytes != NULL) {
+ if (l >= sizeof(buf)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "bytes",
+ "too long");
+ return;
+ }
+ buf[l++] = bytes->value;
+ bytes = bytes->next;
+ }
+
+ if (cpu) {
+ if (cpu_memory_rw_debug(cpu, addr, buf, l, 1) != 0) {
+ error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRIu32
+ " specified", addr, l);
+ return;
+ }
+ } else {
+ MemTxResult r = address_space_write(&address_space_memory, addr,
+ MEMTXATTRS_UNSPECIFIED, buf, l);
+ if (r != MEMTX_OK) {
+ error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64
+ " specified", addr, size);
+ return;
+ }
+ }
+}
+
+void qmp_memwrite(int64_t addr, uint8List *bytes,
+ bool has_cpu, int64_t cpu_index, Error **errp)
+{
+ CPUState *cpu;
+
+ if (!has_cpu) {
+ cpu_index = 0;
+ }
+
+ cpu = qemu_get_cpu(cpu_index);
+ if (cpu == NULL) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+ "a CPU number");
+ return;
+ }
+
+ memwrite(addr, bytes, cpu, errp);
+}
+
+void qmp_pmemwrite(int64_t addr, uint8List *bytes, Error **errp)
+{
+ memwrite(addr, bytes, NULL, errp);
+}
diff --git a/qapi/misc.json b/qapi/misc.json
index dc4cf9da20..3aca91b4ac 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -3047,3 +3047,122 @@
'data': 'NumaOptions',
'allow-preconfig': true
}
+
+##
+# @Bytes:
+#
+# An array of bytes.
+#
+# @bytes: the list of bytes
+#
+# Since: 4.1
+##
+{ 'struct': 'Bytes', 'data': {'bytes': ['uint8'] } }
+
+##
+# @memread:
+#
+# Read a portion of guest memory.
+#
+# @addr: the virtual address of the guest to read from
+#
+# @size: the size of memory region to read (max is 8)
+#
+# @cpu-index: the index of the virtual CPU to use for translating the
+# virtual address (defaults to CPU 0)
+#
+# Returns: The read bytes
+#
+# Since: 4.1
+#
+# Example:
+#
+# -> { "execute": "memread",
+# "arguments": { "addr": 10,
+# "size": 4 } }
+# <- { "return": { 'bytes' : [10, 78, 231, 7] } }
+#
+##
+{ 'command': 'memread',
+ 'data': {'addr': 'int', 'size': 'int', '*cpu-index': 'int'},
+ 'returns' : 'Bytes'
+}
+
+##
+# @memwrite:
+#
+# Write a portion of guest memory.
+#
+# @addr: the virtual address of the guest to write to
+#
+# @bytes: the bytes to write into memory region (max length is 8)
+#
+# @cpu-index: the index of the virtual CPU to use for translating the
+# virtual address (defaults to CPU 0)
+#
+# Since: 4.1
+#
+# Returns: nothing on success.
+#
+# Example:
+#
+# -> { "execute": "memread",
+# "arguments": { "addr": 10,
+# "bytes": [10, 78, 231, 7] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'memwrite',
+ 'data': {'addr': 'int', 'bytes': ['uint8'], '*cpu-index': 'int'}
+}
+
+##
+# @pmemread:
+#
+# Read a portion of guest memory.
+#
+# @addr: the physical address of the guest to read from
+#
+# @size: the size of memory region to read (max is 8)
+#
+# Returns: The read bytes
+#
+# Since: 4.1
+#
+# Example:
+#
+# -> { "execute": "memread",
+# "arguments": { "addr": 10,
+# "size": 4 } }
+# <- { "return": { 'bytes' : [10, 78, 231, 7] } }
+#
+##
+{ 'command': 'pmemread',
+ 'data': {'addr': 'int', 'size': 'int'},
+ 'returns' : 'Bytes'
+}
+
+##
+# @pmemwrite:
+#
+# Write a portion of guest memory.
+#
+# @addr: the physical address of the guest to write to
+#
+# @bytes: the bytes to write into memory region (max length is 8)
+#
+# Since: 4.1
+#
+# Returns: nothing on success.
+#
+# Example:
+#
+# -> { "execute": "memread",
+# "arguments": { "addr": 10,
+# "bytes": [10, 78, 231, 7] } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'pmemwrite',
+ 'data': {'addr': 'int', 'bytes': ['uint8']}
+}
--
2.22.0
next prev parent reply other threads:[~2019-06-28 13:12 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-28 12:45 [Qemu-devel] [RFC PATCH 0/5] FAULT INJECTION FRAMEWORK Damien Hedde
2019-06-28 12:45 ` Damien Hedde [this message]
2019-06-28 12:45 ` [Qemu-devel] [RFC PATCH 2/5] introduce a qmp command to set gpios Damien Hedde
2019-06-28 12:45 ` [Qemu-devel] [RFC PATCH 3/5] add qmp time-notify event triggering system Damien Hedde
2019-06-28 12:45 ` [Qemu-devel] [RFC PATCH 4/5] fault_injection: introduce Python scripting framework Damien Hedde
2019-06-28 12:45 ` [Qemu-devel] [RFC PATCH 5/5] docs: add fault injection framework documentation Damien Hedde
2019-07-01 8:37 ` [Qemu-devel] [RFC PATCH 0/5] FAULT INJECTION FRAMEWORK Stefan Hajnoczi
2019-07-01 10:16 ` Philippe Mathieu-Daudé
2019-07-03 9:29 ` Stefan Hajnoczi
2019-07-03 15:47 ` Damien Hedde
2019-07-09 13:42 ` Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190628124534.10679-2-damien.hedde@greensocs.com \
--to=damien.hedde@greensocs.com \
--cc=armbru@redhat.com \
--cc=crosa@redhat.com \
--cc=edgari@xilinx.com \
--cc=ehabkost@redhat.com \
--cc=luc.michel@greensocs.com \
--cc=mark.burton@greensocs.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--cc=sakisp@xilinx.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).