qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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



  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).