From: Xiao Guangrong <guangrong.xiao@linux.intel.com>
To: pbonzini@redhat.com, imammedo@redhat.com
Cc: Xiao Guangrong <guangrong.xiao@linux.intel.com>,
ehabkost@redhat.com, kvm@vger.kernel.org, mst@redhat.com,
gleb@kernel.org, mtosatti@redhat.com, qemu-devel@nongnu.org,
stefanha@redhat.com, dan.j.williams@intel.com, rth@twiddle.net
Subject: [Qemu-devel] [PATCH 6/6] nvdimm acpi: emulate dsm method
Date: Tue, 5 Jan 2016 02:52:08 +0800 [thread overview]
Message-ID: <1451933528-133684-7-git-send-email-guangrong.xiao@linux.intel.com> (raw)
In-Reply-To: <1451933528-133684-1-git-send-email-guangrong.xiao@linux.intel.com>
Emulate dsm method after IO VM-exit
Currently, we only introduce the framework and no function is actually
supported
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
hw/acpi/aml-build.c | 2 +-
hw/acpi/nvdimm.c | 83 ++++++++++++++++++++++++++++++++++++++++++++-
include/hw/acpi/aml-build.h | 1 +
include/hw/mem/nvdimm.h | 17 ++++++++++
4 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index e65171f..5a7644a 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -231,7 +231,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 dfccbc0..7be9857 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -390,12 +390,80 @@ 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)
{
+ AcpiNVDIMMState *state = opaque;
+ NvdimmDsmIn *in;
+ hwaddr dsm_mem_addr;
+ GArray *out;
+ uint32_t buf_size;
+
+ nvdimm_debug("write address %#lx value %#lx.\n", addr, val);
+
+ if (size != sizeof(uint32_t)) {
+ fprintf(stderr, "BUG: invalid IO bit width %#x.\n", size);
+ return;
+ }
+
+ switch (addr) {
+ case 0:
+ state->low_dsm_mem_addr = val;
+ return;
+ case sizeof(uint32_t):
+ state->high_dsm_mem_addr = val;
+ break;
+ default:
+ fprintf(stderr, "BUG: IO access address %#lx is not dword"
+ " aligned.\n", addr);
+ return;
+ };
+
+ dsm_mem_addr = state->low_dsm_mem_addr;
+ dsm_mem_addr |= (hwaddr)state->high_dsm_mem_addr << (sizeof(uint32_t) *
+ BITS_PER_BYTE);
+ nvdimm_debug("dsm 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);
+ g_free(in);
+ g_array_free(out, true);
}
static const MemoryRegionOps nvdimm_dsm_ops = {
@@ -408,6 +476,17 @@ static const MemoryRegionOps nvdimm_dsm_ops = {
},
};
+static const VMStateDescription nvdimm_acpi_vmstate = {
+ .name = "nvdimm_acpi_vmstate",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(low_dsm_mem_addr, AcpiNVDIMMState),
+ VMSTATE_UINT32(high_dsm_mem_addr, AcpiNVDIMMState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
FWCfgState *fw_cfg, Object *owner)
{
@@ -419,6 +498,8 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
acpi_data_push(state->dsm_mem, TARGET_PAGE_SIZE);
fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
state->dsm_mem->len);
+
+ vmstate_register(NULL, 0, &nvdimm_acpi_vmstate, state);
}
#define NVDIMM_GET_DSM_MEM "MEMA"
@@ -430,7 +511,7 @@ static void nvdimm_build_common_dsm(Aml *dev)
Aml *result_size, *dsm_mem;
uint8_t byte_list[1];
- method = aml_method(NVDIMM_COMMON_DSM, 4, AML_NOTSERIALIZED);
+ method = aml_method(NVDIMM_COMMON_DSM, 4, AML_SERIALIZED);
function = aml_arg(2);
dsm_mem = aml_arg(3);
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 6c1816e..2fa8daa 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -354,6 +354,7 @@ Aml *aml_derefof(Aml *arg);
Aml *aml_sizeof(Aml *arg);
Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
+void build_append_int_noprefix(GArray *table, uint64_t value, int size);
void
build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index d908d6a..5f312a1 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -25,6 +25,14 @@
#include "hw/mem/pc-dimm.h"
+#define NVDIMM_DEBUG 0
+#define nvdimm_debug(fmt, ...) \
+ do { \
+ if (NVDIMM_DEBUG) { \
+ fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
#define TYPE_NVDIMM "nvdimm"
#define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem"
@@ -38,12 +46,21 @@
* @is_enabled: detect if NVDIMM support is enabled.
*
* @dsm_mem: the data of the fw_cfg file NVDIMM_DSM_MEM_FILE.
+ *
+ * The dsm memory is allocated by BIOS and patched into ACPI binary code.
+ * @low_dsm_mem_addr: the low 32 bits of DSM memory.
+ * @high_dsm_mem_addr: the high 32 bits of DSM memory.
+ *
* @io_mr: the IO region used by OSPM to transfer control to QEMU.
*/
struct AcpiNVDIMMState {
bool is_enabled;
GArray *dsm_mem;
+
+ uint32_t low_dsm_mem_addr;
+ uint32_t high_dsm_mem_addr;
+
MemoryRegion io_mr;
};
typedef struct AcpiNVDIMMState AcpiNVDIMMState;
--
1.8.3.1
next prev parent reply other threads:[~2016-01-04 18:59 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-04 18:52 [Qemu-devel] [PATCH 0/6] NVDIMM ACPI: introduce the framework of QEMU emulated DSM Xiao Guangrong
2016-01-04 18:52 ` [Qemu-devel] [PATCH 1/6] pc: acpi: bump DSDT/SSDT compliance revision to v2 Xiao Guangrong
2016-01-04 18:52 ` [Qemu-devel] [PATCH 2/6] nvdimm acpi: initialize the resource used by NVDIMM ACPI Xiao Guangrong
2016-01-04 18:52 ` [Qemu-devel] [PATCH 3/6] nvdimm acpi: introduce patched dsm memory Xiao Guangrong
2016-01-06 15:23 ` Igor Mammedov
2016-01-06 15:39 ` Xiao Guangrong
2016-01-07 11:04 ` Igor Mammedov
2016-01-08 3:40 ` Xiao Guangrong
2016-01-08 17:06 ` Igor Mammedov
2016-01-04 18:52 ` [Qemu-devel] [PATCH 4/6] acpi: allow using acpi named offset for OperationRegion Xiao Guangrong
2016-01-04 18:52 ` [Qemu-devel] [PATCH 5/6] nvdimm acpi: let qemu handle _DSM method Xiao Guangrong
2016-01-07 14:22 ` Igor Mammedov
2016-01-08 4:01 ` Xiao Guangrong
2016-01-08 16:08 ` Igor Mammedov
2016-01-04 18:52 ` Xiao Guangrong [this message]
2016-01-07 14:13 ` [Qemu-devel] [PATCH 0/6] NVDIMM ACPI: introduce the framework of QEMU emulated DSM Igor Mammedov
2016-01-12 19:02 ` Xiao Guangrong
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=1451933528-133684-7-git-send-email-guangrong.xiao@linux.intel.com \
--to=guangrong.xiao@linux.intel.com \
--cc=dan.j.williams@intel.com \
--cc=ehabkost@redhat.com \
--cc=gleb@kernel.org \
--cc=imammedo@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=mst@redhat.com \
--cc=mtosatti@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--cc=stefanha@redhat.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).