qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 8/9] nvdimm acpi: emulate dsm method


From: Xiao Guangrong
Subject: Re: [Qemu-devel] [PATCH 8/9] nvdimm acpi: emulate dsm method
Date: Wed, 2 Mar 2016 12:00:42 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1



On 03/02/2016 01:12 AM, Michael S. Tsirkin wrote:
On Tue, Mar 01, 2016 at 06:56:10PM +0800, Xiao Guangrong wrote:
Emulate dsm method after IO VM-exit

Currently, we only introduce the framework and no function is actually
supported

Signed-off-by: Xiao Guangrong <address@hidden>
---
  hw/acpi/aml-build.c         |  2 +-
  hw/acpi/nvdimm.c            | 44 ++++++++++++++++++++++++++++++++++++++++++++
  include/hw/acpi/aml-build.h |  1 +
  include/hw/mem/nvdimm.h     |  8 ++++++++
  4 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ab89ca6..da11bf8 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -227,7 +227,7 @@ static void build_extop_package(GArray *package, uint8_t op)
      build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
  }

-static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+void build_append_int_noprefix(GArray *table, uint64_t value, int size)
  {
      int i;

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 781f6c1..e0b483a 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -393,12 +393,56 @@ typedef struct NvdimmDsmOut NvdimmDsmOut;
  static uint64_t
  nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
  {
+    fprintf(stderr, "BUG: we never read _DSM IO Port.\n");
      return 0;
  }

  static void
  nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
  {
+    NvdimmDsmIn *in;
+    GArray *out;
+    uint32_t buf_size;
+    hwaddr dsm_mem_addr = val;
+
+    nvdimm_debug("dsm memory address %#lx.\n", dsm_mem_addr);
+
+    /*
+     * The DSM memory is mapped to guest address space so an evil guest
+     * can change its content while we are doing DSM emulation. Avoid
+     * this by copying DSM memory to QEMU local memory.
+     */
+    in = g_malloc(TARGET_PAGE_SIZE);
+    cpu_physical_memory_read(dsm_mem_addr, in, TARGET_PAGE_SIZE);
+
+    le32_to_cpus(&in->revision);
+    le32_to_cpus(&in->function);
+    le32_to_cpus(&in->handle);
+
+    nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
+                 in->handle, in->function);
+
+    out = g_array_new(false, true /* clear */, 1);
+
+    /*
+     * function 0 is called to inquire what functions are supported by
+     * OSPM
+     */
+    if (in->function == 0) {
+        build_append_int_noprefix(out, 0 /* No function Supported */,
+                                  sizeof(uint8_t));
+    } else {
+        /* No function is supported yet. */
+        build_append_int_noprefix(out, 1 /* Not Supported */,
+                                  sizeof(uint8_t));
+    }
+
+    buf_size = cpu_to_le32(out->len);
+    cpu_physical_memory_write(dsm_mem_addr, &buf_size, sizeof(buf_size));
+    cpu_physical_memory_write(dsm_mem_addr + sizeof(buf_size), out->data,
+                              out->len);

BTW, how do we know buffer is big enough? Add assert here?

I planed to do it when we introduce the real handler of NVDIMM command, but yes,
it is better doing it in this patchset. Will follow it in the next version.


Also, you have a packed structure with the layout, correct?
Can't you use that instead of open-coding it?


Okay, how about do it like this:

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index a6359cc..2812f7a 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -401,7 +401,7 @@ static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
     NvdimmDsmIn *in;
-    GArray *out;
+    NvdimmDsmOut *out;
     uint32_t buf_size;
     hwaddr dsm_mem_addr = val;

@@ -422,27 +422,33 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, 
unsigned size)
     nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
                  in->handle, in->function);

-    out = g_array_new(false, true /* clear */, 1);
+    out = g_malloc(TARGET_PAGE_SIZE);
+
+    out->len = sizeof(out);

     /*
      * function 0 is called to inquire what functions are supported by
      * OSPM
      */
     if (in->function == 0) {
-        build_append_int_noprefix(out, 0 /* No function Supported */,
-                                  sizeof(uint8_t));
+        /* No function Supported */
+        uint32_t cmd_list = cpu_to_le32(0);
+
+        out->len += sizeof(cmd_list);
     } else {
-        /* No function is supported yet. */
-        build_append_int_noprefix(out, 1 /* Not Supported */,
-                                  sizeof(uint8_t));
+        /* Not Supported */
+        uint32_t status =  cpu_to_le32(1);
+
+        out->len = sizeof(status);
     }

-    buf_size = cpu_to_le32(out->len);
-    cpu_physical_memory_write(dsm_mem_addr, &buf_size, sizeof(buf_size));
-    cpu_physical_memory_write(dsm_mem_addr + sizeof(buf_size), out->data,
-                              out->len);
+    buf_size = out->len;
+    assert(buf_size <= TARGET_PAGE_SIZE);
+
+    out->len = cpu_to_le32(out->len);
+    cpu_physical_memory_write(dsm_mem_addr, out, buf_size);
     g_free(in);
-    g_array_free(out, true);
+    g_free(out);
 }

 static const MemoryRegionOps nvdimm_dsm_ops = {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]