All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
  2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-18 17:15     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 17:15 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 08:54:09AM +0800, Xiao Guangrong wrote:
> +typedef struct nfit_spa nfit_spa;

There are still multiple coding style violations.  Pls fix all code to
match coding style.  I commented on this before.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
@ 2015-10-18 17:15     ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 17:15 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 08:54:09AM +0800, Xiao Guangrong wrote:
> +typedef struct nfit_spa nfit_spa;

There are still multiple coding style violations.  Pls fix all code to
match coding style.  I commented on this before.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-18 17:16     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 17:16 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> Check if the input Arg3 is valid then store it into dsm_in if needed
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 7e99889..b211b8b 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>  
>      method = aml_method_serialized("NCAL", 4);
>      {
> +        Aml *ifctx;
> +
>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
>  
> +        /* Arg3 is passed as Package and it has one element? */
> +        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> +                                         aml_int(4)),
> +                               aml_equal(aml_sizeof(aml_arg(3)),
> +                                         aml_int(1))));
> +        {
> +            /* Local0 = Index(Arg3, 0) */
> +            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> +                                        aml_local(0)));
> +            /* Local3 = DeRefOf(Local0) */
> +            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> +                                        aml_local(3)));
> +            /* ARG3 = Local3 */
> +            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> +        }
> +        aml_append(method, ifctx);
> +
>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
>  
>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));

I commented on this patch on v3.
It doesn't look like this was addressed.

> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-18 17:16     ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 17:16 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> Check if the input Arg3 is valid then store it into dsm_in if needed
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 7e99889..b211b8b 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>  
>      method = aml_method_serialized("NCAL", 4);
>      {
> +        Aml *ifctx;
> +
>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
>  
> +        /* Arg3 is passed as Package and it has one element? */
> +        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> +                                         aml_int(4)),
> +                               aml_equal(aml_sizeof(aml_arg(3)),
> +                                         aml_int(1))));
> +        {
> +            /* Local0 = Index(Arg3, 0) */
> +            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> +                                        aml_local(0)));
> +            /* Local3 = DeRefOf(Local0) */
> +            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> +                                        aml_local(3)));
> +            /* ARG3 = Local3 */
> +            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> +        }
> +        aml_append(method, ifctx);
> +
>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
>  
>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));

I commented on this patch on v3.
It doesn't look like this was addressed.

> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-18 18:05     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 18:05 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
> 
> Function 0 is a query function. We do not support any function on root
> device and only 3 functions are support for NVDIMM device,
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
> access device's Label Namespace
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 182 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index b211b8b..37fea1c 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>      return nvdimm_slot_to_spa_index(slot) + 1;
>  }
>  
> +static NVDIMMDevice
> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
> +{
> +    for (; list; list = list->next) {
> +        NVDIMMDevice *nvdimm = list->data;
> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
> +                                           NULL);
> +
> +        if (nvdimm_slot_to_handle(slot) == handle) {
> +            return nvdimm;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
>  /*
>   * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>   * Structure
> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>  /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>  #define NOTIFY_VALUE      0x99

Again, please prefix everything consistently.

>  
> +enum {
> +    DSM_FUN_IMPLEMENTED = 0,
> +
> +    /* NVDIMM Root Device Functions */
> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
> +
> +    /* NVDIMM Device (non-root) Functions */
> +    DSM_DEV_FUN_SMART = 1,
> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
> +};

Does FUN stand for "function"? FUNC or FN is probably better.

Please list exact names as they appear in spec so
they can be searched for.



> +
> +enum {
> +    /* Common return status codes. */
> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
> +
> +    /* NVDIMM Root Device _DSM function return status codes*/
> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
> +                                                        Error */
> +
> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
> +};
> +
> +/* Current revision supported by DSM specification is 1. */
> +#define DSM_REVISION        (1)
> +
> +/*
> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
> + * Value Information:

Drop "please refer to".

> + *   if set to zero, no functions are supported (other than function zero)
> + *   for the specified UUID and Revision ID. If set to one, at least one
> + *   additional function is supported.
> + */
> +
> +/* do not support any function on root. */
> +#define ROOT_SUPPORT_FUN     (0ULL)

Needs a name that implies the comment somehow.

> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
> +

I think it's best to just drop these macros.
There's a single point of use - just add a comment there
explaining what does it mean.
You will be able to drop all _FUN_ macros too.


>  struct dsm_in {
>      uint32_t handle;
>      uint32_t revision;
> @@ -420,6 +490,11 @@ struct dsm_in {
>  } QEMU_PACKED;
>  typedef struct dsm_in dsm_in;
>  
> +struct cmd_out_implemented {
> +    uint64_t cmd_list;
> +};
> +typedef struct cmd_out_implemented cmd_out_implemented;
> +
>  struct dsm_out {
>      /* the size of buffer filled by QEMU. */
>      uint32_t len;
> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>      return 0;
>  }
>  
> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
> +{
> +    /* status locates in the first 4 bytes in the dsm memory. */

located?

> +    assert(!out->len);


But dsm itself can be part of a bigger table.
So don't do it.

> +
> +    status = cpu_to_le32(status);
> +    g_array_append_vals(out, &status, sizeof(status));

I think this should just use the (unfortunately named)
build_append_int_noprefix. Same applied everywhere
where you add single values.

> +}
> +
> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
> +{
> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
> +
> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> +    if (in->function == DSM_FUN_IMPLEMENTED) {
> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);

see about about single use values.


> +
> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> +        return;
> +    }
> +
> +    nvdimm_debug("Return status %#x.\n", status);
> +    nvdimm_dsm_write_status(out, status);
> +}
> +
> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
> +{
> +    GSList *list = nvdimm_get_plugged_device_list();
> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
> +    uint64_t cmd_list;
> +
> +    if (!nvdimm) {
> +        goto set_status_free;
> +    }
> +
> +    switch (in->function) {
> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> +    case DSM_FUN_IMPLEMENTED:
> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> +        goto free;
> +    default:
> +        status = DSM_STATUS_NOT_SUPPORTED;
> +    };
> +
> +set_status_free:
> +    nvdimm_debug("Return status %#x.\n", status);
> +    nvdimm_dsm_write_status(out, status);
> +free:
> +    g_slist_free(list);
> +}
> +
>  static void
>  nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>  {
> +    NVDIMMState *state = opaque;
> +    MemoryRegion *dsm_ram_mr;
> +    dsm_in *in;
> +    GArray *out;
> +    void *dsm_ram_addr;


Why don't you give this the correct type? Will avoid need for casts.

> +
>      if (val != NOTIFY_VALUE) {
>          fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>      }
> +
> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
> +                                    getpagesize()).mr;
> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);


This needs a validity check for size.

> +
> +    /*
> +     * copy all input data to our local memory to avoid potential issue
> +     * as the dsm memory is visible to guest.

this comment doesn't help.
pls replace "potential issue" with an explanation.

> +     */
> +    in = g_malloc(memory_region_size(dsm_ram_mr));
> +    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
> +
> +    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);
> +
> +    if (in->revision != DSM_REVISION) {
> +        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
> +                      in->revision, DSM_REVISION);
> +        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
> +        goto exit;
> +    }
> +
> +    /* Handle 0 is reserved for NVDIMM Root Device. */
> +    if (!in->handle) {
> +        nvdimm_dsm_write_root(in, out);
> +        goto exit;
> +    }
> +
> +    nvdimm_dsm_write_nvdimm(in, out);
> +
> +exit:
> +    /* Write our output result to dsm memory. */
> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> +    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);

This breaks migration as memory is not dirtied.

address_space_write is generally preferable to change memory.



> +
> +    g_free(in);
> +    g_array_free(out, true);
> +    memory_region_unref(dsm_ram_mr);
>  }
>  
>  static const MemoryRegionOps nvdimm_dsm_ops = {
> @@ -547,7 +725,8 @@ static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
>           */
>          BUILD_DSM_METHOD(dev, method,
>                           handle /* NVDIMM Device Handle */,
> -                         3 /* Invalid Input Parameters */,
> +                         DSM_DEV_STATUS_INVALID_PARAS, /* error code if UUID
> +                                                         is not matched. */
>                           "4309AC30-0D11-11E4-9191-0800200C9A66"
>                           /* UUID for NVDIMM Devices. */);
>  
> @@ -669,7 +848,8 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>       */
>      BUILD_DSM_METHOD(dev, method,
>                       0 /* 0 is reserved for NVDIMM Root Device*/,
> -                     2 /* Invalid Input Parameters */,
> +                     DSM_ROOT_DEV_STATUS_INVALID_PARAS, /* error code if
> +                                                     UUID is not matched. */
>                       "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
>                       /* UUID for NVDIMM Root Devices. */);
>  
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-18 18:05     ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-18 18:05 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
> 
> Function 0 is a query function. We do not support any function on root
> device and only 3 functions are support for NVDIMM device,
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
> access device's Label Namespace
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 182 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index b211b8b..37fea1c 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>      return nvdimm_slot_to_spa_index(slot) + 1;
>  }
>  
> +static NVDIMMDevice
> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
> +{
> +    for (; list; list = list->next) {
> +        NVDIMMDevice *nvdimm = list->data;
> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
> +                                           NULL);
> +
> +        if (nvdimm_slot_to_handle(slot) == handle) {
> +            return nvdimm;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
>  /*
>   * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>   * Structure
> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>  /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>  #define NOTIFY_VALUE      0x99

Again, please prefix everything consistently.

>  
> +enum {
> +    DSM_FUN_IMPLEMENTED = 0,
> +
> +    /* NVDIMM Root Device Functions */
> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
> +
> +    /* NVDIMM Device (non-root) Functions */
> +    DSM_DEV_FUN_SMART = 1,
> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
> +};

Does FUN stand for "function"? FUNC or FN is probably better.

Please list exact names as they appear in spec so
they can be searched for.



> +
> +enum {
> +    /* Common return status codes. */
> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
> +
> +    /* NVDIMM Root Device _DSM function return status codes*/
> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
> +                                                        Error */
> +
> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
> +};
> +
> +/* Current revision supported by DSM specification is 1. */
> +#define DSM_REVISION        (1)
> +
> +/*
> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
> + * Value Information:

Drop "please refer to".

> + *   if set to zero, no functions are supported (other than function zero)
> + *   for the specified UUID and Revision ID. If set to one, at least one
> + *   additional function is supported.
> + */
> +
> +/* do not support any function on root. */
> +#define ROOT_SUPPORT_FUN     (0ULL)

Needs a name that implies the comment somehow.

> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
> +

I think it's best to just drop these macros.
There's a single point of use - just add a comment there
explaining what does it mean.
You will be able to drop all _FUN_ macros too.


>  struct dsm_in {
>      uint32_t handle;
>      uint32_t revision;
> @@ -420,6 +490,11 @@ struct dsm_in {
>  } QEMU_PACKED;
>  typedef struct dsm_in dsm_in;
>  
> +struct cmd_out_implemented {
> +    uint64_t cmd_list;
> +};
> +typedef struct cmd_out_implemented cmd_out_implemented;
> +
>  struct dsm_out {
>      /* the size of buffer filled by QEMU. */
>      uint32_t len;
> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>      return 0;
>  }
>  
> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
> +{
> +    /* status locates in the first 4 bytes in the dsm memory. */

located?

> +    assert(!out->len);


But dsm itself can be part of a bigger table.
So don't do it.

> +
> +    status = cpu_to_le32(status);
> +    g_array_append_vals(out, &status, sizeof(status));

I think this should just use the (unfortunately named)
build_append_int_noprefix. Same applied everywhere
where you add single values.

> +}
> +
> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
> +{
> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
> +
> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> +    if (in->function == DSM_FUN_IMPLEMENTED) {
> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);

see about about single use values.


> +
> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> +        return;
> +    }
> +
> +    nvdimm_debug("Return status %#x.\n", status);
> +    nvdimm_dsm_write_status(out, status);
> +}
> +
> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
> +{
> +    GSList *list = nvdimm_get_plugged_device_list();
> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
> +    uint64_t cmd_list;
> +
> +    if (!nvdimm) {
> +        goto set_status_free;
> +    }
> +
> +    switch (in->function) {
> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> +    case DSM_FUN_IMPLEMENTED:
> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> +        goto free;
> +    default:
> +        status = DSM_STATUS_NOT_SUPPORTED;
> +    };
> +
> +set_status_free:
> +    nvdimm_debug("Return status %#x.\n", status);
> +    nvdimm_dsm_write_status(out, status);
> +free:
> +    g_slist_free(list);
> +}
> +
>  static void
>  nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>  {
> +    NVDIMMState *state = opaque;
> +    MemoryRegion *dsm_ram_mr;
> +    dsm_in *in;
> +    GArray *out;
> +    void *dsm_ram_addr;


Why don't you give this the correct type? Will avoid need for casts.

> +
>      if (val != NOTIFY_VALUE) {
>          fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>      }
> +
> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
> +                                    getpagesize()).mr;
> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);


This needs a validity check for size.

> +
> +    /*
> +     * copy all input data to our local memory to avoid potential issue
> +     * as the dsm memory is visible to guest.

this comment doesn't help.
pls replace "potential issue" with an explanation.

> +     */
> +    in = g_malloc(memory_region_size(dsm_ram_mr));
> +    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
> +
> +    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);
> +
> +    if (in->revision != DSM_REVISION) {
> +        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
> +                      in->revision, DSM_REVISION);
> +        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
> +        goto exit;
> +    }
> +
> +    /* Handle 0 is reserved for NVDIMM Root Device. */
> +    if (!in->handle) {
> +        nvdimm_dsm_write_root(in, out);
> +        goto exit;
> +    }
> +
> +    nvdimm_dsm_write_nvdimm(in, out);
> +
> +exit:
> +    /* Write our output result to dsm memory. */
> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> +    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);

This breaks migration as memory is not dirtied.

address_space_write is generally preferable to change memory.



> +
> +    g_free(in);
> +    g_array_free(out, true);
> +    memory_region_unref(dsm_ram_mr);
>  }
>  
>  static const MemoryRegionOps nvdimm_dsm_ops = {
> @@ -547,7 +725,8 @@ static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
>           */
>          BUILD_DSM_METHOD(dev, method,
>                           handle /* NVDIMM Device Handle */,
> -                         3 /* Invalid Input Parameters */,
> +                         DSM_DEV_STATUS_INVALID_PARAS, /* error code if UUID
> +                                                         is not matched. */
>                           "4309AC30-0D11-11E4-9191-0800200C9A66"
>                           /* UUID for NVDIMM Devices. */);
>  
> @@ -669,7 +848,8 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>       */
>      BUILD_DSM_METHOD(dev, method,
>                       0 /* 0 is reserved for NVDIMM Root Device*/,
> -                     2 /* Invalid Input Parameters */,
> +                     DSM_ROOT_DEV_STATUS_INVALID_PARAS, /* error code if
> +                                                     UUID is not matched. */
>                       "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
>                       /* UUID for NVDIMM Root Devices. */);
>  
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH v4 00/33] implement vNVDIMM
@ 2015-10-19  0:53 ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

This patchset can be found at:
      https://github.com/xiaogr/qemu.git nvdimm-v4

It is based on pci branch on Michael's tree and the top commit is:
commit e20cff85470be (piix: fix resource leak reported by Coverity).


Changelog in v4:
- changes from Michael's comments:
  1) show the message, "Memory is not allocated from HugeTlbfs", if file
     based memory is not allocated from hugetlbfs.
  2) introduce function, acpi_get_nvdimm_state(), to get NVDIMMState
     from Machine.
  3) statically define UUID and make its operation more clear
  4) use GArray to build device structures to avoid potential buffer
     overflow
  4) improve comments in the code
  5) improve code style

- changes from Igor's comments:
  1) add NVDIMM ACPI spec document
  2) use serialized method to avoid Mutex
  3) move NVDIMM ACPI's code to hw/acpi/nvdimm.c
  4) introduce a common ASL method used by _DSM for all devices to reduce
     ACPI size
  5) handle UUID in ACPI AML code. BTW, i'd keep handling revision in QEMU
     it's better to upgrade QEMU to support Rev2 in the future

- changes from Stefan's comments:
  1) copy input data from DSM memory to local buffer to avoid potential
     issues as DSM memory is visible to guest. Output data is handled
     in a similar way

- changes from Dan's comments:
  1) drop static namespace as Linux has already supported label-less
     nvdimm devices

- changes from Vladimir's comments:
  1) print better message, "failed to get file size for %s, can't create
     backend on it", if any file operation filed to obtain file size

- others:
  create a git repo on github.com for better review/test

Also, thanks for Eric Blake's review on QAPI's side.

Thank all of you to review this patchset.

Changelog in v3:
There is huge change in this version, thank Igor, Stefan, Paolo, Eduardo,
Michael for their valuable comments, the patchset finally gets better shape.
- changes from Igor's comments:
  1) abstract dimm device type from pc-dimm and create nvdimm device based on
     dimm, then it uses memory backend device as nvdimm's memory and NUMA has
     easily been implemented.
  2) let file-backend device support any kind of filesystem not only for
     hugetlbfs and let it work on file not only for directory which is
     achieved by extending 'mem-path' - if it's a directory then it works as
     current behavior, otherwise if it's file then directly allocates memory
     from it.
  3) we figure out a unused memory hole below 4G that is 0xFF00000 ~ 
     0xFFF00000, this range is large enough for NVDIMM ACPI as build 64-bit
     ACPI SSDT/DSDT table will break windows XP.
     BTW, only make SSDT.rev = 2 can not work since the width is only depended
     on DSDT.rev based on 19.6.28 DefinitionBlock (Declare Definition Block)
     in ACPI spec:
| Note: For compatibility with ACPI versions before ACPI 2.0, the bit 
| width of Integer objects is dependent on the ComplianceRevision of the DSDT.
| If the ComplianceRevision is less than 2, all integers are restricted to 32 
| bits. Otherwise, full 64-bit integers are used. The version of the DSDT sets 
| the global integer width for all integers, including integers in SSDTs.
  4) use the lowest ACPI spec version to document AML terms.
  5) use "nvdimm" as nvdimm device name instead of "pc-nvdimm"

- changes from Stefan's comments:
  1) do not do endian adjustment in-place since _DSM memory is visible to guest
  2) use target platform's target page size instead of fixed PAGE_SIZE
     definition
  3) lots of code style improvement and typo fixes.
  4) live migration fix
- changes from Paolo's comments:
  1) improve the name of memory region
  
- other changes:
  1) return exact buffer size for _DSM method instead of the page size.
  2) introduce mutex in NVDIMM ACPI as the _DSM memory is shared by all nvdimm
     devices.
  3) NUMA support
  4) implement _FIT method
  5) rename "configdata" to "reserve-label-data"
  6) simplify _DSM arg3 determination
  7) main changelog update to let it reflect v3.

Changlog in v2:
- Use litten endian for DSM method, thanks for Stefan's suggestion

- introduce a new parameter, @configdata, if it's false, Qemu will
  build a static and readonly namespace in memory and use it serveing
  for DSM GET_CONFIG_SIZE/GET_CONFIG_DATA requests. In this case, no
  reserved region is needed at the end of the @file, it is good for
  the user who want to pass whole nvdimm device and make its data
  completely be visible to guest

- divide the source code into separated files and add maintain info

BTW, PCOMMIT virtualization on KVM side is work in progress, hopefully will
be posted on next week

====== Background ======
NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
on Intel's platform. They are discovered via ACPI and configured by _DSM
method of NVDIMM device in ACPI. There has some supporting documents which
can be found at:
ACPI 6: http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
NVDIMM Namespace: http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
DSM Interface Example: http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
Driver Writer's Guide: http://pmem.io/documents/NVDIMM_Driver_Writers_Guide.pdf

Currently, the NVDIMM driver has been merged into upstream Linux Kernel and
this patchset tries to enable it in virtualization field

====== Design ======
NVDIMM supports two mode accesses, one is PMEM which maps NVDIMM into CPU's
address space then CPU can directly access it as normal memory, another is
BLK which is used as block device to reduce the occupying of CPU address
space

BLK mode accesses NVDIMM via Command Register window and Data Register window.
BLK virtualization has high workload since each sector access will cause at
least two VM-EXIT. So we currently only imperilment vPMEM in this patchset

--- vPMEM design ---
We introduce a new device named "nvdimm", it uses memory backend device as
NVDIMM memory. The file in file-backend device can be a regular file and block 
device. We can use any file when we do test or emulation, however,
in the real word, the files passed to guest are:
- the regular file in the filesystem with DAX enabled created on NVDIMM device
  on host
- the raw PMEM device on host, e,g /dev/pmem0
Memory access on the address created by mmap on these kinds of files can
directly reach NVDIMM device on host.

--- vConfigure data area design ---
Each NVDIMM device has a configure data area which is used to store label
namespace data. In order to emulating this area, we divide the file into two
parts:
- first parts is (0, size - 128K], which is used as PMEM
- 128K at the end of the file, which is used as Label Data Area
So that the label namespace data can be persistent during power lose or system
failure.

We also support passing the whole file to guest without reserve any region for
label data area which is achieved by "reserve-label-data" parameter - if it's
false then QEMU will build static and readonly namespace in memory and that
namespace contains the whole file size. The parameter is false on default.

--- _DSM method design ---
_DSM in ACPI is used to configure NVDIMM, currently we only allow access of
label namespace data, i.e, Get Namespace Label Size (Function Index 4),
Get Namespace Label Data (Function Index 5) and Set Namespace Label Data
(Function Index 6)

_DSM uses two pages to transfer data between ACPI and Qemu, the first page
is RAM-based used to save the input info of _DSM method and Qemu reuse it
store output info and another page is MMIO-based, ACPI write data to this
page to transfer the control to Qemu

====== Test ======
In host
1) create memory backed file, e.g # dd if=zero of=/tmp/nvdimm bs=1G count=10
2) append "-object memory-backend-file,share,id=mem1,
   mem-path=/tmp/nvdimm -device nvdimm,memdev=mem1,reserve-label-data,
   id=nv1" in QEMU command line

In guest, download the latest upsteam kernel (4.2 merge window) and enable
ACPI_NFIT, LIBNVDIMM and BLK_DEV_PMEM.
1) insmod drivers/nvdimm/libnvdimm.ko
2) insmod drivers/acpi/nfit.ko
3) insmod drivers/nvdimm/nd_btt.ko
4) insmod drivers/nvdimm/nd_pmem.ko
You can see the whole nvdimm device used as a single namespace and /dev/pmem0
appears. You can do whatever on /dev/pmem0 including DAX access.

Currently Linux NVDIMM driver does not support namespace operation on this
kind of PMEM, apply below changes to support dynamical namespace:

@@ -798,7 +823,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *a
                        continue;
                }
 
-               if (nfit_mem->bdw && nfit_mem->memdev_pmem)
+               //if (nfit_mem->bdw && nfit_mem->memdev_pmem)
+               if (nfit_mem->memdev_pmem)
                        flags |= NDD_ALIASING;

You can append another NVDIMM device in guest and do:                       
# cd /sys/bus/nd/devices/
# cd namespace1.0/
# echo `uuidgen` > uuid
# echo `expr 1024 \* 1024 \* 128` > size
then reload nd.pmem.ko

You can see /dev/pmem1 appears

Xiao Guangrong (33):
  acpi: add aml_derefof
  acpi: add aml_sizeof
  acpi: add aml_create_field
  acpi: add aml_concatenate
  acpi: add aml_object_type
  acpi: add aml_method_serialized
  util: introduce qemu_file_get_page_size()
  exec: allow memory to be allocated from any kind of path
  exec: allow file_ram_alloc to work on file
  hostmem-file: clean up memory allocation
  hostmem-file: use whole file size if possible
  pc-dimm: remove DEFAULT_PC_DIMMSIZE
  pc-dimm: make pc_existing_dimms_capacity static and rename it
  pc-dimm: drop the prefix of pc-dimm
  stubs: rename qmp_pc_dimm_device_list.c
  pc-dimm: rename pc-dimm.c and pc-dimm.h
  dimm: abstract dimm device from pc-dimm
  dimm: get mapped memory region from DIMMDeviceClass->get_memory_region
  dimm: keep the state of the whole backend memory
  dimm: introduce realize callback
  nvdimm: implement NVDIMM device abstract
  docs: add NVDIMM ACPI documentation
  nvdimm acpi: init the address region used by NVDIMM ACPI
  nvdimm acpi: build ACPI NFIT table
  nvdimm acpi: init the address region used by DSM method
  nvdimm acpi: build ACPI nvdimm devices
  nvdimm acpi: save arg3 for NVDIMM device _DSM method
  nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  nvdimm acpi: support DSM_DEV_FUN_NAMESPACE_LABEL_SIZE function
  nvdimm acpi: support DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA
  nvdimm acpi: support DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
  nvdimm: allow using whole backend memory as pmem
  nvdimm: add maintain info

 MAINTAINERS                                        |    7 +
 backends/hostmem-file.c                            |   59 +-
 default-configs/i386-softmmu.mak                   |    2 +
 default-configs/x86_64-softmmu.mak                 |    2 +
 docs/specs/acpi_nvdimm.txt                         |  154 +++
 exec.c                                             |  114 +-
 hmp.c                                              |    2 +-
 hw/Makefile.objs                                   |    2 +-
 hw/acpi/Makefile.objs                              |    1 +
 hw/acpi/aml-build.c                                |   77 +-
 hw/acpi/ich9.c                                     |    8 +-
 hw/acpi/memory_hotplug.c                           |   26 +-
 hw/acpi/nvdimm.c                                   | 1128 ++++++++++++++++++++
 hw/acpi/piix4.c                                    |    8 +-
 hw/i386/acpi-build.c                               |   10 +
 hw/i386/pc.c                                       |   36 +-
 hw/mem/Makefile.objs                               |    2 +
 hw/mem/{pc-dimm.c => dimm.c}                       |  240 +++--
 hw/mem/nvdimm.c                                    |  135 +++
 hw/mem/pc-dimm.c                                   |  513 +--------
 hw/ppc/spapr.c                                     |   20 +-
 include/hw/acpi/aml-build.h                        |    6 +
 include/hw/i386/pc.h                               |    4 +-
 include/hw/mem/{pc-dimm.h => dimm.h}               |   68 +-
 include/hw/mem/nvdimm.h                            |  111 ++
 include/hw/mem/pc-dimm.h                           |  105 +-
 include/hw/ppc/spapr.h                             |    2 +-
 include/qemu/osdep.h                               |    1 +
 numa.c                                             |    4 +-
 qapi-schema.json                                   |    8 +-
 qmp.c                                              |    4 +-
 stubs/Makefile.objs                                |    2 +-
 ...c_dimm_device_list.c => qmp_dimm_device_list.c} |    4 +-
 target-ppc/kvm.c                                   |   21 +-
 trace-events                                       |    8 +-
 util/oslib-posix.c                                 |   16 +
 util/oslib-win32.c                                 |    5 +
 37 files changed, 2046 insertions(+), 869 deletions(-)
 create mode 100644 docs/specs/acpi_nvdimm.txt
 create mode 100644 hw/acpi/nvdimm.c
 rename hw/mem/{pc-dimm.c => dimm.c} (66%)
 create mode 100644 hw/mem/nvdimm.c
 rewrite hw/mem/pc-dimm.c (91%)
 rename include/hw/mem/{pc-dimm.h => dimm.h} (50%)
 create mode 100644 include/hw/mem/nvdimm.h
 rewrite include/hw/mem/pc-dimm.h (97%)
 rename stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} (56%)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 00/33] implement vNVDIMM
@ 2015-10-19  0:53 ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

This patchset can be found at:
      https://github.com/xiaogr/qemu.git nvdimm-v4

It is based on pci branch on Michael's tree and the top commit is:
commit e20cff85470be (piix: fix resource leak reported by Coverity).


Changelog in v4:
- changes from Michael's comments:
  1) show the message, "Memory is not allocated from HugeTlbfs", if file
     based memory is not allocated from hugetlbfs.
  2) introduce function, acpi_get_nvdimm_state(), to get NVDIMMState
     from Machine.
  3) statically define UUID and make its operation more clear
  4) use GArray to build device structures to avoid potential buffer
     overflow
  4) improve comments in the code
  5) improve code style

- changes from Igor's comments:
  1) add NVDIMM ACPI spec document
  2) use serialized method to avoid Mutex
  3) move NVDIMM ACPI's code to hw/acpi/nvdimm.c
  4) introduce a common ASL method used by _DSM for all devices to reduce
     ACPI size
  5) handle UUID in ACPI AML code. BTW, i'd keep handling revision in QEMU
     it's better to upgrade QEMU to support Rev2 in the future

- changes from Stefan's comments:
  1) copy input data from DSM memory to local buffer to avoid potential
     issues as DSM memory is visible to guest. Output data is handled
     in a similar way

- changes from Dan's comments:
  1) drop static namespace as Linux has already supported label-less
     nvdimm devices

- changes from Vladimir's comments:
  1) print better message, "failed to get file size for %s, can't create
     backend on it", if any file operation filed to obtain file size

- others:
  create a git repo on github.com for better review/test

Also, thanks for Eric Blake's review on QAPI's side.

Thank all of you to review this patchset.

Changelog in v3:
There is huge change in this version, thank Igor, Stefan, Paolo, Eduardo,
Michael for their valuable comments, the patchset finally gets better shape.
- changes from Igor's comments:
  1) abstract dimm device type from pc-dimm and create nvdimm device based on
     dimm, then it uses memory backend device as nvdimm's memory and NUMA has
     easily been implemented.
  2) let file-backend device support any kind of filesystem not only for
     hugetlbfs and let it work on file not only for directory which is
     achieved by extending 'mem-path' - if it's a directory then it works as
     current behavior, otherwise if it's file then directly allocates memory
     from it.
  3) we figure out a unused memory hole below 4G that is 0xFF00000 ~ 
     0xFFF00000, this range is large enough for NVDIMM ACPI as build 64-bit
     ACPI SSDT/DSDT table will break windows XP.
     BTW, only make SSDT.rev = 2 can not work since the width is only depended
     on DSDT.rev based on 19.6.28 DefinitionBlock (Declare Definition Block)
     in ACPI spec:
| Note: For compatibility with ACPI versions before ACPI 2.0, the bit 
| width of Integer objects is dependent on the ComplianceRevision of the DSDT.
| If the ComplianceRevision is less than 2, all integers are restricted to 32 
| bits. Otherwise, full 64-bit integers are used. The version of the DSDT sets 
| the global integer width for all integers, including integers in SSDTs.
  4) use the lowest ACPI spec version to document AML terms.
  5) use "nvdimm" as nvdimm device name instead of "pc-nvdimm"

- changes from Stefan's comments:
  1) do not do endian adjustment in-place since _DSM memory is visible to guest
  2) use target platform's target page size instead of fixed PAGE_SIZE
     definition
  3) lots of code style improvement and typo fixes.
  4) live migration fix
- changes from Paolo's comments:
  1) improve the name of memory region
  
- other changes:
  1) return exact buffer size for _DSM method instead of the page size.
  2) introduce mutex in NVDIMM ACPI as the _DSM memory is shared by all nvdimm
     devices.
  3) NUMA support
  4) implement _FIT method
  5) rename "configdata" to "reserve-label-data"
  6) simplify _DSM arg3 determination
  7) main changelog update to let it reflect v3.

Changlog in v2:
- Use litten endian for DSM method, thanks for Stefan's suggestion

- introduce a new parameter, @configdata, if it's false, Qemu will
  build a static and readonly namespace in memory and use it serveing
  for DSM GET_CONFIG_SIZE/GET_CONFIG_DATA requests. In this case, no
  reserved region is needed at the end of the @file, it is good for
  the user who want to pass whole nvdimm device and make its data
  completely be visible to guest

- divide the source code into separated files and add maintain info

BTW, PCOMMIT virtualization on KVM side is work in progress, hopefully will
be posted on next week

====== Background ======
NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
on Intel's platform. They are discovered via ACPI and configured by _DSM
method of NVDIMM device in ACPI. There has some supporting documents which
can be found at:
ACPI 6: http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
NVDIMM Namespace: http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
DSM Interface Example: http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
Driver Writer's Guide: http://pmem.io/documents/NVDIMM_Driver_Writers_Guide.pdf

Currently, the NVDIMM driver has been merged into upstream Linux Kernel and
this patchset tries to enable it in virtualization field

====== Design ======
NVDIMM supports two mode accesses, one is PMEM which maps NVDIMM into CPU's
address space then CPU can directly access it as normal memory, another is
BLK which is used as block device to reduce the occupying of CPU address
space

BLK mode accesses NVDIMM via Command Register window and Data Register window.
BLK virtualization has high workload since each sector access will cause at
least two VM-EXIT. So we currently only imperilment vPMEM in this patchset

--- vPMEM design ---
We introduce a new device named "nvdimm", it uses memory backend device as
NVDIMM memory. The file in file-backend device can be a regular file and block 
device. We can use any file when we do test or emulation, however,
in the real word, the files passed to guest are:
- the regular file in the filesystem with DAX enabled created on NVDIMM device
  on host
- the raw PMEM device on host, e,g /dev/pmem0
Memory access on the address created by mmap on these kinds of files can
directly reach NVDIMM device on host.

--- vConfigure data area design ---
Each NVDIMM device has a configure data area which is used to store label
namespace data. In order to emulating this area, we divide the file into two
parts:
- first parts is (0, size - 128K], which is used as PMEM
- 128K at the end of the file, which is used as Label Data Area
So that the label namespace data can be persistent during power lose or system
failure.

We also support passing the whole file to guest without reserve any region for
label data area which is achieved by "reserve-label-data" parameter - if it's
false then QEMU will build static and readonly namespace in memory and that
namespace contains the whole file size. The parameter is false on default.

--- _DSM method design ---
_DSM in ACPI is used to configure NVDIMM, currently we only allow access of
label namespace data, i.e, Get Namespace Label Size (Function Index 4),
Get Namespace Label Data (Function Index 5) and Set Namespace Label Data
(Function Index 6)

_DSM uses two pages to transfer data between ACPI and Qemu, the first page
is RAM-based used to save the input info of _DSM method and Qemu reuse it
store output info and another page is MMIO-based, ACPI write data to this
page to transfer the control to Qemu

====== Test ======
In host
1) create memory backed file, e.g # dd if=zero of=/tmp/nvdimm bs=1G count=10
2) append "-object memory-backend-file,share,id=mem1,
   mem-path=/tmp/nvdimm -device nvdimm,memdev=mem1,reserve-label-data,
   id=nv1" in QEMU command line

In guest, download the latest upsteam kernel (4.2 merge window) and enable
ACPI_NFIT, LIBNVDIMM and BLK_DEV_PMEM.
1) insmod drivers/nvdimm/libnvdimm.ko
2) insmod drivers/acpi/nfit.ko
3) insmod drivers/nvdimm/nd_btt.ko
4) insmod drivers/nvdimm/nd_pmem.ko
You can see the whole nvdimm device used as a single namespace and /dev/pmem0
appears. You can do whatever on /dev/pmem0 including DAX access.

Currently Linux NVDIMM driver does not support namespace operation on this
kind of PMEM, apply below changes to support dynamical namespace:

@@ -798,7 +823,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *a
                        continue;
                }
 
-               if (nfit_mem->bdw && nfit_mem->memdev_pmem)
+               //if (nfit_mem->bdw && nfit_mem->memdev_pmem)
+               if (nfit_mem->memdev_pmem)
                        flags |= NDD_ALIASING;

You can append another NVDIMM device in guest and do:                       
# cd /sys/bus/nd/devices/
# cd namespace1.0/
# echo `uuidgen` > uuid
# echo `expr 1024 \* 1024 \* 128` > size
then reload nd.pmem.ko

You can see /dev/pmem1 appears

Xiao Guangrong (33):
  acpi: add aml_derefof
  acpi: add aml_sizeof
  acpi: add aml_create_field
  acpi: add aml_concatenate
  acpi: add aml_object_type
  acpi: add aml_method_serialized
  util: introduce qemu_file_get_page_size()
  exec: allow memory to be allocated from any kind of path
  exec: allow file_ram_alloc to work on file
  hostmem-file: clean up memory allocation
  hostmem-file: use whole file size if possible
  pc-dimm: remove DEFAULT_PC_DIMMSIZE
  pc-dimm: make pc_existing_dimms_capacity static and rename it
  pc-dimm: drop the prefix of pc-dimm
  stubs: rename qmp_pc_dimm_device_list.c
  pc-dimm: rename pc-dimm.c and pc-dimm.h
  dimm: abstract dimm device from pc-dimm
  dimm: get mapped memory region from DIMMDeviceClass->get_memory_region
  dimm: keep the state of the whole backend memory
  dimm: introduce realize callback
  nvdimm: implement NVDIMM device abstract
  docs: add NVDIMM ACPI documentation
  nvdimm acpi: init the address region used by NVDIMM ACPI
  nvdimm acpi: build ACPI NFIT table
  nvdimm acpi: init the address region used by DSM method
  nvdimm acpi: build ACPI nvdimm devices
  nvdimm acpi: save arg3 for NVDIMM device _DSM method
  nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  nvdimm acpi: support DSM_DEV_FUN_NAMESPACE_LABEL_SIZE function
  nvdimm acpi: support DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA
  nvdimm acpi: support DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
  nvdimm: allow using whole backend memory as pmem
  nvdimm: add maintain info

 MAINTAINERS                                        |    7 +
 backends/hostmem-file.c                            |   59 +-
 default-configs/i386-softmmu.mak                   |    2 +
 default-configs/x86_64-softmmu.mak                 |    2 +
 docs/specs/acpi_nvdimm.txt                         |  154 +++
 exec.c                                             |  114 +-
 hmp.c                                              |    2 +-
 hw/Makefile.objs                                   |    2 +-
 hw/acpi/Makefile.objs                              |    1 +
 hw/acpi/aml-build.c                                |   77 +-
 hw/acpi/ich9.c                                     |    8 +-
 hw/acpi/memory_hotplug.c                           |   26 +-
 hw/acpi/nvdimm.c                                   | 1128 ++++++++++++++++++++
 hw/acpi/piix4.c                                    |    8 +-
 hw/i386/acpi-build.c                               |   10 +
 hw/i386/pc.c                                       |   36 +-
 hw/mem/Makefile.objs                               |    2 +
 hw/mem/{pc-dimm.c => dimm.c}                       |  240 +++--
 hw/mem/nvdimm.c                                    |  135 +++
 hw/mem/pc-dimm.c                                   |  513 +--------
 hw/ppc/spapr.c                                     |   20 +-
 include/hw/acpi/aml-build.h                        |    6 +
 include/hw/i386/pc.h                               |    4 +-
 include/hw/mem/{pc-dimm.h => dimm.h}               |   68 +-
 include/hw/mem/nvdimm.h                            |  111 ++
 include/hw/mem/pc-dimm.h                           |  105 +-
 include/hw/ppc/spapr.h                             |    2 +-
 include/qemu/osdep.h                               |    1 +
 numa.c                                             |    4 +-
 qapi-schema.json                                   |    8 +-
 qmp.c                                              |    4 +-
 stubs/Makefile.objs                                |    2 +-
 ...c_dimm_device_list.c => qmp_dimm_device_list.c} |    4 +-
 target-ppc/kvm.c                                   |   21 +-
 trace-events                                       |    8 +-
 util/oslib-posix.c                                 |   16 +
 util/oslib-win32.c                                 |    5 +
 37 files changed, 2046 insertions(+), 869 deletions(-)
 create mode 100644 docs/specs/acpi_nvdimm.txt
 create mode 100644 hw/acpi/nvdimm.c
 rename hw/mem/{pc-dimm.c => dimm.c} (66%)
 create mode 100644 hw/mem/nvdimm.c
 rewrite hw/mem/pc-dimm.c (91%)
 rename include/hw/mem/{pc-dimm.h => dimm.h} (50%)
 create mode 100644 include/hw/mem/nvdimm.h
 rewrite include/hw/mem/pc-dimm.h (97%)
 rename stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} (56%)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH v4 01/33] acpi: add aml_derefof
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement DeRefOf term which is used by NVDIMM _DSM method in later patch

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 0d4b324..cbd53f4 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1135,6 +1135,14 @@ Aml *aml_unicode(const char *str)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
+Aml *aml_derefof(Aml *arg)
+{
+    Aml *var = aml_opcode(0x83 /* DerefOfOp */);
+    aml_append(var, arg);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1b632dc..5a03d33 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -274,6 +274,7 @@ Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name);
 Aml *aml_varpackage(uint32_t num_elements);
 Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
+Aml *aml_derefof(Aml *arg);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 01/33] acpi: add aml_derefof
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement DeRefOf term which is used by NVDIMM _DSM method in later patch

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 0d4b324..cbd53f4 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1135,6 +1135,14 @@ Aml *aml_unicode(const char *str)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
+Aml *aml_derefof(Aml *arg)
+{
+    Aml *var = aml_opcode(0x83 /* DerefOfOp */);
+    aml_append(var, arg);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1b632dc..5a03d33 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -274,6 +274,7 @@ Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name);
 Aml *aml_varpackage(uint32_t num_elements);
 Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
+Aml *aml_derefof(Aml *arg);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 02/33] acpi: add aml_sizeof
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Implement SizeOf term which is used by NVDIMM _DSM method in later patch

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index cbd53f4..a72214d 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1143,6 +1143,14 @@ Aml *aml_derefof(Aml *arg)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSizeOf */
+Aml *aml_sizeof(Aml *arg)
+{
+    Aml *var = aml_opcode(0x87 /* SizeOfOp */);
+    aml_append(var, arg);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 5a03d33..7296efb 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -275,6 +275,7 @@ Aml *aml_varpackage(uint32_t num_elements);
 Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
+Aml *aml_sizeof(Aml *arg);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 02/33] acpi: add aml_sizeof
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement SizeOf term which is used by NVDIMM _DSM method in later patch

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index cbd53f4..a72214d 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1143,6 +1143,14 @@ Aml *aml_derefof(Aml *arg)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSizeOf */
+Aml *aml_sizeof(Aml *arg)
+{
+    Aml *var = aml_opcode(0x87 /* SizeOfOp */);
+    aml_append(var, arg);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 5a03d33..7296efb 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -275,6 +275,7 @@ Aml *aml_varpackage(uint32_t num_elements);
 Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
+Aml *aml_sizeof(Aml *arg);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 03/33] acpi: add aml_create_field
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement CreateField term which is used by NVDIMM _DSM method in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 13 +++++++++++++
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index a72214d..9fe5e7b 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1151,6 +1151,19 @@ Aml *aml_sizeof(Aml *arg)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
+Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name)
+{
+    Aml *var = aml_alloc();
+    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
+    build_append_byte(var->buf, 0x13); /* CreateFieldOp */
+    aml_append(var, srcbuf);
+    aml_append(var, index);
+    aml_append(var, len);
+    build_append_namestring(var->buf, "%s", name);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 7296efb..7e1c43b 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -276,6 +276,7 @@ Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
+Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 03/33] acpi: add aml_create_field
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement CreateField term which is used by NVDIMM _DSM method in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 13 +++++++++++++
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index a72214d..9fe5e7b 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1151,6 +1151,19 @@ Aml *aml_sizeof(Aml *arg)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
+Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name)
+{
+    Aml *var = aml_alloc();
+    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
+    build_append_byte(var->buf, 0x13); /* CreateFieldOp */
+    aml_append(var, srcbuf);
+    aml_append(var, index);
+    aml_append(var, len);
+    build_append_namestring(var->buf, "%s", name);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 7296efb..7e1c43b 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -276,6 +276,7 @@ Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
+Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 04/33] acpi: add aml_concatenate
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Implement Concatenate term which is used by NVDIMM _DSM method
in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 14 ++++++++++++++
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 15 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 9fe5e7b..efc06ab 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1164,6 +1164,20 @@ Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
+{
+    Aml *var = aml_opcode(0x73 /* ConcatOp */);
+    aml_append(var, source1);
+    aml_append(var, source2);
+
+    if (target) {
+        aml_append(var, target);
+    }
+
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 7e1c43b..325782d 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -277,6 +277,7 @@ Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
 Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 04/33] acpi: add aml_concatenate
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement Concatenate term which is used by NVDIMM _DSM method
in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 14 ++++++++++++++
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 15 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 9fe5e7b..efc06ab 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1164,6 +1164,20 @@ Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
+{
+    Aml *var = aml_opcode(0x73 /* ConcatOp */);
+    aml_append(var, source1);
+    aml_append(var, source2);
+
+    if (target) {
+        aml_append(var, target);
+    }
+
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 7e1c43b..325782d 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -277,6 +277,7 @@ Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
 Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 05/33] acpi: add aml_object_type
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Implement ObjectType which is used by NVDIMM _DSM method in
later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index efc06ab..9f792ab 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1178,6 +1178,14 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefObjectType */
+Aml *aml_object_type(Aml *object)
+{
+    Aml *var = aml_opcode(0x8E /* ObjectTypeOp */);
+    aml_append(var, object);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 325782d..5b8a118 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -278,6 +278,7 @@ Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
 Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
 Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
+Aml *aml_object_type(Aml *object);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 05/33] acpi: add aml_object_type
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Implement ObjectType which is used by NVDIMM _DSM method in
later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 8 ++++++++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index efc06ab..9f792ab 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1178,6 +1178,14 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
     return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefObjectType */
+Aml *aml_object_type(Aml *object)
+{
+    Aml *var = aml_opcode(0x8E /* ObjectTypeOp */);
+    aml_append(var, object);
+    return var;
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 325782d..5b8a118 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -278,6 +278,7 @@ Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
 Aml *aml_create_field(Aml *srcbuf, Aml *index, Aml *len, const char *name);
 Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
+Aml *aml_object_type(Aml *object);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 06/33] acpi: add aml_method_serialized
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

It avoid explicit Mutex and will be used by NVDIMM ACPI

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 26 ++++++++++++++++++++++++--
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 9f792ab..8bee8b2 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -696,14 +696,36 @@ Aml *aml_while(Aml *predicate)
 }
 
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
-Aml *aml_method(const char *name, int arg_count)
+static Aml *__aml_method(const char *name, int arg_count, bool serialized)
 {
     Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
+    int methodflags;
+
+    /*
+     * MethodFlags:
+     *   bit 0-2: ArgCount (0-7)
+     *   bit 3: SerializeFlag
+     *     0: NotSerialized
+     *     1: Serialized
+     *   bit 4-7: reserved (must be 0)
+     */
+    assert(!(arg_count & ~7));
+    methodflags = arg_count | (serialized << 3);
     build_append_namestring(var->buf, "%s", name);
-    build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */
+    build_append_byte(var->buf, methodflags);
     return var;
 }
 
+Aml *aml_method(const char *name, int arg_count)
+{
+    return __aml_method(name, arg_count, false);
+}
+
+Aml *aml_method_serialized(const char *name, int arg_count)
+{
+    return __aml_method(name, arg_count, true);
+}
+
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
 Aml *aml_device(const char *name_format, ...)
 {
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 5b8a118..00cf40e 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -263,6 +263,7 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
 Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
 Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
 Aml *aml_method(const char *name, int arg_count);
+Aml *aml_method_serialized(const char *name, int arg_count);
 Aml *aml_if(Aml *predicate);
 Aml *aml_else(void);
 Aml *aml_while(Aml *predicate);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 06/33] acpi: add aml_method_serialized
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

It avoid explicit Mutex and will be used by NVDIMM ACPI

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 26 ++++++++++++++++++++++++--
 include/hw/acpi/aml-build.h |  1 +
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 9f792ab..8bee8b2 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -696,14 +696,36 @@ Aml *aml_while(Aml *predicate)
 }
 
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
-Aml *aml_method(const char *name, int arg_count)
+static Aml *__aml_method(const char *name, int arg_count, bool serialized)
 {
     Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
+    int methodflags;
+
+    /*
+     * MethodFlags:
+     *   bit 0-2: ArgCount (0-7)
+     *   bit 3: SerializeFlag
+     *     0: NotSerialized
+     *     1: Serialized
+     *   bit 4-7: reserved (must be 0)
+     */
+    assert(!(arg_count & ~7));
+    methodflags = arg_count | (serialized << 3);
     build_append_namestring(var->buf, "%s", name);
-    build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */
+    build_append_byte(var->buf, methodflags);
     return var;
 }
 
+Aml *aml_method(const char *name, int arg_count)
+{
+    return __aml_method(name, arg_count, false);
+}
+
+Aml *aml_method_serialized(const char *name, int arg_count)
+{
+    return __aml_method(name, arg_count, true);
+}
+
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
 Aml *aml_device(const char *name_format, ...)
 {
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 5b8a118..00cf40e 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -263,6 +263,7 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
 Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
 Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
 Aml *aml_method(const char *name, int arg_count);
+Aml *aml_method_serialized(const char *name, int arg_count);
 Aml *aml_if(Aml *predicate);
 Aml *aml_else(void);
 Aml *aml_while(Aml *predicate);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 07/33] util: introduce qemu_file_get_page_size()
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

There are three places use the some logic to get the page size on
the file path or file fd

This patch introduces qemu_file_get_page_size() to unify the code

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 include/qemu/osdep.h |  1 +
 target-ppc/kvm.c     | 21 +++------------------
 util/oslib-posix.c   | 16 ++++++++++++++++
 util/oslib-win32.c   |  5 +++++
 4 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index ef21efb..9c8c0c4 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -286,4 +286,5 @@ void os_mem_prealloc(int fd, char *area, size_t sz);
 
 int qemu_read_password(char *buf, int buf_size);
 
+size_t qemu_file_get_page_size(const char *mem_path);
 #endif
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index f8ea783..ed3424e 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -306,28 +306,13 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
 
 static long gethugepagesize(const char *mem_path)
 {
-    struct statfs fs;
-    int ret;
-
-    do {
-        ret = statfs(mem_path, &fs);
-    } while (ret != 0 && errno == EINTR);
+    long size = qemu_file_get_page_size(mem_path);
 
-    if (ret != 0) {
-        fprintf(stderr, "Couldn't statfs() memory path: %s\n",
-                strerror(errno));
+    if (!size) {
         exit(1);
     }
 
-#define HUGETLBFS_MAGIC       0x958458f6
-
-    if (fs.f_type != HUGETLBFS_MAGIC) {
-        /* Explicit mempath, but it's ordinary pages */
-        return getpagesize();
-    }
-
-    /* It's hugepage, return the huge page size */
-    return fs.f_bsize;
+    return size;
 }
 
 static int find_max_supported_pagesize(Object *obj, void *opaque)
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 892d2d8..32b4d1f 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -360,6 +360,22 @@ static size_t fd_getpagesize(int fd)
     return getpagesize();
 }
 
+size_t qemu_file_get_page_size(const char *path)
+{
+    size_t size = 0;
+    int fd = qemu_open(path, O_RDONLY);
+
+    if (fd < 0) {
+        fprintf(stderr, "Could not open %s.\n", path);
+        goto exit;
+    }
+
+    size = fd_getpagesize(fd);
+    qemu_close(fd);
+exit:
+    return size;
+}
+
 void os_mem_prealloc(int fd, char *area, size_t memory)
 {
     int ret;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 08f5a9c..1ff1fae 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -462,6 +462,11 @@ size_t getpagesize(void)
     return system_info.dwPageSize;
 }
 
+size_t qemu_file_get_page_size(const char *path)
+{
+    return getpagesize();
+}
+
 void os_mem_prealloc(int fd, char *area, size_t memory)
 {
     int i;
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 07/33] util: introduce qemu_file_get_page_size()
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

There are three places use the some logic to get the page size on
the file path or file fd

This patch introduces qemu_file_get_page_size() to unify the code

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 include/qemu/osdep.h |  1 +
 target-ppc/kvm.c     | 21 +++------------------
 util/oslib-posix.c   | 16 ++++++++++++++++
 util/oslib-win32.c   |  5 +++++
 4 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index ef21efb..9c8c0c4 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -286,4 +286,5 @@ void os_mem_prealloc(int fd, char *area, size_t sz);
 
 int qemu_read_password(char *buf, int buf_size);
 
+size_t qemu_file_get_page_size(const char *mem_path);
 #endif
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index f8ea783..ed3424e 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -306,28 +306,13 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
 
 static long gethugepagesize(const char *mem_path)
 {
-    struct statfs fs;
-    int ret;
-
-    do {
-        ret = statfs(mem_path, &fs);
-    } while (ret != 0 && errno == EINTR);
+    long size = qemu_file_get_page_size(mem_path);
 
-    if (ret != 0) {
-        fprintf(stderr, "Couldn't statfs() memory path: %s\n",
-                strerror(errno));
+    if (!size) {
         exit(1);
     }
 
-#define HUGETLBFS_MAGIC       0x958458f6
-
-    if (fs.f_type != HUGETLBFS_MAGIC) {
-        /* Explicit mempath, but it's ordinary pages */
-        return getpagesize();
-    }
-
-    /* It's hugepage, return the huge page size */
-    return fs.f_bsize;
+    return size;
 }
 
 static int find_max_supported_pagesize(Object *obj, void *opaque)
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 892d2d8..32b4d1f 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -360,6 +360,22 @@ static size_t fd_getpagesize(int fd)
     return getpagesize();
 }
 
+size_t qemu_file_get_page_size(const char *path)
+{
+    size_t size = 0;
+    int fd = qemu_open(path, O_RDONLY);
+
+    if (fd < 0) {
+        fprintf(stderr, "Could not open %s.\n", path);
+        goto exit;
+    }
+
+    size = fd_getpagesize(fd);
+    qemu_close(fd);
+exit:
+    return size;
+}
+
 void os_mem_prealloc(int fd, char *area, size_t memory)
 {
     int ret;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 08f5a9c..1ff1fae 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -462,6 +462,11 @@ size_t getpagesize(void)
     return system_info.dwPageSize;
 }
 
+size_t qemu_file_get_page_size(const char *path)
+{
+    return getpagesize();
+}
+
 void os_mem_prealloc(int fd, char *area, size_t memory)
 {
     int i;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 08/33] exec: allow memory to be allocated from any kind of path
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Currently file_ram_alloc() is designed for hugetlbfs, however, the memory
of nvdimm can come from either raw pmem device eg, /dev/pmem, or the file
locates at DAX enabled filesystem

So this patch let it work on any kind of path

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 exec.c | 56 +++++++++++++++++---------------------------------------
 1 file changed, 17 insertions(+), 39 deletions(-)

diff --git a/exec.c b/exec.c
index 4505dc7..d2a3357 100644
--- a/exec.c
+++ b/exec.c
@@ -1157,32 +1157,6 @@ void qemu_mutex_unlock_ramlist(void)
 }
 
 #ifdef __linux__
-
-#include <sys/vfs.h>
-
-#define HUGETLBFS_MAGIC       0x958458f6
-
-static long gethugepagesize(const char *path, Error **errp)
-{
-    struct statfs fs;
-    int ret;
-
-    do {
-        ret = statfs(path, &fs);
-    } while (ret != 0 && errno == EINTR);
-
-    if (ret != 0) {
-        error_setg_errno(errp, errno, "failed to get page size of file %s",
-                         path);
-        return 0;
-    }
-
-    if (fs.f_type != HUGETLBFS_MAGIC)
-        fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
-
-    return fs.f_bsize;
-}
-
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path,
@@ -1193,20 +1167,24 @@ static void *file_ram_alloc(RAMBlock *block,
     char *c;
     void *area;
     int fd;
-    uint64_t hpagesize;
-    Error *local_err = NULL;
+    uint64_t pagesize;
 
-    hpagesize = gethugepagesize(path, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    pagesize = qemu_file_get_page_size(path);
+    if (!pagesize) {
+        error_setg(errp, "can't get page size for %s", path);
         goto error;
     }
-    block->mr->align = hpagesize;
 
-    if (memory < hpagesize) {
+    if (pagesize == getpagesize()) {
+        fprintf(stderr, "Memory is not allocated from HugeTlbfs.\n");
+    }
+
+    block->mr->align = pagesize;
+
+    if (memory < pagesize) {
         error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
-                   "or larger than huge page size 0x%" PRIx64,
-                   memory, hpagesize);
+                   "or larger than page size 0x%" PRIx64,
+                   memory, pagesize);
         goto error;
     }
 
@@ -1230,14 +1208,14 @@ static void *file_ram_alloc(RAMBlock *block,
     fd = mkstemp(filename);
     if (fd < 0) {
         error_setg_errno(errp, errno,
-                         "unable to create backing store for hugepages");
+                         "unable to create backing store for path %s", path);
         g_free(filename);
         goto error;
     }
     unlink(filename);
     g_free(filename);
 
-    memory = ROUND_UP(memory, hpagesize);
+    memory = ROUND_UP(memory, pagesize);
 
     /*
      * ftruncate is not supported by hugetlbfs in older
@@ -1249,10 +1227,10 @@ static void *file_ram_alloc(RAMBlock *block,
         perror("ftruncate");
     }
 
-    area = qemu_ram_mmap(fd, memory, hpagesize, block->flags & RAM_SHARED);
+    area = qemu_ram_mmap(fd, memory, pagesize, block->flags & RAM_SHARED);
     if (area == MAP_FAILED) {
         error_setg_errno(errp, errno,
-                         "unable to map backing store for hugepages");
+                         "unable to map backing store for path %s", path);
         close(fd);
         goto error;
     }
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 08/33] exec: allow memory to be allocated from any kind of path
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Currently file_ram_alloc() is designed for hugetlbfs, however, the memory
of nvdimm can come from either raw pmem device eg, /dev/pmem, or the file
locates at DAX enabled filesystem

So this patch let it work on any kind of path

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 exec.c | 56 +++++++++++++++++---------------------------------------
 1 file changed, 17 insertions(+), 39 deletions(-)

diff --git a/exec.c b/exec.c
index 4505dc7..d2a3357 100644
--- a/exec.c
+++ b/exec.c
@@ -1157,32 +1157,6 @@ void qemu_mutex_unlock_ramlist(void)
 }
 
 #ifdef __linux__
-
-#include <sys/vfs.h>
-
-#define HUGETLBFS_MAGIC       0x958458f6
-
-static long gethugepagesize(const char *path, Error **errp)
-{
-    struct statfs fs;
-    int ret;
-
-    do {
-        ret = statfs(path, &fs);
-    } while (ret != 0 && errno == EINTR);
-
-    if (ret != 0) {
-        error_setg_errno(errp, errno, "failed to get page size of file %s",
-                         path);
-        return 0;
-    }
-
-    if (fs.f_type != HUGETLBFS_MAGIC)
-        fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
-
-    return fs.f_bsize;
-}
-
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path,
@@ -1193,20 +1167,24 @@ static void *file_ram_alloc(RAMBlock *block,
     char *c;
     void *area;
     int fd;
-    uint64_t hpagesize;
-    Error *local_err = NULL;
+    uint64_t pagesize;
 
-    hpagesize = gethugepagesize(path, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    pagesize = qemu_file_get_page_size(path);
+    if (!pagesize) {
+        error_setg(errp, "can't get page size for %s", path);
         goto error;
     }
-    block->mr->align = hpagesize;
 
-    if (memory < hpagesize) {
+    if (pagesize == getpagesize()) {
+        fprintf(stderr, "Memory is not allocated from HugeTlbfs.\n");
+    }
+
+    block->mr->align = pagesize;
+
+    if (memory < pagesize) {
         error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
-                   "or larger than huge page size 0x%" PRIx64,
-                   memory, hpagesize);
+                   "or larger than page size 0x%" PRIx64,
+                   memory, pagesize);
         goto error;
     }
 
@@ -1230,14 +1208,14 @@ static void *file_ram_alloc(RAMBlock *block,
     fd = mkstemp(filename);
     if (fd < 0) {
         error_setg_errno(errp, errno,
-                         "unable to create backing store for hugepages");
+                         "unable to create backing store for path %s", path);
         g_free(filename);
         goto error;
     }
     unlink(filename);
     g_free(filename);
 
-    memory = ROUND_UP(memory, hpagesize);
+    memory = ROUND_UP(memory, pagesize);
 
     /*
      * ftruncate is not supported by hugetlbfs in older
@@ -1249,10 +1227,10 @@ static void *file_ram_alloc(RAMBlock *block,
         perror("ftruncate");
     }
 
-    area = qemu_ram_mmap(fd, memory, hpagesize, block->flags & RAM_SHARED);
+    area = qemu_ram_mmap(fd, memory, pagesize, block->flags & RAM_SHARED);
     if (area == MAP_FAILED) {
         error_setg_errno(errp, errno,
-                         "unable to map backing store for hugepages");
+                         "unable to map backing store for path %s", path);
         close(fd);
         goto error;
     }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 09/33] exec: allow file_ram_alloc to work on file
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Currently, file_ram_alloc() only works on directory - it creates a file
under @path and do mmap on it

This patch tries to allow it to work on file directly, if @path is a
directory it works as before, otherwise it treats @path as the target
file then directly allocate memory from it

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 exec.c | 80 ++++++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/exec.c b/exec.c
index d2a3357..09e9938 100644
--- a/exec.c
+++ b/exec.c
@@ -1157,14 +1157,60 @@ void qemu_mutex_unlock_ramlist(void)
 }
 
 #ifdef __linux__
+static bool path_is_dir(const char *path)
+{
+    struct stat fs;
+
+    return stat(path, &fs) == 0 && S_ISDIR(fs.st_mode);
+}
+
+static int open_file_path(RAMBlock *block, const char *path, size_t size)
+{
+    char *filename;
+    char *sanitized_name;
+    char *c;
+    int fd;
+
+    if (!path_is_dir(path)) {
+        int flags = (block->flags & RAM_SHARED) ? O_RDWR : O_RDONLY;
+
+        flags |= O_EXCL;
+        return open(path, flags);
+    }
+
+    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
+    sanitized_name = g_strdup(memory_region_name(block->mr));
+    for (c = sanitized_name; *c != '\0'; c++) {
+        if (*c == '/') {
+            *c = '_';
+        }
+    }
+    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
+                               sanitized_name);
+    g_free(sanitized_name);
+    fd = mkstemp(filename);
+    if (fd >= 0) {
+        unlink(filename);
+        /*
+         * ftruncate is not supported by hugetlbfs in older
+         * hosts, so don't bother bailing out on errors.
+         * If anything goes wrong with it under other filesystems,
+         * mmap will fail.
+         */
+        if (ftruncate(fd, size)) {
+            perror("ftruncate");
+        }
+    }
+    g_free(filename);
+
+    return fd;
+}
+
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path,
                             Error **errp)
 {
-    char *filename;
-    char *sanitized_name;
-    char *c;
     void *area;
     int fd;
     uint64_t pagesize;
@@ -1194,38 +1240,14 @@ static void *file_ram_alloc(RAMBlock *block,
         goto error;
     }
 
-    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
-    sanitized_name = g_strdup(memory_region_name(block->mr));
-    for (c = sanitized_name; *c != '\0'; c++) {
-        if (*c == '/')
-            *c = '_';
-    }
-
-    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
-                               sanitized_name);
-    g_free(sanitized_name);
+    memory = ROUND_UP(memory, pagesize);
 
-    fd = mkstemp(filename);
+    fd = open_file_path(block, path, memory);
     if (fd < 0) {
         error_setg_errno(errp, errno,
                          "unable to create backing store for path %s", path);
-        g_free(filename);
         goto error;
     }
-    unlink(filename);
-    g_free(filename);
-
-    memory = ROUND_UP(memory, pagesize);
-
-    /*
-     * ftruncate is not supported by hugetlbfs in older
-     * hosts, so don't bother bailing out on errors.
-     * If anything goes wrong with it under other filesystems,
-     * mmap will fail.
-     */
-    if (ftruncate(fd, memory)) {
-        perror("ftruncate");
-    }
 
     area = qemu_ram_mmap(fd, memory, pagesize, block->flags & RAM_SHARED);
     if (area == MAP_FAILED) {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 09/33] exec: allow file_ram_alloc to work on file
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Currently, file_ram_alloc() only works on directory - it creates a file
under @path and do mmap on it

This patch tries to allow it to work on file directly, if @path is a
directory it works as before, otherwise it treats @path as the target
file then directly allocate memory from it

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 exec.c | 80 ++++++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/exec.c b/exec.c
index d2a3357..09e9938 100644
--- a/exec.c
+++ b/exec.c
@@ -1157,14 +1157,60 @@ void qemu_mutex_unlock_ramlist(void)
 }
 
 #ifdef __linux__
+static bool path_is_dir(const char *path)
+{
+    struct stat fs;
+
+    return stat(path, &fs) == 0 && S_ISDIR(fs.st_mode);
+}
+
+static int open_file_path(RAMBlock *block, const char *path, size_t size)
+{
+    char *filename;
+    char *sanitized_name;
+    char *c;
+    int fd;
+
+    if (!path_is_dir(path)) {
+        int flags = (block->flags & RAM_SHARED) ? O_RDWR : O_RDONLY;
+
+        flags |= O_EXCL;
+        return open(path, flags);
+    }
+
+    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
+    sanitized_name = g_strdup(memory_region_name(block->mr));
+    for (c = sanitized_name; *c != '\0'; c++) {
+        if (*c == '/') {
+            *c = '_';
+        }
+    }
+    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
+                               sanitized_name);
+    g_free(sanitized_name);
+    fd = mkstemp(filename);
+    if (fd >= 0) {
+        unlink(filename);
+        /*
+         * ftruncate is not supported by hugetlbfs in older
+         * hosts, so don't bother bailing out on errors.
+         * If anything goes wrong with it under other filesystems,
+         * mmap will fail.
+         */
+        if (ftruncate(fd, size)) {
+            perror("ftruncate");
+        }
+    }
+    g_free(filename);
+
+    return fd;
+}
+
 static void *file_ram_alloc(RAMBlock *block,
                             ram_addr_t memory,
                             const char *path,
                             Error **errp)
 {
-    char *filename;
-    char *sanitized_name;
-    char *c;
     void *area;
     int fd;
     uint64_t pagesize;
@@ -1194,38 +1240,14 @@ static void *file_ram_alloc(RAMBlock *block,
         goto error;
     }
 
-    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
-    sanitized_name = g_strdup(memory_region_name(block->mr));
-    for (c = sanitized_name; *c != '\0'; c++) {
-        if (*c == '/')
-            *c = '_';
-    }
-
-    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
-                               sanitized_name);
-    g_free(sanitized_name);
+    memory = ROUND_UP(memory, pagesize);
 
-    fd = mkstemp(filename);
+    fd = open_file_path(block, path, memory);
     if (fd < 0) {
         error_setg_errno(errp, errno,
                          "unable to create backing store for path %s", path);
-        g_free(filename);
         goto error;
     }
-    unlink(filename);
-    g_free(filename);
-
-    memory = ROUND_UP(memory, pagesize);
-
-    /*
-     * ftruncate is not supported by hugetlbfs in older
-     * hosts, so don't bother bailing out on errors.
-     * If anything goes wrong with it under other filesystems,
-     * mmap will fail.
-     */
-    if (ftruncate(fd, memory)) {
-        perror("ftruncate");
-    }
 
     area = qemu_ram_mmap(fd, memory, pagesize, block->flags & RAM_SHARED);
     if (area == MAP_FAILED) {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 10/33] hostmem-file: clean up memory allocation
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

- hostmem-file.c is compiled only if CONFIG_LINUX is enabled so that is
  unnecessary to do the same check in the source file

- the interface, HostMemoryBackendClass->alloc(), is not called many
  times, do not need to check if the memory-region is initialized

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 backends/hostmem-file.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index e9b6d21..9097a57 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -46,17 +46,12 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
         error_setg(errp, "mem-path property not set");
         return;
     }
-#ifndef CONFIG_LINUX
-    error_setg(errp, "-mem-path not supported on this host");
-#else
-    if (!memory_region_size(&backend->mr)) {
-        backend->force_prealloc = mem_prealloc;
-        memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
+
+    backend->force_prealloc = mem_prealloc;
+    memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
                                  object_get_canonical_path(OBJECT(backend)),
                                  backend->size, fb->share,
                                  fb->mem_path, errp);
-    }
-#endif
 }
 
 static void
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 10/33] hostmem-file: clean up memory allocation
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

- hostmem-file.c is compiled only if CONFIG_LINUX is enabled so that is
  unnecessary to do the same check in the source file

- the interface, HostMemoryBackendClass->alloc(), is not called many
  times, do not need to check if the memory-region is initialized

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 backends/hostmem-file.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index e9b6d21..9097a57 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -46,17 +46,12 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
         error_setg(errp, "mem-path property not set");
         return;
     }
-#ifndef CONFIG_LINUX
-    error_setg(errp, "-mem-path not supported on this host");
-#else
-    if (!memory_region_size(&backend->mr)) {
-        backend->force_prealloc = mem_prealloc;
-        memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
+
+    backend->force_prealloc = mem_prealloc;
+    memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
                                  object_get_canonical_path(OBJECT(backend)),
                                  backend->size, fb->share,
                                  fb->mem_path, errp);
-    }
-#endif
 }
 
 static void
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 11/33] hostmem-file: use whole file size if possible
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Use the whole file size if @size is not specified which is useful
if we want to directly pass a file to guest

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 backends/hostmem-file.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 9097a57..e1bc9ff 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -9,6 +9,9 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+
 #include "qemu-common.h"
 #include "sysemu/hostmem.h"
 #include "sysemu/sysemu.h"
@@ -33,20 +36,57 @@ struct HostMemoryBackendFile {
     char *mem_path;
 };
 
+static uint64_t get_file_size(const char *file)
+{
+    struct stat stat_buf;
+    uint64_t size = 0;
+    int fd;
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+        return 0;
+    }
+
+    if (stat(file, &stat_buf) < 0) {
+        goto exit;
+    }
+
+    if ((S_ISBLK(stat_buf.st_mode)) && !ioctl(fd, BLKGETSIZE64, &size)) {
+        goto exit;
+    }
+
+    size = lseek(fd, 0, SEEK_END);
+    if (size == -1) {
+        size = 0;
+    }
+exit:
+    close(fd);
+    return size;
+}
+
 static void
 file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
 {
     HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
 
-    if (!backend->size) {
-        error_setg(errp, "can't create backend with size 0");
-        return;
-    }
     if (!fb->mem_path) {
         error_setg(errp, "mem-path property not set");
         return;
     }
 
+    if (!backend->size) {
+        /*
+         * use the whole file size if @size is not specified.
+         */
+        backend->size = get_file_size(fb->mem_path);
+    }
+
+    if (!backend->size) {
+        error_setg(errp, "failed to get file size for %s, can't create "
+                         "backend on it", mem_path);
+        return;
+    }
+
     backend->force_prealloc = mem_prealloc;
     memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
                                  object_get_canonical_path(OBJECT(backend)),
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 11/33] hostmem-file: use whole file size if possible
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Use the whole file size if @size is not specified which is useful
if we want to directly pass a file to guest

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 backends/hostmem-file.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 9097a57..e1bc9ff 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -9,6 +9,9 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+
 #include "qemu-common.h"
 #include "sysemu/hostmem.h"
 #include "sysemu/sysemu.h"
@@ -33,20 +36,57 @@ struct HostMemoryBackendFile {
     char *mem_path;
 };
 
+static uint64_t get_file_size(const char *file)
+{
+    struct stat stat_buf;
+    uint64_t size = 0;
+    int fd;
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+        return 0;
+    }
+
+    if (stat(file, &stat_buf) < 0) {
+        goto exit;
+    }
+
+    if ((S_ISBLK(stat_buf.st_mode)) && !ioctl(fd, BLKGETSIZE64, &size)) {
+        goto exit;
+    }
+
+    size = lseek(fd, 0, SEEK_END);
+    if (size == -1) {
+        size = 0;
+    }
+exit:
+    close(fd);
+    return size;
+}
+
 static void
 file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
 {
     HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
 
-    if (!backend->size) {
-        error_setg(errp, "can't create backend with size 0");
-        return;
-    }
     if (!fb->mem_path) {
         error_setg(errp, "mem-path property not set");
         return;
     }
 
+    if (!backend->size) {
+        /*
+         * use the whole file size if @size is not specified.
+         */
+        backend->size = get_file_size(fb->mem_path);
+    }
+
+    if (!backend->size) {
+        error_setg(errp, "failed to get file size for %s, can't create "
+                         "backend on it", mem_path);
+        return;
+    }
+
     backend->force_prealloc = mem_prealloc;
     memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
                                  object_get_canonical_path(OBJECT(backend)),
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 12/33] pc-dimm: remove DEFAULT_PC_DIMMSIZE
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

It's not used any more

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 include/hw/mem/pc-dimm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index c1ee7b0..15590f1 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -20,8 +20,6 @@
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define DEFAULT_PC_DIMMSIZE (1024*1024*1024)
-
 #define TYPE_PC_DIMM "pc-dimm"
 #define PC_DIMM(obj) \
     OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 12/33] pc-dimm: remove DEFAULT_PC_DIMMSIZE
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

It's not used any more

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 include/hw/mem/pc-dimm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index c1ee7b0..15590f1 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -20,8 +20,6 @@
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define DEFAULT_PC_DIMMSIZE (1024*1024*1024)
-
 #define TYPE_PC_DIMM "pc-dimm"
 #define PC_DIMM(obj) \
     OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 13/33] pc-dimm: make pc_existing_dimms_capacity static and rename it
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:53   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

pc_existing_dimms_capacity() can be static since it is not used out of
pc-dimm.c and drop the pc_ prefix to prepare the work which abstracts
dimm device type from pc-dimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/pc-dimm.c         | 73 ++++++++++++++++++++++++------------------------
 include/hw/mem/pc-dimm.h |  1 -
 2 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 2bae994..425f627 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -32,6 +32,38 @@ typedef struct pc_dimms_capacity {
      Error    **errp;
 } pc_dimms_capacity;
 
+static int existing_dimms_capacity_internal(Object *obj, void *opaque)
+{
+    pc_dimms_capacity *cap = opaque;
+    uint64_t *size = &cap->size;
+
+    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+        DeviceState *dev = DEVICE(obj);
+
+        if (dev->realized) {
+            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
+                cap->errp);
+        }
+
+        if (cap->errp && *cap->errp) {
+            return 1;
+        }
+    }
+    object_child_foreach(obj, existing_dimms_capacity_internal, opaque);
+    return 0;
+}
+
+static uint64_t existing_dimms_capacity(Error **errp)
+{
+    pc_dimms_capacity cap;
+
+    cap.size = 0;
+    cap.errp = errp;
+
+    existing_dimms_capacity_internal(qdev_get_machine(), &cap);
+    return cap.size;
+}
+
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp)
@@ -40,7 +72,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     MachineState *machine = MACHINE(qdev_get_machine());
     PCDIMMDevice *dimm = PC_DIMM(dev);
     Error *local_err = NULL;
-    uint64_t existing_dimms_capacity = 0;
+    uint64_t dimms_capacity = 0;
     uint64_t addr;
 
     addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
@@ -56,17 +88,16 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
-    existing_dimms_capacity = pc_existing_dimms_capacity(&local_err);
+    dimms_capacity = existing_dimms_capacity(&local_err);
     if (local_err) {
         goto out;
     }
 
-    if (existing_dimms_capacity + memory_region_size(mr) >
+    if (dimms_capacity + memory_region_size(mr) >
         machine->maxram_size - machine->ram_size) {
         error_setg(&local_err, "not enough space, currently 0x%" PRIx64
                    " in use of total hot pluggable 0x" RAM_ADDR_FMT,
-                   existing_dimms_capacity,
-                   machine->maxram_size - machine->ram_size);
+                   dimms_capacity, machine->maxram_size - machine->ram_size);
         goto out;
     }
 
@@ -121,38 +152,6 @@ void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
     vmstate_unregister_ram(mr, dev);
 }
 
-static int pc_existing_dimms_capacity_internal(Object *obj, void *opaque)
-{
-    pc_dimms_capacity *cap = opaque;
-    uint64_t *size = &cap->size;
-
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
-        DeviceState *dev = DEVICE(obj);
-
-        if (dev->realized) {
-            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
-                cap->errp);
-        }
-
-        if (cap->errp && *cap->errp) {
-            return 1;
-        }
-    }
-    object_child_foreach(obj, pc_existing_dimms_capacity_internal, opaque);
-    return 0;
-}
-
-uint64_t pc_existing_dimms_capacity(Error **errp)
-{
-    pc_dimms_capacity cap;
-
-    cap.size = 0;
-    cap.errp = errp;
-
-    pc_existing_dimms_capacity_internal(qdev_get_machine(), &cap);
-    return cap.size;
-}
-
 int qmp_pc_dimm_device_list(Object *obj, void *opaque)
 {
     MemoryDeviceInfoList ***prev = opaque;
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 15590f1..c1e5774 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -87,7 +87,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 int qmp_pc_dimm_device_list(Object *obj, void *opaque);
-uint64_t pc_existing_dimms_capacity(Error **errp);
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 13/33] pc-dimm: make pc_existing_dimms_capacity static and rename it
@ 2015-10-19  0:53   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:53 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

pc_existing_dimms_capacity() can be static since it is not used out of
pc-dimm.c and drop the pc_ prefix to prepare the work which abstracts
dimm device type from pc-dimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/pc-dimm.c         | 73 ++++++++++++++++++++++++------------------------
 include/hw/mem/pc-dimm.h |  1 -
 2 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 2bae994..425f627 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -32,6 +32,38 @@ typedef struct pc_dimms_capacity {
      Error    **errp;
 } pc_dimms_capacity;
 
+static int existing_dimms_capacity_internal(Object *obj, void *opaque)
+{
+    pc_dimms_capacity *cap = opaque;
+    uint64_t *size = &cap->size;
+
+    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+        DeviceState *dev = DEVICE(obj);
+
+        if (dev->realized) {
+            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
+                cap->errp);
+        }
+
+        if (cap->errp && *cap->errp) {
+            return 1;
+        }
+    }
+    object_child_foreach(obj, existing_dimms_capacity_internal, opaque);
+    return 0;
+}
+
+static uint64_t existing_dimms_capacity(Error **errp)
+{
+    pc_dimms_capacity cap;
+
+    cap.size = 0;
+    cap.errp = errp;
+
+    existing_dimms_capacity_internal(qdev_get_machine(), &cap);
+    return cap.size;
+}
+
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp)
@@ -40,7 +72,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     MachineState *machine = MACHINE(qdev_get_machine());
     PCDIMMDevice *dimm = PC_DIMM(dev);
     Error *local_err = NULL;
-    uint64_t existing_dimms_capacity = 0;
+    uint64_t dimms_capacity = 0;
     uint64_t addr;
 
     addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
@@ -56,17 +88,16 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
-    existing_dimms_capacity = pc_existing_dimms_capacity(&local_err);
+    dimms_capacity = existing_dimms_capacity(&local_err);
     if (local_err) {
         goto out;
     }
 
-    if (existing_dimms_capacity + memory_region_size(mr) >
+    if (dimms_capacity + memory_region_size(mr) >
         machine->maxram_size - machine->ram_size) {
         error_setg(&local_err, "not enough space, currently 0x%" PRIx64
                    " in use of total hot pluggable 0x" RAM_ADDR_FMT,
-                   existing_dimms_capacity,
-                   machine->maxram_size - machine->ram_size);
+                   dimms_capacity, machine->maxram_size - machine->ram_size);
         goto out;
     }
 
@@ -121,38 +152,6 @@ void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
     vmstate_unregister_ram(mr, dev);
 }
 
-static int pc_existing_dimms_capacity_internal(Object *obj, void *opaque)
-{
-    pc_dimms_capacity *cap = opaque;
-    uint64_t *size = &cap->size;
-
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
-        DeviceState *dev = DEVICE(obj);
-
-        if (dev->realized) {
-            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
-                cap->errp);
-        }
-
-        if (cap->errp && *cap->errp) {
-            return 1;
-        }
-    }
-    object_child_foreach(obj, pc_existing_dimms_capacity_internal, opaque);
-    return 0;
-}
-
-uint64_t pc_existing_dimms_capacity(Error **errp)
-{
-    pc_dimms_capacity cap;
-
-    cap.size = 0;
-    cap.errp = errp;
-
-    pc_existing_dimms_capacity_internal(qdev_get_machine(), &cap);
-    return cap.size;
-}
-
 int qmp_pc_dimm_device_list(Object *obj, void *opaque)
 {
     MemoryDeviceInfoList ***prev = opaque;
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 15590f1..c1e5774 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -87,7 +87,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 int qmp_pc_dimm_device_list(Object *obj, void *opaque);
-uint64_t pc_existing_dimms_capacity(Error **errp);
 void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 14/33] pc-dimm: drop the prefix of pc-dimm
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

This patch is generated by this script:

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/PC_DIMM/DIMM/g"

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/PCDIMM/DIMM/g"

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/pc_dimm/dimm/g"

find ./ -name "trace-events" -type f | xargs sed -i "s/pc-dimm/dimm/g"

It prepares the work which abstracts dimm device type for both pc-dimm and
nvdimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hmp.c                           |   2 +-
 hw/acpi/ich9.c                  |   6 +-
 hw/acpi/memory_hotplug.c        |  16 ++---
 hw/acpi/piix4.c                 |   6 +-
 hw/i386/pc.c                    |  32 ++++-----
 hw/mem/pc-dimm.c                | 148 ++++++++++++++++++++--------------------
 hw/ppc/spapr.c                  |  18 ++---
 include/hw/mem/pc-dimm.h        |  62 ++++++++---------
 numa.c                          |   2 +-
 qapi-schema.json                |   8 +--
 qmp.c                           |   2 +-
 stubs/qmp_pc_dimm_device_list.c |   2 +-
 trace-events                    |   8 +--
 13 files changed, 156 insertions(+), 156 deletions(-)

diff --git a/hmp.c b/hmp.c
index 5048eee..5c617d2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1952,7 +1952,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
     MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err);
     MemoryDeviceInfoList *info;
     MemoryDeviceInfo *value;
-    PCDIMMDeviceInfo *di;
+    DIMMDeviceInfo *di;
 
     for (info = info_list; info; info = info->next) {
         value = info->value;
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 1c7fcfa..b0d6a67 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -440,7 +440,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
 void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
                             dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
@@ -455,7 +455,7 @@ void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
                                       Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
                                       &pm->acpi_memory_hotplug, dev, errp);
     } else {
@@ -468,7 +468,7 @@ void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
                               Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 2ff0d5c..1f6cccc 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -54,23 +54,23 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
     o = OBJECT(mdev->dimm);
     switch (addr) {
     case 0x0: /* Lo part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_ADDR_PROP, NULL) : 0;
         trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
         break;
     case 0x4: /* Hi part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
+        val = o ? object_property_get_int(o, DIMM_ADDR_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
         break;
     case 0x8: /* Lo part of DIMM size */
-        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_SIZE_PROP, NULL) : 0;
         trace_mhp_acpi_read_size_lo(mem_st->selector, val);
         break;
     case 0xc: /* Hi part of DIMM size */
-        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
+        val = o ? object_property_get_int(o, DIMM_SIZE_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_size_hi(mem_st->selector, val);
         break;
     case 0x10: /* node proximity for _PXM method */
-        val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_NODE_PROP, NULL) : 0;
         trace_mhp_acpi_read_pxm(mem_st->selector, val);
         break;
     case 0x14: /* pack and return is_* fields */
@@ -151,13 +151,13 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
             /* call pc-dimm unplug cb */
             hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
             if (local_err) {
-                trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector);
+                trace_mhp_acpi_dimm_delete_failed(mem_st->selector);
                 qapi_event_send_mem_unplug_error(dev->id,
                                                  error_get_pretty(local_err),
                                                  &error_abort);
                 break;
             }
-            trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
+            trace_mhp_acpi_dimm_deleted(mem_st->selector);
         }
         break;
     default:
@@ -206,7 +206,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
                         DeviceState *dev, Error **errp)
 {
     Error *local_err = NULL;
-    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+    int slot = object_property_get_int(OBJECT(dev), DIMM_SLOT_PROP,
                                        &local_err);
 
     if (local_err) {
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2cd2fee..0b2cb6e 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -344,7 +344,7 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_plug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
         acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
@@ -363,7 +363,7 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
                                       dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
@@ -381,7 +381,7 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 682867a..d6b9fa7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1609,15 +1609,15 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
     }
 }
 
-static void pc_dimm_plug(HotplugHandler *hotplug_dev,
+static void dimm_plug(HotplugHandler *hotplug_dev,
                          DeviceState *dev, Error **errp)
 {
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     uint64_t align = TARGET_PAGE_SIZE;
 
@@ -1631,7 +1631,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
+    dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
                         pcmc->inter_dimm_gap, &local_err);
     if (local_err) {
         goto out;
@@ -1643,7 +1643,7 @@ out:
     error_propagate(errp, local_err);
 }
 
-static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
+static void dimm_unplug_request(HotplugHandler *hotplug_dev,
                                    DeviceState *dev, Error **errp)
 {
     HotplugHandlerClass *hhc;
@@ -1663,12 +1663,12 @@ out:
     error_propagate(errp, local_err);
 }
 
-static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
+static void dimm_unplug(HotplugHandler *hotplug_dev,
                            DeviceState *dev, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
@@ -1680,7 +1680,7 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);
+    dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);
     object_unparent(OBJECT(dev));
 
  out:
@@ -1719,8 +1719,8 @@ out:
 static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
                                       DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_plug(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_plug(hotplug_dev, dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
         pc_cpu_plug(hotplug_dev, dev, errp);
     }
@@ -1729,8 +1729,8 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                                 DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_unplug_request(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_unplug_request(hotplug_dev, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug request for not supported device"
                    " type: %s", object_get_typename(OBJECT(dev)));
@@ -1740,8 +1740,8 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
 static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
                                         DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_unplug(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_unplug(hotplug_dev, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
                    " type: %s", object_get_typename(OBJECT(dev)));
@@ -1753,7 +1753,7 @@ static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
 {
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
 
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM) ||
         object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
         return HOTPLUG_HANDLER(machine);
     }
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 425f627..51f737f 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -27,21 +27,21 @@
 #include "trace.h"
 #include "hw/virtio/vhost.h"
 
-typedef struct pc_dimms_capacity {
+typedef struct dimms_capacity {
      uint64_t size;
      Error    **errp;
-} pc_dimms_capacity;
+} dimms_capacity;
 
 static int existing_dimms_capacity_internal(Object *obj, void *opaque)
 {
-    pc_dimms_capacity *cap = opaque;
+    dimms_capacity *cap = opaque;
     uint64_t *size = &cap->size;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
 
         if (dev->realized) {
-            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
+            (*size) += object_property_get_int(obj, DIMM_SIZE_PROP,
                 cap->errp);
         }
 
@@ -55,7 +55,7 @@ static int existing_dimms_capacity_internal(Object *obj, void *opaque)
 
 static uint64_t existing_dimms_capacity(Error **errp)
 {
-    pc_dimms_capacity cap;
+    dimms_capacity cap;
 
     cap.size = 0;
     cap.errp = errp;
@@ -64,23 +64,23 @@ static uint64_t existing_dimms_capacity(Error **errp)
     return cap.size;
 }
 
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp)
 {
     int slot;
     MachineState *machine = MACHINE(qdev_get_machine());
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
     Error *local_err = NULL;
     uint64_t dimms_capacity = 0;
     uint64_t addr;
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_int(OBJECT(dimm), DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
 
-    addr = pc_dimm_get_free_addr(hpms->base,
+    addr = dimm_get_free_addr(hpms->base,
                                  memory_region_size(&hpms->mr),
                                  !addr ? NULL : &addr, align, gap,
                                  memory_region_size(mr), &local_err);
@@ -101,27 +101,27 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
-    object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
+    object_property_set_int(OBJECT(dev), addr, DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
-    trace_mhp_pc_dimm_assigned_address(addr);
+    trace_mhp_dimm_assigned_address(addr);
 
-    slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err);
+    slot = object_property_get_int(OBJECT(dev), DIMM_SLOT_PROP, &local_err);
     if (local_err) {
         goto out;
     }
 
-    slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot,
+    slot = dimm_get_free_slot(slot == DIMM_UNASSIGNED_SLOT ? NULL : &slot,
                                  machine->ram_slots, &local_err);
     if (local_err) {
         goto out;
     }
-    object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err);
+    object_property_set_int(OBJECT(dev), slot, DIMM_SLOT_PROP, &local_err);
     if (local_err) {
         goto out;
     }
-    trace_mhp_pc_dimm_assigned_slot(slot);
+    trace_mhp_dimm_assigned_slot(slot);
 
     if (kvm_enabled() && !kvm_has_free_slot(machine)) {
         error_setg(&local_err, "hypervisor has no free memory slots left");
@@ -142,29 +142,29 @@ out:
     error_propagate(errp, local_err);
 }
 
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr)
 {
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
 
     numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);
     memory_region_del_subregion(&hpms->mr, mr);
     vmstate_unregister_ram(mr, dev);
 }
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque)
+int qmp_dimm_device_list(Object *obj, void *opaque)
 {
     MemoryDeviceInfoList ***prev = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
 
         if (dev->realized) {
             MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1);
             MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
-            PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);
+            DIMMDeviceInfo *di = g_new0(DIMMDeviceInfo, 1);
             DeviceClass *dc = DEVICE_GET_CLASS(obj);
-            PCDIMMDevice *dimm = PC_DIMM(obj);
+            DIMMDevice *dimm = DIMM(obj);
 
             if (dev->id) {
                 di->has_id = true;
@@ -175,7 +175,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
             di->addr = dimm->addr;
             di->slot = dimm->slot;
             di->node = dimm->node;
-            di->size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
+            di->size = object_property_get_int(OBJECT(dimm), DIMM_SIZE_PROP,
                                                NULL);
             di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
 
@@ -187,7 +187,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
         }
     }
 
-    object_child_foreach(obj, qmp_pc_dimm_device_list, opaque);
+    object_child_foreach(obj, qmp_dimm_device_list, opaque);
     return 0;
 }
 
@@ -198,7 +198,7 @@ ram_addr_t get_current_ram_size(void)
     MemoryDeviceInfoList *info;
     ram_addr_t size = ram_size;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
     for (info = info_list; info; info = info->next) {
         MemoryDeviceInfo *value = info->value;
 
@@ -217,28 +217,28 @@ ram_addr_t get_current_ram_size(void)
     return size;
 }
 
-static int pc_dimm_slot2bitmap(Object *obj, void *opaque)
+static int dimm_slot2bitmap(Object *obj, void *opaque)
 {
     unsigned long *bitmap = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
         if (dev->realized) { /* count only realized DIMMs */
-            PCDIMMDevice *d = PC_DIMM(obj);
+            DIMMDevice *d = DIMM(obj);
             set_bit(d->slot, bitmap);
         }
     }
 
-    object_child_foreach(obj, pc_dimm_slot2bitmap, opaque);
+    object_child_foreach(obj, dimm_slot2bitmap, opaque);
     return 0;
 }
 
-int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp)
+int dimm_get_free_slot(const int *hint, int max_slots, Error **errp)
 {
     unsigned long *bitmap = bitmap_new(max_slots);
     int slot = 0;
 
-    object_child_foreach(qdev_get_machine(), pc_dimm_slot2bitmap, bitmap);
+    object_child_foreach(qdev_get_machine(), dimm_slot2bitmap, bitmap);
 
     /* check if requested slot is not occupied */
     if (hint) {
@@ -263,10 +263,10 @@ out:
     return slot;
 }
 
-static gint pc_dimm_addr_sort(gconstpointer a, gconstpointer b)
+static gint dimm_addr_sort(gconstpointer a, gconstpointer b)
 {
-    PCDIMMDevice *x = PC_DIMM(a);
-    PCDIMMDevice *y = PC_DIMM(b);
+    DIMMDevice *x = DIMM(a);
+    DIMMDevice *y = DIMM(b);
     Int128 diff = int128_sub(int128_make64(x->addr), int128_make64(y->addr));
 
     if (int128_lt(diff, int128_zero())) {
@@ -277,22 +277,22 @@ static gint pc_dimm_addr_sort(gconstpointer a, gconstpointer b)
     return 0;
 }
 
-static int pc_dimm_built_list(Object *obj, void *opaque)
+static int dimm_built_list(Object *obj, void *opaque)
 {
     GSList **list = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
         if (dev->realized) { /* only realized DIMMs matter */
-            *list = g_slist_insert_sorted(*list, dev, pc_dimm_addr_sort);
+            *list = g_slist_insert_sorted(*list, dev, dimm_addr_sort);
         }
     }
 
-    object_child_foreach(obj, pc_dimm_built_list, opaque);
+    object_child_foreach(obj, dimm_built_list, opaque);
     return 0;
 }
 
-uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
+uint64_t dimm_get_free_addr(uint64_t address_space_start,
                                uint64_t address_space_size,
                                uint64_t *hint, uint64_t align, bool gap,
                                uint64_t size, Error **errp)
@@ -322,7 +322,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
     }
 
     assert(address_space_end > address_space_start);
-    object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list);
+    object_child_foreach(qdev_get_machine(), dimm_built_list, &list);
 
     if (hint) {
         new_addr = *hint;
@@ -332,9 +332,9 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 
     /* find address range that will fit new DIMM */
     for (item = list; item; item = g_slist_next(item)) {
-        PCDIMMDevice *dimm = item->data;
+        DIMMDevice *dimm = item->data;
         uint64_t dimm_size = object_property_get_int(OBJECT(dimm),
-                                                     PC_DIMM_SIZE_PROP,
+                                                     DIMM_SIZE_PROP,
                                                      errp);
         if (errp && *errp) {
             goto out;
@@ -366,20 +366,20 @@ out:
     return ret;
 }
 
-static Property pc_dimm_properties[] = {
-    DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
-    DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
-    DEFINE_PROP_INT32(PC_DIMM_SLOT_PROP, PCDIMMDevice, slot,
-                      PC_DIMM_UNASSIGNED_SLOT),
+static Property dimm_properties[] = {
+    DEFINE_PROP_UINT64(DIMM_ADDR_PROP, DIMMDevice, addr, 0),
+    DEFINE_PROP_UINT32(DIMM_NODE_PROP, DIMMDevice, node, 0),
+    DEFINE_PROP_INT32(DIMM_SLOT_PROP, DIMMDevice, slot,
+                      DIMM_UNASSIGNED_SLOT),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
+static void dimm_get_size(Object *obj, Visitor *v, void *opaque,
                           const char *name, Error **errp)
 {
     int64_t value;
     MemoryRegion *mr;
-    PCDIMMDevice *dimm = PC_DIMM(obj);
+    DIMMDevice *dimm = DIMM(obj);
 
     mr = host_memory_backend_get_memory(dimm->hostmem, errp);
     value = memory_region_size(mr);
@@ -387,7 +387,7 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
     visit_type_int(v, &value, name, errp);
 }
 
-static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
+static void dimm_check_memdev_is_busy(Object *obj, const char *name,
                                       Object *val, Error **errp)
 {
     MemoryRegion *mr;
@@ -402,65 +402,65 @@ static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
     }
 }
 
-static void pc_dimm_init(Object *obj)
+static void dimm_init(Object *obj)
 {
-    PCDIMMDevice *dimm = PC_DIMM(obj);
+    DIMMDevice *dimm = DIMM(obj);
 
-    object_property_add(obj, PC_DIMM_SIZE_PROP, "int", pc_dimm_get_size,
+    object_property_add(obj, DIMM_SIZE_PROP, "int", dimm_get_size,
                         NULL, NULL, NULL, &error_abort);
-    object_property_add_link(obj, PC_DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND,
+    object_property_add_link(obj, DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND,
                              (Object **)&dimm->hostmem,
-                             pc_dimm_check_memdev_is_busy,
+                             dimm_check_memdev_is_busy,
                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
                              &error_abort);
 }
 
-static void pc_dimm_realize(DeviceState *dev, Error **errp)
+static void dimm_realize(DeviceState *dev, Error **errp)
 {
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
 
     if (!dimm->hostmem) {
-        error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
+        error_setg(errp, "'" DIMM_MEMDEV_PROP "' property is not set");
         return;
     }
     if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
         (!nb_numa_nodes && dimm->node)) {
-        error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
+        error_setg(errp, "'DIMM property " DIMM_NODE_PROP " has value %"
                    PRIu32 "' which exceeds the number of numa nodes: %d",
                    dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
         return;
     }
 }
 
-static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
+static MemoryRegion *dimm_get_memory_region(DIMMDevice *dimm)
 {
     return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
 }
 
-static void pc_dimm_class_init(ObjectClass *oc, void *data)
+static void dimm_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
-    PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
 
-    dc->realize = pc_dimm_realize;
-    dc->props = pc_dimm_properties;
+    dc->realize = dimm_realize;
+    dc->props = dimm_properties;
     dc->desc = "DIMM memory module";
 
-    ddc->get_memory_region = pc_dimm_get_memory_region;
+    ddc->get_memory_region = dimm_get_memory_region;
 }
 
-static TypeInfo pc_dimm_info = {
-    .name          = TYPE_PC_DIMM,
+static TypeInfo dimm_info = {
+    .name          = TYPE_DIMM,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(PCDIMMDevice),
-    .instance_init = pc_dimm_init,
-    .class_init    = pc_dimm_class_init,
-    .class_size    = sizeof(PCDIMMDeviceClass),
+    .instance_size = sizeof(DIMMDevice),
+    .instance_init = dimm_init,
+    .class_init    = dimm_class_init,
+    .class_size    = sizeof(DIMMDeviceClass),
 };
 
-static void pc_dimm_register_types(void)
+static void dimm_register_types(void)
 {
-    type_register_static(&pc_dimm_info);
+    type_register_static(&dimm_info);
 }
 
-type_init(pc_dimm_register_types)
+type_init(dimm_register_types)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d1b0e53..4fb91a5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2083,8 +2083,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
 {
     Error *local_err = NULL;
     sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     uint64_t align = memory_region_get_alignment(mr);
     uint64_t size = memory_region_size(mr);
@@ -2096,14 +2096,14 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err);
+    dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err);
     if (local_err) {
         goto out;
     }
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_int(OBJECT(dimm), DIMM_ADDR_PROP, &local_err);
     if (local_err) {
-        pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
+        dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
         goto out;
     }
 
@@ -2118,14 +2118,14 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
 {
     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine());
 
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         int node;
 
         if (!smc->dr_lmb_enabled) {
             error_setg(errp, "Memory hotplug not supported for this machine");
             return;
         }
-        node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
+        node = object_property_get_int(OBJECT(dev), DIMM_NODE_PROP, errp);
         if (*errp) {
             return;
         }
@@ -2159,7 +2159,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
 static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
                                       DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         error_setg(errp, "Memory hot unplug not supported by sPAPR");
     }
 }
@@ -2167,7 +2167,7 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
 static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine,
                                              DeviceState *dev)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         return HOTPLUG_HANDLER(machine);
     }
     return NULL;
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index c1e5774..5ddbf08 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -13,39 +13,39 @@
  *
  */
 
-#ifndef QEMU_PC_DIMM_H
-#define QEMU_PC_DIMM_H
+#ifndef QEMU_DIMM_H
+#define QEMU_DIMM_H
 
 #include "exec/memory.h"
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define TYPE_PC_DIMM "pc-dimm"
-#define PC_DIMM(obj) \
-    OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-#define PC_DIMM_CLASS(oc) \
-    OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM)
-#define PC_DIMM_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM)
+#define TYPE_DIMM "pc-dimm"
+#define DIMM(obj) \
+    OBJECT_CHECK(DIMMDevice, (obj), TYPE_DIMM)
+#define DIMM_CLASS(oc) \
+    OBJECT_CLASS_CHECK(DIMMDeviceClass, (oc), TYPE_DIMM)
+#define DIMM_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(DIMMDeviceClass, (obj), TYPE_DIMM)
 
-#define PC_DIMM_ADDR_PROP "addr"
-#define PC_DIMM_SLOT_PROP "slot"
-#define PC_DIMM_NODE_PROP "node"
-#define PC_DIMM_SIZE_PROP "size"
-#define PC_DIMM_MEMDEV_PROP "memdev"
+#define DIMM_ADDR_PROP "addr"
+#define DIMM_SLOT_PROP "slot"
+#define DIMM_NODE_PROP "node"
+#define DIMM_SIZE_PROP "size"
+#define DIMM_MEMDEV_PROP "memdev"
 
-#define PC_DIMM_UNASSIGNED_SLOT -1
+#define DIMM_UNASSIGNED_SLOT -1
 
 /**
- * PCDIMMDevice:
- * @addr: starting guest physical address, where @PCDIMMDevice is mapped.
+ * DIMMDevice:
+ * @addr: starting guest physical address, where @DIMMDevice is mapped.
  *         Default value: 0, means that address is auto-allocated.
- * @node: numa node to which @PCDIMMDevice is attached.
- * @slot: slot number into which @PCDIMMDevice is plugged in.
+ * @node: numa node to which @DIMMDevice is attached.
+ * @slot: slot number into which @DIMMDevice is plugged in.
  *        Default value: -1, means that slot is auto-allocated.
- * @hostmem: host memory backend providing memory for @PCDIMMDevice
+ * @hostmem: host memory backend providing memory for @DIMMDevice
  */
-typedef struct PCDIMMDevice {
+typedef struct DIMMDevice {
     /* private */
     DeviceState parent_obj;
 
@@ -54,19 +54,19 @@ typedef struct PCDIMMDevice {
     uint32_t node;
     int32_t slot;
     HostMemoryBackend *hostmem;
-} PCDIMMDevice;
+} DIMMDevice;
 
 /**
- * PCDIMMDeviceClass:
+ * DIMMDeviceClass:
  * @get_memory_region: returns #MemoryRegion associated with @dimm
  */
-typedef struct PCDIMMDeviceClass {
+typedef struct DIMMDeviceClass {
     /* private */
     DeviceClass parent_class;
 
     /* public */
-    MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm);
-} PCDIMMDeviceClass;
+    MemoryRegion *(*get_memory_region)(DIMMDevice *dimm);
+} DIMMDeviceClass;
 
 /**
  * MemoryHotplugState:
@@ -79,17 +79,17 @@ typedef struct MemoryHotplugState {
     MemoryRegion mr;
 } MemoryHotplugState;
 
-uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
+uint64_t dimm_get_free_addr(uint64_t address_space_start,
                                uint64_t address_space_size,
                                uint64_t *hint, uint64_t align, bool gap,
                                uint64_t size, Error **errp);
 
-int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
+int dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque);
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+int qmp_dimm_device_list(Object *obj, void *opaque);
+void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp);
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr);
 #endif
diff --git a/numa.c b/numa.c
index e9b18f5..cb69965 100644
--- a/numa.c
+++ b/numa.c
@@ -482,7 +482,7 @@ static void numa_stat_memory_devices(uint64_t node_mem[])
     MemoryDeviceInfoList **prev = &info_list;
     MemoryDeviceInfoList *info;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
     for (info = info_list; info; info = info->next) {
         MemoryDeviceInfo *value = info->value;
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 8b0520c..d8dd8b9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3684,9 +3684,9 @@
 { 'command': 'query-memdev', 'returns': ['Memdev'] }
 
 ##
-# @PCDIMMDeviceInfo:
+# @DIMMDeviceInfo:
 #
-# PCDIMMDevice state information
+# DIMMDevice state information
 #
 # @id: #optional device's ID
 #
@@ -3706,7 +3706,7 @@
 #
 # Since: 2.1
 ##
-{ 'struct': 'PCDIMMDeviceInfo',
+{ 'struct': 'DIMMDeviceInfo',
   'data': { '*id': 'str',
             'addr': 'int',
             'size': 'int',
@@ -3725,7 +3725,7 @@
 #
 # Since: 2.1
 ##
-{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} }
+{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'DIMMDeviceInfo'} }
 
 ##
 # @query-memory-devices
diff --git a/qmp.c b/qmp.c
index 057a7cb..6709aea 100644
--- a/qmp.c
+++ b/qmp.c
@@ -699,7 +699,7 @@ MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
     MemoryDeviceInfoList *head = NULL;
     MemoryDeviceInfoList **prev = &head;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
 
     return head;
 }
diff --git a/stubs/qmp_pc_dimm_device_list.c b/stubs/qmp_pc_dimm_device_list.c
index b584bd8..b2704c6 100644
--- a/stubs/qmp_pc_dimm_device_list.c
+++ b/stubs/qmp_pc_dimm_device_list.c
@@ -1,7 +1,7 @@
 #include "qom/object.h"
 #include "hw/mem/pc-dimm.h"
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque)
+int qmp_dimm_device_list(Object *obj, void *opaque)
 {
    return 0;
 }
diff --git a/trace-events b/trace-events
index b813ae4..06c76f2 100644
--- a/trace-events
+++ b/trace-events
@@ -1639,12 +1639,12 @@ mhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "slot[0x%"PRIx32"] OST EVENT:
 mhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "slot[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
 mhp_acpi_clear_insert_evt(uint32_t slot) "slot[0x%"PRIx32"] clear insert event"
 mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event"
-mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted"
-mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed"
+mhp_acpi_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] dimm deleted"
+mhp_acpi_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] dimm delete failed"
 
 # hw/i386/pc.c
-mhp_pc_dimm_assigned_slot(int slot) "0x%d"
-mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
+mhp_dimm_assigned_slot(int slot) "0x%d"
+mhp_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
 
 # target-s390x/kvm.c
 kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 14/33] pc-dimm: drop the prefix of pc-dimm
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

This patch is generated by this script:

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/PC_DIMM/DIMM/g"

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/PCDIMM/DIMM/g"

find ./ -name "*.[ch]" -o -name "*.json" -o -name "trace-events" -type f \
| xargs sed -i "s/pc_dimm/dimm/g"

find ./ -name "trace-events" -type f | xargs sed -i "s/pc-dimm/dimm/g"

It prepares the work which abstracts dimm device type for both pc-dimm and
nvdimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hmp.c                           |   2 +-
 hw/acpi/ich9.c                  |   6 +-
 hw/acpi/memory_hotplug.c        |  16 ++---
 hw/acpi/piix4.c                 |   6 +-
 hw/i386/pc.c                    |  32 ++++-----
 hw/mem/pc-dimm.c                | 148 ++++++++++++++++++++--------------------
 hw/ppc/spapr.c                  |  18 ++---
 include/hw/mem/pc-dimm.h        |  62 ++++++++---------
 numa.c                          |   2 +-
 qapi-schema.json                |   8 +--
 qmp.c                           |   2 +-
 stubs/qmp_pc_dimm_device_list.c |   2 +-
 trace-events                    |   8 +--
 13 files changed, 156 insertions(+), 156 deletions(-)

diff --git a/hmp.c b/hmp.c
index 5048eee..5c617d2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1952,7 +1952,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
     MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err);
     MemoryDeviceInfoList *info;
     MemoryDeviceInfo *value;
-    PCDIMMDeviceInfo *di;
+    DIMMDeviceInfo *di;
 
     for (info = info_list; info; info = info->next) {
         value = info->value;
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 1c7fcfa..b0d6a67 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -440,7 +440,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
 void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
                             dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
@@ -455,7 +455,7 @@ void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
                                       Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
                                       &pm->acpi_memory_hotplug, dev, errp);
     } else {
@@ -468,7 +468,7 @@ void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
                               Error **errp)
 {
     if (pm->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 2ff0d5c..1f6cccc 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -54,23 +54,23 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
     o = OBJECT(mdev->dimm);
     switch (addr) {
     case 0x0: /* Lo part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_ADDR_PROP, NULL) : 0;
         trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
         break;
     case 0x4: /* Hi part of phys address where DIMM is mapped */
-        val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
+        val = o ? object_property_get_int(o, DIMM_ADDR_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
         break;
     case 0x8: /* Lo part of DIMM size */
-        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_SIZE_PROP, NULL) : 0;
         trace_mhp_acpi_read_size_lo(mem_st->selector, val);
         break;
     case 0xc: /* Hi part of DIMM size */
-        val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
+        val = o ? object_property_get_int(o, DIMM_SIZE_PROP, NULL) >> 32 : 0;
         trace_mhp_acpi_read_size_hi(mem_st->selector, val);
         break;
     case 0x10: /* node proximity for _PXM method */
-        val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
+        val = o ? object_property_get_int(o, DIMM_NODE_PROP, NULL) : 0;
         trace_mhp_acpi_read_pxm(mem_st->selector, val);
         break;
     case 0x14: /* pack and return is_* fields */
@@ -151,13 +151,13 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
             /* call pc-dimm unplug cb */
             hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
             if (local_err) {
-                trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector);
+                trace_mhp_acpi_dimm_delete_failed(mem_st->selector);
                 qapi_event_send_mem_unplug_error(dev->id,
                                                  error_get_pretty(local_err),
                                                  &error_abort);
                 break;
             }
-            trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
+            trace_mhp_acpi_dimm_deleted(mem_st->selector);
         }
         break;
     default:
@@ -206,7 +206,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
                         DeviceState *dev, Error **errp)
 {
     Error *local_err = NULL;
-    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+    int slot = object_property_get_int(OBJECT(dev), DIMM_SLOT_PROP,
                                        &local_err);
 
     if (local_err) {
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2cd2fee..0b2cb6e 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -344,7 +344,7 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_plug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
         acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
@@ -363,7 +363,7 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
                                       dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
@@ -381,7 +381,7 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
     PIIX4PMState *s = PIIX4_PM(hotplug_dev);
 
     if (s->acpi_memory_hotplug.is_enabled &&
-        object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 682867a..d6b9fa7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1609,15 +1609,15 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
     }
 }
 
-static void pc_dimm_plug(HotplugHandler *hotplug_dev,
+static void dimm_plug(HotplugHandler *hotplug_dev,
                          DeviceState *dev, Error **errp)
 {
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     uint64_t align = TARGET_PAGE_SIZE;
 
@@ -1631,7 +1631,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
+    dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
                         pcmc->inter_dimm_gap, &local_err);
     if (local_err) {
         goto out;
@@ -1643,7 +1643,7 @@ out:
     error_propagate(errp, local_err);
 }
 
-static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
+static void dimm_unplug_request(HotplugHandler *hotplug_dev,
                                    DeviceState *dev, Error **errp)
 {
     HotplugHandlerClass *hhc;
@@ -1663,12 +1663,12 @@ out:
     error_propagate(errp, local_err);
 }
 
-static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
+static void dimm_unplug(HotplugHandler *hotplug_dev,
                            DeviceState *dev, Error **errp)
 {
     PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     HotplugHandlerClass *hhc;
     Error *local_err = NULL;
@@ -1680,7 +1680,7 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
         goto out;
     }
 
-    pc_dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);
+    dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);
     object_unparent(OBJECT(dev));
 
  out:
@@ -1719,8 +1719,8 @@ out:
 static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
                                       DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_plug(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_plug(hotplug_dev, dev, errp);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
         pc_cpu_plug(hotplug_dev, dev, errp);
     }
@@ -1729,8 +1729,8 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                                 DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_unplug_request(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_unplug_request(hotplug_dev, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug request for not supported device"
                    " type: %s", object_get_typename(OBJECT(dev)));
@@ -1740,8 +1740,8 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
 static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
                                         DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        pc_dimm_unplug(hotplug_dev, dev, errp);
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
+        dimm_unplug(hotplug_dev, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug for not supported device"
                    " type: %s", object_get_typename(OBJECT(dev)));
@@ -1753,7 +1753,7 @@ static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
 {
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
 
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM) ||
         object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
         return HOTPLUG_HANDLER(machine);
     }
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 425f627..51f737f 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -27,21 +27,21 @@
 #include "trace.h"
 #include "hw/virtio/vhost.h"
 
-typedef struct pc_dimms_capacity {
+typedef struct dimms_capacity {
      uint64_t size;
      Error    **errp;
-} pc_dimms_capacity;
+} dimms_capacity;
 
 static int existing_dimms_capacity_internal(Object *obj, void *opaque)
 {
-    pc_dimms_capacity *cap = opaque;
+    dimms_capacity *cap = opaque;
     uint64_t *size = &cap->size;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
 
         if (dev->realized) {
-            (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
+            (*size) += object_property_get_int(obj, DIMM_SIZE_PROP,
                 cap->errp);
         }
 
@@ -55,7 +55,7 @@ static int existing_dimms_capacity_internal(Object *obj, void *opaque)
 
 static uint64_t existing_dimms_capacity(Error **errp)
 {
-    pc_dimms_capacity cap;
+    dimms_capacity cap;
 
     cap.size = 0;
     cap.errp = errp;
@@ -64,23 +64,23 @@ static uint64_t existing_dimms_capacity(Error **errp)
     return cap.size;
 }
 
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp)
 {
     int slot;
     MachineState *machine = MACHINE(qdev_get_machine());
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
     Error *local_err = NULL;
     uint64_t dimms_capacity = 0;
     uint64_t addr;
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_int(OBJECT(dimm), DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
 
-    addr = pc_dimm_get_free_addr(hpms->base,
+    addr = dimm_get_free_addr(hpms->base,
                                  memory_region_size(&hpms->mr),
                                  !addr ? NULL : &addr, align, gap,
                                  memory_region_size(mr), &local_err);
@@ -101,27 +101,27 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
         goto out;
     }
 
-    object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
+    object_property_set_int(OBJECT(dev), addr, DIMM_ADDR_PROP, &local_err);
     if (local_err) {
         goto out;
     }
-    trace_mhp_pc_dimm_assigned_address(addr);
+    trace_mhp_dimm_assigned_address(addr);
 
-    slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err);
+    slot = object_property_get_int(OBJECT(dev), DIMM_SLOT_PROP, &local_err);
     if (local_err) {
         goto out;
     }
 
-    slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot,
+    slot = dimm_get_free_slot(slot == DIMM_UNASSIGNED_SLOT ? NULL : &slot,
                                  machine->ram_slots, &local_err);
     if (local_err) {
         goto out;
     }
-    object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err);
+    object_property_set_int(OBJECT(dev), slot, DIMM_SLOT_PROP, &local_err);
     if (local_err) {
         goto out;
     }
-    trace_mhp_pc_dimm_assigned_slot(slot);
+    trace_mhp_dimm_assigned_slot(slot);
 
     if (kvm_enabled() && !kvm_has_free_slot(machine)) {
         error_setg(&local_err, "hypervisor has no free memory slots left");
@@ -142,29 +142,29 @@ out:
     error_propagate(errp, local_err);
 }
 
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr)
 {
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
 
     numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);
     memory_region_del_subregion(&hpms->mr, mr);
     vmstate_unregister_ram(mr, dev);
 }
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque)
+int qmp_dimm_device_list(Object *obj, void *opaque)
 {
     MemoryDeviceInfoList ***prev = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
 
         if (dev->realized) {
             MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1);
             MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
-            PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1);
+            DIMMDeviceInfo *di = g_new0(DIMMDeviceInfo, 1);
             DeviceClass *dc = DEVICE_GET_CLASS(obj);
-            PCDIMMDevice *dimm = PC_DIMM(obj);
+            DIMMDevice *dimm = DIMM(obj);
 
             if (dev->id) {
                 di->has_id = true;
@@ -175,7 +175,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
             di->addr = dimm->addr;
             di->slot = dimm->slot;
             di->node = dimm->node;
-            di->size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
+            di->size = object_property_get_int(OBJECT(dimm), DIMM_SIZE_PROP,
                                                NULL);
             di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
 
@@ -187,7 +187,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
         }
     }
 
-    object_child_foreach(obj, qmp_pc_dimm_device_list, opaque);
+    object_child_foreach(obj, qmp_dimm_device_list, opaque);
     return 0;
 }
 
@@ -198,7 +198,7 @@ ram_addr_t get_current_ram_size(void)
     MemoryDeviceInfoList *info;
     ram_addr_t size = ram_size;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
     for (info = info_list; info; info = info->next) {
         MemoryDeviceInfo *value = info->value;
 
@@ -217,28 +217,28 @@ ram_addr_t get_current_ram_size(void)
     return size;
 }
 
-static int pc_dimm_slot2bitmap(Object *obj, void *opaque)
+static int dimm_slot2bitmap(Object *obj, void *opaque)
 {
     unsigned long *bitmap = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
         if (dev->realized) { /* count only realized DIMMs */
-            PCDIMMDevice *d = PC_DIMM(obj);
+            DIMMDevice *d = DIMM(obj);
             set_bit(d->slot, bitmap);
         }
     }
 
-    object_child_foreach(obj, pc_dimm_slot2bitmap, opaque);
+    object_child_foreach(obj, dimm_slot2bitmap, opaque);
     return 0;
 }
 
-int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp)
+int dimm_get_free_slot(const int *hint, int max_slots, Error **errp)
 {
     unsigned long *bitmap = bitmap_new(max_slots);
     int slot = 0;
 
-    object_child_foreach(qdev_get_machine(), pc_dimm_slot2bitmap, bitmap);
+    object_child_foreach(qdev_get_machine(), dimm_slot2bitmap, bitmap);
 
     /* check if requested slot is not occupied */
     if (hint) {
@@ -263,10 +263,10 @@ out:
     return slot;
 }
 
-static gint pc_dimm_addr_sort(gconstpointer a, gconstpointer b)
+static gint dimm_addr_sort(gconstpointer a, gconstpointer b)
 {
-    PCDIMMDevice *x = PC_DIMM(a);
-    PCDIMMDevice *y = PC_DIMM(b);
+    DIMMDevice *x = DIMM(a);
+    DIMMDevice *y = DIMM(b);
     Int128 diff = int128_sub(int128_make64(x->addr), int128_make64(y->addr));
 
     if (int128_lt(diff, int128_zero())) {
@@ -277,22 +277,22 @@ static gint pc_dimm_addr_sort(gconstpointer a, gconstpointer b)
     return 0;
 }
 
-static int pc_dimm_built_list(Object *obj, void *opaque)
+static int dimm_built_list(Object *obj, void *opaque)
 {
     GSList **list = opaque;
 
-    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(obj, TYPE_DIMM)) {
         DeviceState *dev = DEVICE(obj);
         if (dev->realized) { /* only realized DIMMs matter */
-            *list = g_slist_insert_sorted(*list, dev, pc_dimm_addr_sort);
+            *list = g_slist_insert_sorted(*list, dev, dimm_addr_sort);
         }
     }
 
-    object_child_foreach(obj, pc_dimm_built_list, opaque);
+    object_child_foreach(obj, dimm_built_list, opaque);
     return 0;
 }
 
-uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
+uint64_t dimm_get_free_addr(uint64_t address_space_start,
                                uint64_t address_space_size,
                                uint64_t *hint, uint64_t align, bool gap,
                                uint64_t size, Error **errp)
@@ -322,7 +322,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
     }
 
     assert(address_space_end > address_space_start);
-    object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list);
+    object_child_foreach(qdev_get_machine(), dimm_built_list, &list);
 
     if (hint) {
         new_addr = *hint;
@@ -332,9 +332,9 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 
     /* find address range that will fit new DIMM */
     for (item = list; item; item = g_slist_next(item)) {
-        PCDIMMDevice *dimm = item->data;
+        DIMMDevice *dimm = item->data;
         uint64_t dimm_size = object_property_get_int(OBJECT(dimm),
-                                                     PC_DIMM_SIZE_PROP,
+                                                     DIMM_SIZE_PROP,
                                                      errp);
         if (errp && *errp) {
             goto out;
@@ -366,20 +366,20 @@ out:
     return ret;
 }
 
-static Property pc_dimm_properties[] = {
-    DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
-    DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
-    DEFINE_PROP_INT32(PC_DIMM_SLOT_PROP, PCDIMMDevice, slot,
-                      PC_DIMM_UNASSIGNED_SLOT),
+static Property dimm_properties[] = {
+    DEFINE_PROP_UINT64(DIMM_ADDR_PROP, DIMMDevice, addr, 0),
+    DEFINE_PROP_UINT32(DIMM_NODE_PROP, DIMMDevice, node, 0),
+    DEFINE_PROP_INT32(DIMM_SLOT_PROP, DIMMDevice, slot,
+                      DIMM_UNASSIGNED_SLOT),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
+static void dimm_get_size(Object *obj, Visitor *v, void *opaque,
                           const char *name, Error **errp)
 {
     int64_t value;
     MemoryRegion *mr;
-    PCDIMMDevice *dimm = PC_DIMM(obj);
+    DIMMDevice *dimm = DIMM(obj);
 
     mr = host_memory_backend_get_memory(dimm->hostmem, errp);
     value = memory_region_size(mr);
@@ -387,7 +387,7 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
     visit_type_int(v, &value, name, errp);
 }
 
-static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
+static void dimm_check_memdev_is_busy(Object *obj, const char *name,
                                       Object *val, Error **errp)
 {
     MemoryRegion *mr;
@@ -402,65 +402,65 @@ static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
     }
 }
 
-static void pc_dimm_init(Object *obj)
+static void dimm_init(Object *obj)
 {
-    PCDIMMDevice *dimm = PC_DIMM(obj);
+    DIMMDevice *dimm = DIMM(obj);
 
-    object_property_add(obj, PC_DIMM_SIZE_PROP, "int", pc_dimm_get_size,
+    object_property_add(obj, DIMM_SIZE_PROP, "int", dimm_get_size,
                         NULL, NULL, NULL, &error_abort);
-    object_property_add_link(obj, PC_DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND,
+    object_property_add_link(obj, DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND,
                              (Object **)&dimm->hostmem,
-                             pc_dimm_check_memdev_is_busy,
+                             dimm_check_memdev_is_busy,
                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
                              &error_abort);
 }
 
-static void pc_dimm_realize(DeviceState *dev, Error **errp)
+static void dimm_realize(DeviceState *dev, Error **errp)
 {
-    PCDIMMDevice *dimm = PC_DIMM(dev);
+    DIMMDevice *dimm = DIMM(dev);
 
     if (!dimm->hostmem) {
-        error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
+        error_setg(errp, "'" DIMM_MEMDEV_PROP "' property is not set");
         return;
     }
     if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
         (!nb_numa_nodes && dimm->node)) {
-        error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
+        error_setg(errp, "'DIMM property " DIMM_NODE_PROP " has value %"
                    PRIu32 "' which exceeds the number of numa nodes: %d",
                    dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
         return;
     }
 }
 
-static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
+static MemoryRegion *dimm_get_memory_region(DIMMDevice *dimm)
 {
     return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
 }
 
-static void pc_dimm_class_init(ObjectClass *oc, void *data)
+static void dimm_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
-    PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
 
-    dc->realize = pc_dimm_realize;
-    dc->props = pc_dimm_properties;
+    dc->realize = dimm_realize;
+    dc->props = dimm_properties;
     dc->desc = "DIMM memory module";
 
-    ddc->get_memory_region = pc_dimm_get_memory_region;
+    ddc->get_memory_region = dimm_get_memory_region;
 }
 
-static TypeInfo pc_dimm_info = {
-    .name          = TYPE_PC_DIMM,
+static TypeInfo dimm_info = {
+    .name          = TYPE_DIMM,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(PCDIMMDevice),
-    .instance_init = pc_dimm_init,
-    .class_init    = pc_dimm_class_init,
-    .class_size    = sizeof(PCDIMMDeviceClass),
+    .instance_size = sizeof(DIMMDevice),
+    .instance_init = dimm_init,
+    .class_init    = dimm_class_init,
+    .class_size    = sizeof(DIMMDeviceClass),
 };
 
-static void pc_dimm_register_types(void)
+static void dimm_register_types(void)
 {
-    type_register_static(&pc_dimm_info);
+    type_register_static(&dimm_info);
 }
 
-type_init(pc_dimm_register_types)
+type_init(dimm_register_types)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d1b0e53..4fb91a5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2083,8 +2083,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
 {
     Error *local_err = NULL;
     sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
-    PCDIMMDevice *dimm = PC_DIMM(dev);
-    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
     MemoryRegion *mr = ddc->get_memory_region(dimm);
     uint64_t align = memory_region_get_alignment(mr);
     uint64_t size = memory_region_size(mr);
@@ -2096,14 +2096,14 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
         goto out;
     }
 
-    pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err);
+    dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err);
     if (local_err) {
         goto out;
     }
 
-    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
+    addr = object_property_get_int(OBJECT(dimm), DIMM_ADDR_PROP, &local_err);
     if (local_err) {
-        pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
+        dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
         goto out;
     }
 
@@ -2118,14 +2118,14 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
 {
     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine());
 
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         int node;
 
         if (!smc->dr_lmb_enabled) {
             error_setg(errp, "Memory hotplug not supported for this machine");
             return;
         }
-        node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
+        node = object_property_get_int(OBJECT(dev), DIMM_NODE_PROP, errp);
         if (*errp) {
             return;
         }
@@ -2159,7 +2159,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
 static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
                                       DeviceState *dev, Error **errp)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         error_setg(errp, "Memory hot unplug not supported by sPAPR");
     }
 }
@@ -2167,7 +2167,7 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
 static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine,
                                              DeviceState *dev)
 {
-    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+    if (object_dynamic_cast(OBJECT(dev), TYPE_DIMM)) {
         return HOTPLUG_HANDLER(machine);
     }
     return NULL;
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index c1e5774..5ddbf08 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -13,39 +13,39 @@
  *
  */
 
-#ifndef QEMU_PC_DIMM_H
-#define QEMU_PC_DIMM_H
+#ifndef QEMU_DIMM_H
+#define QEMU_DIMM_H
 
 #include "exec/memory.h"
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define TYPE_PC_DIMM "pc-dimm"
-#define PC_DIMM(obj) \
-    OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-#define PC_DIMM_CLASS(oc) \
-    OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM)
-#define PC_DIMM_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM)
+#define TYPE_DIMM "pc-dimm"
+#define DIMM(obj) \
+    OBJECT_CHECK(DIMMDevice, (obj), TYPE_DIMM)
+#define DIMM_CLASS(oc) \
+    OBJECT_CLASS_CHECK(DIMMDeviceClass, (oc), TYPE_DIMM)
+#define DIMM_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(DIMMDeviceClass, (obj), TYPE_DIMM)
 
-#define PC_DIMM_ADDR_PROP "addr"
-#define PC_DIMM_SLOT_PROP "slot"
-#define PC_DIMM_NODE_PROP "node"
-#define PC_DIMM_SIZE_PROP "size"
-#define PC_DIMM_MEMDEV_PROP "memdev"
+#define DIMM_ADDR_PROP "addr"
+#define DIMM_SLOT_PROP "slot"
+#define DIMM_NODE_PROP "node"
+#define DIMM_SIZE_PROP "size"
+#define DIMM_MEMDEV_PROP "memdev"
 
-#define PC_DIMM_UNASSIGNED_SLOT -1
+#define DIMM_UNASSIGNED_SLOT -1
 
 /**
- * PCDIMMDevice:
- * @addr: starting guest physical address, where @PCDIMMDevice is mapped.
+ * DIMMDevice:
+ * @addr: starting guest physical address, where @DIMMDevice is mapped.
  *         Default value: 0, means that address is auto-allocated.
- * @node: numa node to which @PCDIMMDevice is attached.
- * @slot: slot number into which @PCDIMMDevice is plugged in.
+ * @node: numa node to which @DIMMDevice is attached.
+ * @slot: slot number into which @DIMMDevice is plugged in.
  *        Default value: -1, means that slot is auto-allocated.
- * @hostmem: host memory backend providing memory for @PCDIMMDevice
+ * @hostmem: host memory backend providing memory for @DIMMDevice
  */
-typedef struct PCDIMMDevice {
+typedef struct DIMMDevice {
     /* private */
     DeviceState parent_obj;
 
@@ -54,19 +54,19 @@ typedef struct PCDIMMDevice {
     uint32_t node;
     int32_t slot;
     HostMemoryBackend *hostmem;
-} PCDIMMDevice;
+} DIMMDevice;
 
 /**
- * PCDIMMDeviceClass:
+ * DIMMDeviceClass:
  * @get_memory_region: returns #MemoryRegion associated with @dimm
  */
-typedef struct PCDIMMDeviceClass {
+typedef struct DIMMDeviceClass {
     /* private */
     DeviceClass parent_class;
 
     /* public */
-    MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm);
-} PCDIMMDeviceClass;
+    MemoryRegion *(*get_memory_region)(DIMMDevice *dimm);
+} DIMMDeviceClass;
 
 /**
  * MemoryHotplugState:
@@ -79,17 +79,17 @@ typedef struct MemoryHotplugState {
     MemoryRegion mr;
 } MemoryHotplugState;
 
-uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
+uint64_t dimm_get_free_addr(uint64_t address_space_start,
                                uint64_t address_space_size,
                                uint64_t *hint, uint64_t align, bool gap,
                                uint64_t size, Error **errp);
 
-int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
+int dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque);
-void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
+int qmp_dimm_device_list(Object *obj, void *opaque);
+void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                          MemoryRegion *mr, uint64_t align, bool gap,
                          Error **errp);
-void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
+void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr);
 #endif
diff --git a/numa.c b/numa.c
index e9b18f5..cb69965 100644
--- a/numa.c
+++ b/numa.c
@@ -482,7 +482,7 @@ static void numa_stat_memory_devices(uint64_t node_mem[])
     MemoryDeviceInfoList **prev = &info_list;
     MemoryDeviceInfoList *info;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
     for (info = info_list; info; info = info->next) {
         MemoryDeviceInfo *value = info->value;
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 8b0520c..d8dd8b9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3684,9 +3684,9 @@
 { 'command': 'query-memdev', 'returns': ['Memdev'] }
 
 ##
-# @PCDIMMDeviceInfo:
+# @DIMMDeviceInfo:
 #
-# PCDIMMDevice state information
+# DIMMDevice state information
 #
 # @id: #optional device's ID
 #
@@ -3706,7 +3706,7 @@
 #
 # Since: 2.1
 ##
-{ 'struct': 'PCDIMMDeviceInfo',
+{ 'struct': 'DIMMDeviceInfo',
   'data': { '*id': 'str',
             'addr': 'int',
             'size': 'int',
@@ -3725,7 +3725,7 @@
 #
 # Since: 2.1
 ##
-{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} }
+{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'DIMMDeviceInfo'} }
 
 ##
 # @query-memory-devices
diff --git a/qmp.c b/qmp.c
index 057a7cb..6709aea 100644
--- a/qmp.c
+++ b/qmp.c
@@ -699,7 +699,7 @@ MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
     MemoryDeviceInfoList *head = NULL;
     MemoryDeviceInfoList **prev = &head;
 
-    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+    qmp_dimm_device_list(qdev_get_machine(), &prev);
 
     return head;
 }
diff --git a/stubs/qmp_pc_dimm_device_list.c b/stubs/qmp_pc_dimm_device_list.c
index b584bd8..b2704c6 100644
--- a/stubs/qmp_pc_dimm_device_list.c
+++ b/stubs/qmp_pc_dimm_device_list.c
@@ -1,7 +1,7 @@
 #include "qom/object.h"
 #include "hw/mem/pc-dimm.h"
 
-int qmp_pc_dimm_device_list(Object *obj, void *opaque)
+int qmp_dimm_device_list(Object *obj, void *opaque)
 {
    return 0;
 }
diff --git a/trace-events b/trace-events
index b813ae4..06c76f2 100644
--- a/trace-events
+++ b/trace-events
@@ -1639,12 +1639,12 @@ mhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "slot[0x%"PRIx32"] OST EVENT:
 mhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "slot[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
 mhp_acpi_clear_insert_evt(uint32_t slot) "slot[0x%"PRIx32"] clear insert event"
 mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event"
-mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted"
-mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed"
+mhp_acpi_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] dimm deleted"
+mhp_acpi_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] dimm delete failed"
 
 # hw/i386/pc.c
-mhp_pc_dimm_assigned_slot(int slot) "0x%d"
-mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
+mhp_dimm_assigned_slot(int slot) "0x%d"
+mhp_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
 
 # target-s390x/kvm.c
 kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 15/33] stubs: rename qmp_pc_dimm_device_list.c
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Rename qmp_pc_dimm_device_list.c to qmp_dimm_device_list.c

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 stubs/Makefile.objs                                         | 2 +-
 stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} (100%)

diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index ce6ce11..e28af50 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -37,6 +37,6 @@ stub-obj-y += vmstate.o
 stub-obj-$(CONFIG_WIN32) += fd-register.o
 stub-obj-y += cpus.o
 stub-obj-y += kvm.o
-stub-obj-y += qmp_pc_dimm_device_list.o
+stub-obj-y += qmp_dimm_device_list.o
 stub-obj-y += target-monitor-defs.o
 stub-obj-y += vhost.o
diff --git a/stubs/qmp_pc_dimm_device_list.c b/stubs/qmp_dimm_device_list.c
similarity index 100%
rename from stubs/qmp_pc_dimm_device_list.c
rename to stubs/qmp_dimm_device_list.c
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 15/33] stubs: rename qmp_pc_dimm_device_list.c
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Rename qmp_pc_dimm_device_list.c to qmp_dimm_device_list.c

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 stubs/Makefile.objs                                         | 2 +-
 stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename stubs/{qmp_pc_dimm_device_list.c => qmp_dimm_device_list.c} (100%)

diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index ce6ce11..e28af50 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -37,6 +37,6 @@ stub-obj-y += vmstate.o
 stub-obj-$(CONFIG_WIN32) += fd-register.o
 stub-obj-y += cpus.o
 stub-obj-y += kvm.o
-stub-obj-y += qmp_pc_dimm_device_list.o
+stub-obj-y += qmp_dimm_device_list.o
 stub-obj-y += target-monitor-defs.o
 stub-obj-y += vhost.o
diff --git a/stubs/qmp_pc_dimm_device_list.c b/stubs/qmp_dimm_device_list.c
similarity index 100%
rename from stubs/qmp_pc_dimm_device_list.c
rename to stubs/qmp_dimm_device_list.c
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 16/33] pc-dimm: rename pc-dimm.c and pc-dimm.h
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Rename:
   pc-dimm.c => dimm.c
   pc-dimm.h => dimm.h

It prepares the work which abstracts dimm device type for both pc-dimm and
nvdimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/Makefile.objs                     | 2 +-
 hw/acpi/ich9.c                       | 2 +-
 hw/acpi/memory_hotplug.c             | 4 ++--
 hw/acpi/piix4.c                      | 2 +-
 hw/i386/pc.c                         | 2 +-
 hw/mem/Makefile.objs                 | 2 +-
 hw/mem/{pc-dimm.c => dimm.c}         | 2 +-
 hw/ppc/spapr.c                       | 2 +-
 include/hw/i386/pc.h                 | 2 +-
 include/hw/mem/{pc-dimm.h => dimm.h} | 0
 include/hw/ppc/spapr.h               | 2 +-
 numa.c                               | 2 +-
 qmp.c                                | 2 +-
 stubs/qmp_dimm_device_list.c         | 2 +-
 14 files changed, 14 insertions(+), 14 deletions(-)
 rename hw/mem/{pc-dimm.c => dimm.c} (99%)
 rename include/hw/mem/{pc-dimm.h => dimm.h} (100%)

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 7e7c241..12ecda9 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -30,8 +30,8 @@ devices-dirs-$(CONFIG_SOFTMMU) += vfio/
 devices-dirs-$(CONFIG_VIRTIO) += virtio/
 devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
 devices-dirs-$(CONFIG_SOFTMMU) += xen/
-devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
 devices-dirs-$(CONFIG_SMBIOS) += smbios/
+devices-dirs-y += mem/
 devices-dirs-y += core/
 common-obj-y += $(devices-dirs-y)
 obj-y += $(devices-dirs-y)
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index b0d6a67..1e9ae20 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -35,7 +35,7 @@
 #include "exec/address-spaces.h"
 
 #include "hw/i386/ich9.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 //#define DEBUG
 
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 1f6cccc..e232641 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -1,6 +1,6 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/pc-hotplug.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "trace.h"
@@ -148,7 +148,7 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
 
             dev = DEVICE(mdev->dimm);
             hotplug_ctrl = qdev_get_hotplug_handler(dev);
-            /* call pc-dimm unplug cb */
+            /* call dimm unplug cb */
             hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
             if (local_err) {
                 trace_mhp_acpi_dimm_delete_failed(mem_st->selector);
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 0b2cb6e..b2f5b2c 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -33,7 +33,7 @@
 #include "hw/acpi/pcihp.h"
 #include "hw/acpi/cpu_hotplug.h"
 #include "hw/hotplug.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/xen/xen.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d6b9fa7..6694b18 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -62,7 +62,7 @@
 #include "hw/boards.h"
 #include "hw/pci/pci_host.h"
 #include "acpi-build.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qapi/visitor.h"
 #include "qapi-visit.h"
 
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index b000fb4..7563ef5 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1 @@
-common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_MEM_HOTPLUG) += dimm.o
diff --git a/hw/mem/pc-dimm.c b/hw/mem/dimm.c
similarity index 99%
rename from hw/mem/pc-dimm.c
rename to hw/mem/dimm.c
index 51f737f..6c1ea98 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/dimm.c
@@ -18,7 +18,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qemu/config-file.h"
 #include "qapi/visitor.h"
 #include "qemu/range.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4fb91a5..171fa77 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2138,7 +2138,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
          *
          * - Memory gets hotplugged to a different node than what the user
          *   specified.
-         * - Since pc-dimm subsystem in QEMU still thinks that memory belongs
+         * - Since dimm subsystem in QEMU still thinks that memory belongs
          *   to memory-less node, a reboot will set things accordingly
          *   and the previously hotplugged memory now ends in the right node.
          *   This appears as if some memory moved from one node to another.
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 0503485..693b6c5 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -16,7 +16,7 @@
 #include "hw/pci/pci.h"
 #include "hw/boards.h"
 #include "hw/compat.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/dimm.h
similarity index 100%
rename from include/hw/mem/pc-dimm.h
rename to include/hw/mem/dimm.h
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 56c5b0b..ec46ce0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -5,7 +5,7 @@
 #include "hw/boards.h"
 #include "hw/ppc/xics.h"
 #include "hw/ppc/spapr_drc.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 struct VIOsPAPRBus;
 struct sPAPRPHBState;
diff --git a/numa.c b/numa.c
index cb69965..34c6d6b 100644
--- a/numa.c
+++ b/numa.c
@@ -34,7 +34,7 @@
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
 #include "qmp-commands.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 
diff --git a/qmp.c b/qmp.c
index 6709aea..54c9c37 100644
--- a/qmp.c
+++ b/qmp.c
@@ -30,7 +30,7 @@
 #include "qapi/qmp-input-visitor.h"
 #include "hw/boards.h"
 #include "qom/object_interfaces.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/acpi/acpi_dev_interface.h"
 
 NameInfo *qmp_query_name(Error **errp)
diff --git a/stubs/qmp_dimm_device_list.c b/stubs/qmp_dimm_device_list.c
index b2704c6..fb66400 100644
--- a/stubs/qmp_dimm_device_list.c
+++ b/stubs/qmp_dimm_device_list.c
@@ -1,5 +1,5 @@
 #include "qom/object.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 int qmp_dimm_device_list(Object *obj, void *opaque)
 {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 16/33] pc-dimm: rename pc-dimm.c and pc-dimm.h
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Rename:
   pc-dimm.c => dimm.c
   pc-dimm.h => dimm.h

It prepares the work which abstracts dimm device type for both pc-dimm and
nvdimm

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/Makefile.objs                     | 2 +-
 hw/acpi/ich9.c                       | 2 +-
 hw/acpi/memory_hotplug.c             | 4 ++--
 hw/acpi/piix4.c                      | 2 +-
 hw/i386/pc.c                         | 2 +-
 hw/mem/Makefile.objs                 | 2 +-
 hw/mem/{pc-dimm.c => dimm.c}         | 2 +-
 hw/ppc/spapr.c                       | 2 +-
 include/hw/i386/pc.h                 | 2 +-
 include/hw/mem/{pc-dimm.h => dimm.h} | 0
 include/hw/ppc/spapr.h               | 2 +-
 numa.c                               | 2 +-
 qmp.c                                | 2 +-
 stubs/qmp_dimm_device_list.c         | 2 +-
 14 files changed, 14 insertions(+), 14 deletions(-)
 rename hw/mem/{pc-dimm.c => dimm.c} (99%)
 rename include/hw/mem/{pc-dimm.h => dimm.h} (100%)

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 7e7c241..12ecda9 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -30,8 +30,8 @@ devices-dirs-$(CONFIG_SOFTMMU) += vfio/
 devices-dirs-$(CONFIG_VIRTIO) += virtio/
 devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
 devices-dirs-$(CONFIG_SOFTMMU) += xen/
-devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
 devices-dirs-$(CONFIG_SMBIOS) += smbios/
+devices-dirs-y += mem/
 devices-dirs-y += core/
 common-obj-y += $(devices-dirs-y)
 obj-y += $(devices-dirs-y)
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index b0d6a67..1e9ae20 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -35,7 +35,7 @@
 #include "exec/address-spaces.h"
 
 #include "hw/i386/ich9.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 //#define DEBUG
 
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 1f6cccc..e232641 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -1,6 +1,6 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/pc-hotplug.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "trace.h"
@@ -148,7 +148,7 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
 
             dev = DEVICE(mdev->dimm);
             hotplug_ctrl = qdev_get_hotplug_handler(dev);
-            /* call pc-dimm unplug cb */
+            /* call dimm unplug cb */
             hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
             if (local_err) {
                 trace_mhp_acpi_dimm_delete_failed(mem_st->selector);
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 0b2cb6e..b2f5b2c 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -33,7 +33,7 @@
 #include "hw/acpi/pcihp.h"
 #include "hw/acpi/cpu_hotplug.h"
 #include "hw/hotplug.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/xen/xen.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d6b9fa7..6694b18 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -62,7 +62,7 @@
 #include "hw/boards.h"
 #include "hw/pci/pci_host.h"
 #include "acpi-build.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qapi/visitor.h"
 #include "qapi-visit.h"
 
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index b000fb4..7563ef5 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1 @@
-common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_MEM_HOTPLUG) += dimm.o
diff --git a/hw/mem/pc-dimm.c b/hw/mem/dimm.c
similarity index 99%
rename from hw/mem/pc-dimm.c
rename to hw/mem/dimm.c
index 51f737f..6c1ea98 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/dimm.c
@@ -18,7 +18,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qemu/config-file.h"
 #include "qapi/visitor.h"
 #include "qemu/range.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4fb91a5..171fa77 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2138,7 +2138,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
          *
          * - Memory gets hotplugged to a different node than what the user
          *   specified.
-         * - Since pc-dimm subsystem in QEMU still thinks that memory belongs
+         * - Since dimm subsystem in QEMU still thinks that memory belongs
          *   to memory-less node, a reboot will set things accordingly
          *   and the previously hotplugged memory now ends in the right node.
          *   This appears as if some memory moved from one node to another.
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 0503485..693b6c5 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -16,7 +16,7 @@
 #include "hw/pci/pci.h"
 #include "hw/boards.h"
 #include "hw/compat.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/dimm.h
similarity index 100%
rename from include/hw/mem/pc-dimm.h
rename to include/hw/mem/dimm.h
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 56c5b0b..ec46ce0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -5,7 +5,7 @@
 #include "hw/boards.h"
 #include "hw/ppc/xics.h"
 #include "hw/ppc/spapr_drc.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 struct VIOsPAPRBus;
 struct sPAPRPHBState;
diff --git a/numa.c b/numa.c
index cb69965..34c6d6b 100644
--- a/numa.c
+++ b/numa.c
@@ -34,7 +34,7 @@
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
 #include "qmp-commands.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 
diff --git a/qmp.c b/qmp.c
index 6709aea..54c9c37 100644
--- a/qmp.c
+++ b/qmp.c
@@ -30,7 +30,7 @@
 #include "qapi/qmp-input-visitor.h"
 #include "hw/boards.h"
 #include "qom/object_interfaces.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 #include "hw/acpi/acpi_dev_interface.h"
 
 NameInfo *qmp_query_name(Error **errp)
diff --git a/stubs/qmp_dimm_device_list.c b/stubs/qmp_dimm_device_list.c
index b2704c6..fb66400 100644
--- a/stubs/qmp_dimm_device_list.c
+++ b/stubs/qmp_dimm_device_list.c
@@ -1,5 +1,5 @@
 #include "qom/object.h"
-#include "hw/mem/pc-dimm.h"
+#include "hw/mem/dimm.h"
 
 int qmp_dimm_device_list(Object *obj, void *opaque)
 {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

A base device, dimm, is abstracted from pc-dimm, so that we can
build nvdimm device based on dimm in the later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 default-configs/i386-softmmu.mak   |  1 +
 default-configs/x86_64-softmmu.mak |  1 +
 hw/mem/Makefile.objs               |  3 ++-
 hw/mem/dimm.c                      | 11 ++-------
 hw/mem/pc-dimm.c                   | 46 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/dimm.h              |  4 ++--
 include/hw/mem/pc-dimm.h           |  7 ++++++
 7 files changed, 61 insertions(+), 12 deletions(-)
 create mode 100644 hw/mem/pc-dimm.c
 create mode 100644 include/hw/mem/pc-dimm.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 43c96d1..3ece8bb 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -18,6 +18,7 @@ CONFIG_FDC=y
 CONFIG_ACPI=y
 CONFIG_ACPI_X86=y
 CONFIG_ACPI_X86_ICH=y
+CONFIG_DIMM=y
 CONFIG_ACPI_MEMORY_HOTPLUG=y
 CONFIG_ACPI_CPU_HOTPLUG=y
 CONFIG_APM=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index dfb8095..92ea7c1 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -18,6 +18,7 @@ CONFIG_FDC=y
 CONFIG_ACPI=y
 CONFIG_ACPI_X86=y
 CONFIG_ACPI_X86_ICH=y
+CONFIG_DIMM=y
 CONFIG_ACPI_MEMORY_HOTPLUG=y
 CONFIG_ACPI_CPU_HOTPLUG=y
 CONFIG_APM=y
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index 7563ef5..cebb4b1 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1,2 @@
-common-obj-$(CONFIG_MEM_HOTPLUG) += dimm.o
+common-obj-$(CONFIG_DIMM) += dimm.o
+common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 6c1ea98..23d5daa 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -1,5 +1,5 @@
 /*
- * Dimm device for Memory Hotplug
+ * Dimm device abstraction
  *
  * Copyright ProfitBricks GmbH 2012
  * Copyright (C) 2014 Red Hat Inc
@@ -432,21 +432,13 @@ static void dimm_realize(DeviceState *dev, Error **errp)
     }
 }
 
-static MemoryRegion *dimm_get_memory_region(DIMMDevice *dimm)
-{
-    return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
-}
-
 static void dimm_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
-    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
 
     dc->realize = dimm_realize;
     dc->props = dimm_properties;
     dc->desc = "DIMM memory module";
-
-    ddc->get_memory_region = dimm_get_memory_region;
 }
 
 static TypeInfo dimm_info = {
@@ -456,6 +448,7 @@ static TypeInfo dimm_info = {
     .instance_init = dimm_init,
     .class_init    = dimm_class_init,
     .class_size    = sizeof(DIMMDeviceClass),
+    .abstract      = true,
 };
 
 static void dimm_register_types(void)
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
new file mode 100644
index 0000000..38323e9
--- /dev/null
+++ b/hw/mem/pc-dimm.c
@@ -0,0 +1,46 @@
+/*
+ * Dimm device for Memory Hotplug
+ *
+ * Copyright ProfitBricks GmbH 2012
+ * Copyright (C) 2014 Red Hat Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "hw/mem/pc-dimm.h"
+
+static MemoryRegion *pc_dimm_get_memory_region(DIMMDevice *dimm)
+{
+    return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
+}
+
+static void pc_dimm_class_init(ObjectClass *oc, void *data)
+{
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
+
+    ddc->get_memory_region = pc_dimm_get_memory_region;
+}
+
+static TypeInfo pc_dimm_info = {
+    .name          = TYPE_PC_DIMM,
+    .parent        = TYPE_DIMM,
+    .class_init    = pc_dimm_class_init,
+};
+
+static void pc_dimm_register_types(void)
+{
+    type_register_static(&pc_dimm_info);
+}
+
+type_init(pc_dimm_register_types)
diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h
index 5ddbf08..84a62ed 100644
--- a/include/hw/mem/dimm.h
+++ b/include/hw/mem/dimm.h
@@ -1,5 +1,5 @@
 /*
- * PC DIMM device
+ * Dimm device abstraction
  *
  * Copyright ProfitBricks GmbH 2012
  * Copyright (C) 2013-2014 Red Hat Inc
@@ -20,7 +20,7 @@
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define TYPE_DIMM "pc-dimm"
+#define TYPE_DIMM "dimm"
 #define DIMM(obj) \
     OBJECT_CHECK(DIMMDevice, (obj), TYPE_DIMM)
 #define DIMM_CLASS(oc) \
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
new file mode 100644
index 0000000..50818c2
--- /dev/null
+++ b/include/hw/mem/pc-dimm.h
@@ -0,0 +1,7 @@
+#ifndef QEMU_PC_DIMM_H
+#define QEMU_PC_DIMM_H
+
+#include "hw/mem/dimm.h"
+
+#define TYPE_PC_DIMM "pc-dimm"
+#endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

A base device, dimm, is abstracted from pc-dimm, so that we can
build nvdimm device based on dimm in the later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 default-configs/i386-softmmu.mak   |  1 +
 default-configs/x86_64-softmmu.mak |  1 +
 hw/mem/Makefile.objs               |  3 ++-
 hw/mem/dimm.c                      | 11 ++-------
 hw/mem/pc-dimm.c                   | 46 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/dimm.h              |  4 ++--
 include/hw/mem/pc-dimm.h           |  7 ++++++
 7 files changed, 61 insertions(+), 12 deletions(-)
 create mode 100644 hw/mem/pc-dimm.c
 create mode 100644 include/hw/mem/pc-dimm.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 43c96d1..3ece8bb 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -18,6 +18,7 @@ CONFIG_FDC=y
 CONFIG_ACPI=y
 CONFIG_ACPI_X86=y
 CONFIG_ACPI_X86_ICH=y
+CONFIG_DIMM=y
 CONFIG_ACPI_MEMORY_HOTPLUG=y
 CONFIG_ACPI_CPU_HOTPLUG=y
 CONFIG_APM=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index dfb8095..92ea7c1 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -18,6 +18,7 @@ CONFIG_FDC=y
 CONFIG_ACPI=y
 CONFIG_ACPI_X86=y
 CONFIG_ACPI_X86_ICH=y
+CONFIG_DIMM=y
 CONFIG_ACPI_MEMORY_HOTPLUG=y
 CONFIG_ACPI_CPU_HOTPLUG=y
 CONFIG_APM=y
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index 7563ef5..cebb4b1 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1,2 @@
-common-obj-$(CONFIG_MEM_HOTPLUG) += dimm.o
+common-obj-$(CONFIG_DIMM) += dimm.o
+common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 6c1ea98..23d5daa 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -1,5 +1,5 @@
 /*
- * Dimm device for Memory Hotplug
+ * Dimm device abstraction
  *
  * Copyright ProfitBricks GmbH 2012
  * Copyright (C) 2014 Red Hat Inc
@@ -432,21 +432,13 @@ static void dimm_realize(DeviceState *dev, Error **errp)
     }
 }
 
-static MemoryRegion *dimm_get_memory_region(DIMMDevice *dimm)
-{
-    return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
-}
-
 static void dimm_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
-    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
 
     dc->realize = dimm_realize;
     dc->props = dimm_properties;
     dc->desc = "DIMM memory module";
-
-    ddc->get_memory_region = dimm_get_memory_region;
 }
 
 static TypeInfo dimm_info = {
@@ -456,6 +448,7 @@ static TypeInfo dimm_info = {
     .instance_init = dimm_init,
     .class_init    = dimm_class_init,
     .class_size    = sizeof(DIMMDeviceClass),
+    .abstract      = true,
 };
 
 static void dimm_register_types(void)
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
new file mode 100644
index 0000000..38323e9
--- /dev/null
+++ b/hw/mem/pc-dimm.c
@@ -0,0 +1,46 @@
+/*
+ * Dimm device for Memory Hotplug
+ *
+ * Copyright ProfitBricks GmbH 2012
+ * Copyright (C) 2014 Red Hat Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "hw/mem/pc-dimm.h"
+
+static MemoryRegion *pc_dimm_get_memory_region(DIMMDevice *dimm)
+{
+    return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
+}
+
+static void pc_dimm_class_init(ObjectClass *oc, void *data)
+{
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
+
+    ddc->get_memory_region = pc_dimm_get_memory_region;
+}
+
+static TypeInfo pc_dimm_info = {
+    .name          = TYPE_PC_DIMM,
+    .parent        = TYPE_DIMM,
+    .class_init    = pc_dimm_class_init,
+};
+
+static void pc_dimm_register_types(void)
+{
+    type_register_static(&pc_dimm_info);
+}
+
+type_init(pc_dimm_register_types)
diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h
index 5ddbf08..84a62ed 100644
--- a/include/hw/mem/dimm.h
+++ b/include/hw/mem/dimm.h
@@ -1,5 +1,5 @@
 /*
- * PC DIMM device
+ * Dimm device abstraction
  *
  * Copyright ProfitBricks GmbH 2012
  * Copyright (C) 2013-2014 Red Hat Inc
@@ -20,7 +20,7 @@
 #include "sysemu/hostmem.h"
 #include "hw/qdev.h"
 
-#define TYPE_DIMM "pc-dimm"
+#define TYPE_DIMM "dimm"
 #define DIMM(obj) \
     OBJECT_CHECK(DIMMDevice, (obj), TYPE_DIMM)
 #define DIMM_CLASS(oc) \
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
new file mode 100644
index 0000000..50818c2
--- /dev/null
+++ b/include/hw/mem/pc-dimm.h
@@ -0,0 +1,7 @@
+#ifndef QEMU_PC_DIMM_H
+#define QEMU_PC_DIMM_H
+
+#include "hw/mem/dimm.h"
+
+#define TYPE_PC_DIMM "pc-dimm"
+#endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 18/33] dimm: get mapped memory region from DIMMDeviceClass->get_memory_region
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Curretly, the memory region of backed memory is directly mapped to
guest's address space, however, it is not true for nvdimm device

This patch let dimm device realize this fact and use
DIMMDeviceClass->get_memory_region method to get the mapped memory
region

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 23d5daa..9e0403a 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -380,8 +380,9 @@ static void dimm_get_size(Object *obj, Visitor *v, void *opaque,
     int64_t value;
     MemoryRegion *mr;
     DIMMDevice *dimm = DIMM(obj);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(obj);
 
-    mr = host_memory_backend_get_memory(dimm->hostmem, errp);
+    mr = ddc->get_memory_region(dimm);
     value = memory_region_size(mr);
 
     visit_type_int(v, &value, name, errp);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 18/33] dimm: get mapped memory region from DIMMDeviceClass->get_memory_region
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Curretly, the memory region of backed memory is directly mapped to
guest's address space, however, it is not true for nvdimm device

This patch let dimm device realize this fact and use
DIMMDeviceClass->get_memory_region method to get the mapped memory
region

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 23d5daa..9e0403a 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -380,8 +380,9 @@ static void dimm_get_size(Object *obj, Visitor *v, void *opaque,
     int64_t value;
     MemoryRegion *mr;
     DIMMDevice *dimm = DIMM(obj);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(obj);
 
-    mr = host_memory_backend_get_memory(dimm->hostmem, errp);
+    mr = ddc->get_memory_region(dimm);
     value = memory_region_size(mr);
 
     visit_type_int(v, &value, name, errp);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 19/33] dimm: keep the state of the whole backend memory
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

QEMU keeps the state of memory of dimm device during live migration,
however, it is not enough for nvdimm device as its memory does not
contain its label data, so that we should protect the whole backend
memory instead

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 9e0403a..478cacd 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -135,9 +135,16 @@ void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     }
 
     memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
-    vmstate_register_ram(mr, dev);
     numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node);
 
+    /*
+     * save the state only for @mr is not enough as it does not contain
+     * the label data of NVDIMM device, so that we keep the state of
+     * whole hostmem instead.
+     */
+    vmstate_register_ram(host_memory_backend_get_memory(dimm->hostmem, errp),
+                         dev);
+
 out:
     error_propagate(errp, local_err);
 }
@@ -146,10 +153,13 @@ void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr)
 {
     DIMMDevice *dimm = DIMM(dev);
+    MemoryRegion *backend_mr;
+
+    backend_mr = host_memory_backend_get_memory(dimm->hostmem, &error_abort);
 
     numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);
     memory_region_del_subregion(&hpms->mr, mr);
-    vmstate_unregister_ram(mr, dev);
+    vmstate_unregister_ram(backend_mr, dev);
 }
 
 int qmp_dimm_device_list(Object *obj, void *opaque)
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 19/33] dimm: keep the state of the whole backend memory
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

QEMU keeps the state of memory of dimm device during live migration,
however, it is not enough for nvdimm device as its memory does not
contain its label data, so that we should protect the whole backend
memory instead

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 9e0403a..478cacd 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -135,9 +135,16 @@ void dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
     }
 
     memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
-    vmstate_register_ram(mr, dev);
     numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node);
 
+    /*
+     * save the state only for @mr is not enough as it does not contain
+     * the label data of NVDIMM device, so that we keep the state of
+     * whole hostmem instead.
+     */
+    vmstate_register_ram(host_memory_backend_get_memory(dimm->hostmem, errp),
+                         dev);
+
 out:
     error_propagate(errp, local_err);
 }
@@ -146,10 +153,13 @@ void dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
                            MemoryRegion *mr)
 {
     DIMMDevice *dimm = DIMM(dev);
+    MemoryRegion *backend_mr;
+
+    backend_mr = host_memory_backend_get_memory(dimm->hostmem, &error_abort);
 
     numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);
     memory_region_del_subregion(&hpms->mr, mr);
-    vmstate_unregister_ram(mr, dev);
+    vmstate_unregister_ram(backend_mr, dev);
 }
 
 int qmp_dimm_device_list(Object *obj, void *opaque)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 20/33] dimm: introduce realize callback
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

nvdimm need check if the backend memory is large enough to contain label
data and init its memory region when the device is realized, so introduce
realize callback which is called after common dimm has been realize

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c         | 5 +++++
 include/hw/mem/dimm.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 478cacd..3d06cb9 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -429,6 +429,7 @@ static void dimm_init(Object *obj)
 static void dimm_realize(DeviceState *dev, Error **errp)
 {
     DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
 
     if (!dimm->hostmem) {
         error_setg(errp, "'" DIMM_MEMDEV_PROP "' property is not set");
@@ -441,6 +442,10 @@ static void dimm_realize(DeviceState *dev, Error **errp)
                    dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
         return;
     }
+
+    if (ddc->realize) {
+        ddc->realize(dimm, errp);
+    }
 }
 
 static void dimm_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h
index 84a62ed..663288d 100644
--- a/include/hw/mem/dimm.h
+++ b/include/hw/mem/dimm.h
@@ -65,6 +65,7 @@ typedef struct DIMMDeviceClass {
     DeviceClass parent_class;
 
     /* public */
+    void (*realize)(DIMMDevice *dimm, Error **errp);
     MemoryRegion *(*get_memory_region)(DIMMDevice *dimm);
 } DIMMDeviceClass;
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 20/33] dimm: introduce realize callback
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

nvdimm need check if the backend memory is large enough to contain label
data and init its memory region when the device is realized, so introduce
realize callback which is called after common dimm has been realize

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/dimm.c         | 5 +++++
 include/hw/mem/dimm.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index 478cacd..3d06cb9 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -429,6 +429,7 @@ static void dimm_init(Object *obj)
 static void dimm_realize(DeviceState *dev, Error **errp)
 {
     DIMMDevice *dimm = DIMM(dev);
+    DIMMDeviceClass *ddc = DIMM_GET_CLASS(dimm);
 
     if (!dimm->hostmem) {
         error_setg(errp, "'" DIMM_MEMDEV_PROP "' property is not set");
@@ -441,6 +442,10 @@ static void dimm_realize(DeviceState *dev, Error **errp)
                    dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
         return;
     }
+
+    if (ddc->realize) {
+        ddc->realize(dimm, errp);
+    }
 }
 
 static void dimm_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h
index 84a62ed..663288d 100644
--- a/include/hw/mem/dimm.h
+++ b/include/hw/mem/dimm.h
@@ -65,6 +65,7 @@ typedef struct DIMMDeviceClass {
     DeviceClass parent_class;
 
     /* public */
+    void (*realize)(DIMMDevice *dimm, Error **errp);
     MemoryRegion *(*get_memory_region)(DIMMDevice *dimm);
 } DIMMDeviceClass;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 21/33] nvdimm: implement NVDIMM device abstract
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Introduce "nvdimm" device which is based on dimm device type

128K memory region which is the minimum namespace label size
required by NVDIMM Namespace Spec locates at the end of
backend memory device is reserved for label data

We can use "-m 1G,maxmem=100G,slots=10 -object memory-backend-file,
id=mem1,size=1G,mem-path=/dev/pmem0 -device nvdimm,memdev=mem1" to
create NVDIMM device for guest

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 default-configs/i386-softmmu.mak   |  1 +
 default-configs/x86_64-softmmu.mak |  1 +
 hw/acpi/memory_hotplug.c           |  6 +++
 hw/mem/Makefile.objs               |  1 +
 hw/mem/nvdimm.c                    | 84 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/nvdimm.h            | 66 ++++++++++++++++++++++++++++++
 6 files changed, 159 insertions(+)
 create mode 100644 hw/mem/nvdimm.c
 create mode 100644 include/hw/mem/nvdimm.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 3ece8bb..a1b24e5 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_APIC=y
 CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_NVDIMM = y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 92ea7c1..e3f5a0b 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_APIC=y
 CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_NVDIMM = y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index e232641..92cd973 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -1,6 +1,7 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/pc-hotplug.h"
 #include "hw/mem/dimm.h"
+#include "hw/mem/nvdimm.h"
 #include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "trace.h"
@@ -231,6 +232,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
 {
     MemStatus *mdev;
 
+    /* Currently, NVDIMM hotplug has not been supported yet. */
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
+        return;
+    }
+
     mdev = acpi_memory_slot_status(mem_st, dev, errp);
     if (!mdev) {
         return;
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index cebb4b1..12d9b72 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1,2 +1,3 @@
 common-obj-$(CONFIG_DIMM) += dimm.o
 common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_NVDIMM) += nvdimm.o
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
new file mode 100644
index 0000000..51494b6
--- /dev/null
+++ b/hw/mem/nvdimm.c
@@ -0,0 +1,84 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * Currently, it only supports PMEM Virtualization.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "qapi/visitor.h"
+#include "hw/mem/nvdimm.h"
+
+static MemoryRegion *nvdimm_get_memory_region(DIMMDevice *dimm)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(dimm);
+
+    return memory_region_size(&nvdimm->nvdimm_mr) ? &nvdimm->nvdimm_mr : NULL;
+}
+
+static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
+{
+    MemoryRegion *mr;
+    NVDIMMDevice *nvdimm = NVDIMM(dimm);
+    uint64_t size;
+
+    nvdimm->label_size = MIN_NAMESPACE_LABEL_SIZE;
+
+    mr = host_memory_backend_get_memory(dimm->hostmem, errp);
+    size = memory_region_size(mr);
+
+    if (size <= nvdimm->label_size) {
+        char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem));
+        error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too small"
+                   " to contain nvdimm namespace label (0x%" PRIx64 ")", path,
+                   memory_region_size(mr), nvdimm->label_size);
+        return;
+    }
+
+    memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm), "nvdimm-memory",
+                             mr, 0, size - nvdimm->label_size);
+    nvdimm->label_data = memory_region_get_ram_ptr(mr) +
+                         memory_region_size(&nvdimm->nvdimm_mr);
+}
+
+static void nvdimm_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
+
+    /* nvdimm hotplug has not been supported yet. */
+    dc->hotpluggable = false;
+
+    ddc->realize = nvdimm_realize;
+    ddc->get_memory_region = nvdimm_get_memory_region;
+}
+
+static TypeInfo nvdimm_info = {
+    .name          = TYPE_NVDIMM,
+    .parent        = TYPE_DIMM,
+    .instance_size = sizeof(NVDIMMDevice),
+    .class_init    = nvdimm_class_init,
+};
+
+static void nvdimm_register_types(void)
+{
+    type_register_static(&nvdimm_info);
+}
+
+type_init(nvdimm_register_types)
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
new file mode 100644
index 0000000..60399d8
--- /dev/null
+++ b/include/hw/mem/nvdimm.h
@@ -0,0 +1,66 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * NVDIMM specifications and some documents can be found at:
+ * NVDIMM ACPI device and NFIT are introduced in ACPI 6:
+ *      http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
+ * NVDIMM Namespace specification:
+ *      http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
+ * DSM Interface Example:
+ *      http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+ * Driver Writer's Guide:
+ *      http://pmem.io/documents/NVDIMM_Driver_Writers_Guide.pdf
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_NVDIMM_H
+#define QEMU_NVDIMM_H
+
+#include "hw/mem/dimm.h"
+
+/*
+ * The minimum label data size is required by NVDIMM Namespace
+ * specification, please refer to chapter 2 Namespaces:
+ *   "NVDIMMs following the NVDIMM Block Mode Specification use an area
+ *    at least 128KB in size, which holds around 1000 labels."
+ */
+#define MIN_NAMESPACE_LABEL_SIZE      (128UL << 10)
+
+#define TYPE_NVDIMM      "nvdimm"
+#define NVDIMM(obj)      OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
+
+struct NVDIMMDevice {
+    /* private */
+    DIMMDevice parent_obj;
+
+    /* public */
+
+    /*
+     * the size of label data in NVDIMM device which is presented to
+     * guest via __DSM "Get Namespace Label Size" command.
+     */
+    uint64_t label_size;
+
+    /*
+     * the address of label data which is read by __DSM "Get Namespace
+     * Label Data" command and written by __DSM "Set Namespace Label
+     * Data" command.
+     */
+    void *label_data;
+
+    /*
+     * it's the PMEM region in NVDIMM device, which is presented to
+     * guest via ACPI NFIT and _FIT method if NVDIMM hotplug is supported.
+     */
+    MemoryRegion nvdimm_mr;
+};
+typedef struct NVDIMMDevice NVDIMMDevice;
+
+#endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 21/33] nvdimm: implement NVDIMM device abstract
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Introduce "nvdimm" device which is based on dimm device type

128K memory region which is the minimum namespace label size
required by NVDIMM Namespace Spec locates at the end of
backend memory device is reserved for label data

We can use "-m 1G,maxmem=100G,slots=10 -object memory-backend-file,
id=mem1,size=1G,mem-path=/dev/pmem0 -device nvdimm,memdev=mem1" to
create NVDIMM device for guest

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 default-configs/i386-softmmu.mak   |  1 +
 default-configs/x86_64-softmmu.mak |  1 +
 hw/acpi/memory_hotplug.c           |  6 +++
 hw/mem/Makefile.objs               |  1 +
 hw/mem/nvdimm.c                    | 84 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/nvdimm.h            | 66 ++++++++++++++++++++++++++++++
 6 files changed, 159 insertions(+)
 create mode 100644 hw/mem/nvdimm.c
 create mode 100644 include/hw/mem/nvdimm.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 3ece8bb..a1b24e5 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_APIC=y
 CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_NVDIMM = y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 92ea7c1..e3f5a0b 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_APIC=y
 CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_NVDIMM = y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index e232641..92cd973 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -1,6 +1,7 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/pc-hotplug.h"
 #include "hw/mem/dimm.h"
+#include "hw/mem/nvdimm.h"
 #include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "trace.h"
@@ -231,6 +232,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
 {
     MemStatus *mdev;
 
+    /* Currently, NVDIMM hotplug has not been supported yet. */
+    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
+        return;
+    }
+
     mdev = acpi_memory_slot_status(mem_st, dev, errp);
     if (!mdev) {
         return;
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index cebb4b1..12d9b72 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1,2 +1,3 @@
 common-obj-$(CONFIG_DIMM) += dimm.o
 common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_NVDIMM) += nvdimm.o
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
new file mode 100644
index 0000000..51494b6
--- /dev/null
+++ b/hw/mem/nvdimm.c
@@ -0,0 +1,84 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * Currently, it only supports PMEM Virtualization.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "qapi/visitor.h"
+#include "hw/mem/nvdimm.h"
+
+static MemoryRegion *nvdimm_get_memory_region(DIMMDevice *dimm)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(dimm);
+
+    return memory_region_size(&nvdimm->nvdimm_mr) ? &nvdimm->nvdimm_mr : NULL;
+}
+
+static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
+{
+    MemoryRegion *mr;
+    NVDIMMDevice *nvdimm = NVDIMM(dimm);
+    uint64_t size;
+
+    nvdimm->label_size = MIN_NAMESPACE_LABEL_SIZE;
+
+    mr = host_memory_backend_get_memory(dimm->hostmem, errp);
+    size = memory_region_size(mr);
+
+    if (size <= nvdimm->label_size) {
+        char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem));
+        error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too small"
+                   " to contain nvdimm namespace label (0x%" PRIx64 ")", path,
+                   memory_region_size(mr), nvdimm->label_size);
+        return;
+    }
+
+    memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm), "nvdimm-memory",
+                             mr, 0, size - nvdimm->label_size);
+    nvdimm->label_data = memory_region_get_ram_ptr(mr) +
+                         memory_region_size(&nvdimm->nvdimm_mr);
+}
+
+static void nvdimm_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    DIMMDeviceClass *ddc = DIMM_CLASS(oc);
+
+    /* nvdimm hotplug has not been supported yet. */
+    dc->hotpluggable = false;
+
+    ddc->realize = nvdimm_realize;
+    ddc->get_memory_region = nvdimm_get_memory_region;
+}
+
+static TypeInfo nvdimm_info = {
+    .name          = TYPE_NVDIMM,
+    .parent        = TYPE_DIMM,
+    .instance_size = sizeof(NVDIMMDevice),
+    .class_init    = nvdimm_class_init,
+};
+
+static void nvdimm_register_types(void)
+{
+    type_register_static(&nvdimm_info);
+}
+
+type_init(nvdimm_register_types)
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
new file mode 100644
index 0000000..60399d8
--- /dev/null
+++ b/include/hw/mem/nvdimm.h
@@ -0,0 +1,66 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * NVDIMM specifications and some documents can be found at:
+ * NVDIMM ACPI device and NFIT are introduced in ACPI 6:
+ *      http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
+ * NVDIMM Namespace specification:
+ *      http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
+ * DSM Interface Example:
+ *      http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+ * Driver Writer's Guide:
+ *      http://pmem.io/documents/NVDIMM_Driver_Writers_Guide.pdf
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_NVDIMM_H
+#define QEMU_NVDIMM_H
+
+#include "hw/mem/dimm.h"
+
+/*
+ * The minimum label data size is required by NVDIMM Namespace
+ * specification, please refer to chapter 2 Namespaces:
+ *   "NVDIMMs following the NVDIMM Block Mode Specification use an area
+ *    at least 128KB in size, which holds around 1000 labels."
+ */
+#define MIN_NAMESPACE_LABEL_SIZE      (128UL << 10)
+
+#define TYPE_NVDIMM      "nvdimm"
+#define NVDIMM(obj)      OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
+
+struct NVDIMMDevice {
+    /* private */
+    DIMMDevice parent_obj;
+
+    /* public */
+
+    /*
+     * the size of label data in NVDIMM device which is presented to
+     * guest via __DSM "Get Namespace Label Size" command.
+     */
+    uint64_t label_size;
+
+    /*
+     * the address of label data which is read by __DSM "Get Namespace
+     * Label Data" command and written by __DSM "Set Namespace Label
+     * Data" command.
+     */
+    void *label_data;
+
+    /*
+     * it's the PMEM region in NVDIMM device, which is presented to
+     * guest via ACPI NFIT and _FIT method if NVDIMM hotplug is supported.
+     */
+    MemoryRegion nvdimm_mr;
+};
+typedef struct NVDIMMDevice NVDIMMDevice;
+
+#endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 22/33] docs: add NVDIMM ACPI documentation
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

It describes the basic concepts of NVDIMM ACPI and the interface
between QEMU and the ACPI BIOS

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 docs/specs/acpi_nvdimm.txt | 154 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 154 insertions(+)
 create mode 100644 docs/specs/acpi_nvdimm.txt

diff --git a/docs/specs/acpi_nvdimm.txt b/docs/specs/acpi_nvdimm.txt
new file mode 100644
index 0000000..feafa93
--- /dev/null
+++ b/docs/specs/acpi_nvdimm.txt
@@ -0,0 +1,154 @@
+QEMU<->ACPI BIOS NVDIMM interface
+---------------------------------
+
+QEMU supports NVDIMM via ACPI. This document describes the basic concepts of
+NVDIMM ACPI and the interface between QEMU and the ACPI BIOS.
+
+NVDIMM ACPI Background
+----------------------
+NVDIMM is introduced in ACPI 6.0 which defines an NVDIMM root device under
+_SB scope with a _HID of “ACPI0012”. For each NVDIMM present or intended
+to be supported by platform, platform firmware also exposes an ACPI
+Namespace Device under the root device.
+
+The NVDIMM child devices under the NVDIMM root device are defined with _ADR
+corresponding to the NFIT device handle. The NVDIMM root device and the
+NVDIMM devices can have device specific methods (_DSM) to provide additional
+functions specific to a particular NVDIMM implementation.
+
+This is an example from ACPI 6.0, a platform contains one NVDIMM:
+
+Scope (\_SB){
+   Device (NVDR) // Root device
+   {
+      Name (_HID, “ACPI0012”)
+      Method (_STA) {...}
+      Method (_FIT) {...}
+      Method (_DSM, ...) {...}
+      Device (NVD)
+      {
+         Name(_ADR, h) //where h is NFIT Device Handle for this NVDIMM
+         Method (_DSM, ...) {...}
+      }
+   }
+}
+
+Methods supported on both NVDIMM root device and NVDIMM device are
+1) _STA(Status)
+   It returns the current status of a device, which can be one of the
+   following: enabled, disabled, or removed.
+
+   Arguments: None
+
+   Return Value:
+   It returns an An Integer which is defined as followings:
+   Bit [0] – Set if the device is present.
+   Bit [1] – Set if the device is enabled and decoding its resources.
+   Bit [2] – Set if the device should be shown in the UI.
+   Bit [3] – Set if the device is functioning properly (cleared if device
+             failed its diagnostics).
+   Bit [4] – Set if the battery is present.
+   Bits [31:5] – Reserved (must be cleared).
+
+2) _DSM (Device Specific Method)
+   It is a control method that enables devices to provide device specific
+   control functions that are consumed by the device driver.
+   The NVDIMM DSM specification can be found at:
+        http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+
+   Arguments:
+   Arg0 – A Buffer containing a UUID (16 Bytes)
+   Arg1 – An Integer containing the Revision ID (4 Bytes)
+   Arg2 – An Integer containing the Function Index (4 Bytes)
+   Arg3 – A package containing parameters for the function specified by the
+          UUID, Revision ID, and Function Index
+
+   Return Value:
+   If Function Index = 0, a Buffer containing a function index bitfield.
+   Otherwise, the return value and type depends on the UUID, revision ID
+   and function index which are described in the DSM specification.
+
+Methods on NVDIMM ROOT Device
+_FIT(Firmware Interface Table)
+   It evaluates to a buffer returning data in the format of a series of NFIT
+   Type Structure.
+
+   Arguments: None
+
+   Return Value:
+   A Buffer containing a list of NFIT Type structure entries.
+
+   The detailed definition of the structure can be found at ACPI 6.0: 5.2.25
+   NVDIMM Firmware Interface Table (NFIT).
+
+QEMU NVDIMM Implemention
+========================
+QEMU reserves the memory region, 0xFF00000 ~ 0xFFF00000, for NVDIMM ACPI.
+
+0xFF00000 - 0xFF00FFF:
+   The first page of the region is MMIO-based that means any access in this
+   region will be emulated by QEMU. ACPU uses it to transfer control from
+   guest to QEMU.
+
+   Write Access:
+       [0xFF00000 - 0xFF00003]: 4 bytes, ACPI write 0x99 to it to transfer
+                                control to QEMU.
+
+0xFF01000 - 0xFF01FFF:
+   This second page of the region is RAM-based and it is used to transfer
+   data between _DSM method and QEMU. If ACPI has control, this pages is
+   owned by ACPI which writes _DSM input data to it, otherwise, it is owned
+   by QEMU which emulates _DSM access and writes the output data to it.
+
+   ACPI Writes _DSM Input Data:
+   [0xFF01000 - 0xFF01003]: 4 bytes, NVDIMM Devcie Handle, 0 is reserved
+                            for NVDIMM Root device.
+   [0xFF01004 - 0xFF01007]: 4 bytes, Revision ID, that is the Arg1 of _DSM
+                            method.
+   [0xFF01008 - 0xFF0100B]: 4 bytes. Function Index, that is the Arg2 of
+                            _DSM method.
+   [0xFF0100C - 0xFF01FFF]: 4084 bytes, the Arg3 of _DSM method
+
+   QEMU Writes Output Data
+   [0xFF01000 - 0xFF01003]: 4 bytes, @buffer-size, see below.
+   [0xFF01004 - @buffer-size]: the size is depends on the value read from
+                               0xFF01000 - 0xFF01003. It is the buffer
+                               returned by _DSM
+
+0xFF02000 - 0xFFF00000:
+   It is RAM-based mapping. QEMU inquires all the NVDIMM device plugged into
+   the platform and saves their structures to this region while system is
+   booting or NVDIMM device is being hot added or removed (not enabled yet).
+
+   _FIT method gets system structure information from this region and returns
+   it to Guest.
+
+_DSM process diagram:
+---------------------
+The second page in the reserved region, 0xFF01000 - 0xFF01FFF, is used by
+_DSM Virtualization.
+
+ +----------------------+      +-----------------------+
+ |    1. OSPM           |      |    2. OSPM            |
+ | save _DSM input data |      | write 0x99 to         | Exit to QEMU
+ | to the page          +----->| 0xFF00000 - 0xFF00003 +------------+
+ |                      |      |                       |            |
+ +----------------------+      +-----------------------+            |
+                                                                    |
+                                                                    v
+ +-------------   ----+       +-----------+      +------------------+--------+
+ |      5 QEMU        |       | 4 QEMU    |      |        3. QEMU            |
+ | write buffer size  |       |  emulate  |      | get _DSM input parameters |
+ | and buffer to      +<------+ _DSM      +<-----+ from the page             |
+ | the page           |       |           |      |                           |
+ +--------+-----------+       +-----------+      +---------------------------+
+          |
+          | Enter Guest
+          |
+          v
+ +--------------------------+      +--------------+
+ |     6 OSPM               |      |   7 OSPM     |
+ | get buffer size          |      |  _DSM return |
+ | and buffer from the page +----->+              |
+ |                          |      |              |
+ +--------------------------+      +--------------+
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 22/33] docs: add NVDIMM ACPI documentation
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

It describes the basic concepts of NVDIMM ACPI and the interface
between QEMU and the ACPI BIOS

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 docs/specs/acpi_nvdimm.txt | 154 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 154 insertions(+)
 create mode 100644 docs/specs/acpi_nvdimm.txt

diff --git a/docs/specs/acpi_nvdimm.txt b/docs/specs/acpi_nvdimm.txt
new file mode 100644
index 0000000..feafa93
--- /dev/null
+++ b/docs/specs/acpi_nvdimm.txt
@@ -0,0 +1,154 @@
+QEMU<->ACPI BIOS NVDIMM interface
+---------------------------------
+
+QEMU supports NVDIMM via ACPI. This document describes the basic concepts of
+NVDIMM ACPI and the interface between QEMU and the ACPI BIOS.
+
+NVDIMM ACPI Background
+----------------------
+NVDIMM is introduced in ACPI 6.0 which defines an NVDIMM root device under
+_SB scope with a _HID of “ACPI0012”. For each NVDIMM present or intended
+to be supported by platform, platform firmware also exposes an ACPI
+Namespace Device under the root device.
+
+The NVDIMM child devices under the NVDIMM root device are defined with _ADR
+corresponding to the NFIT device handle. The NVDIMM root device and the
+NVDIMM devices can have device specific methods (_DSM) to provide additional
+functions specific to a particular NVDIMM implementation.
+
+This is an example from ACPI 6.0, a platform contains one NVDIMM:
+
+Scope (\_SB){
+   Device (NVDR) // Root device
+   {
+      Name (_HID, “ACPI0012”)
+      Method (_STA) {...}
+      Method (_FIT) {...}
+      Method (_DSM, ...) {...}
+      Device (NVD)
+      {
+         Name(_ADR, h) //where h is NFIT Device Handle for this NVDIMM
+         Method (_DSM, ...) {...}
+      }
+   }
+}
+
+Methods supported on both NVDIMM root device and NVDIMM device are
+1) _STA(Status)
+   It returns the current status of a device, which can be one of the
+   following: enabled, disabled, or removed.
+
+   Arguments: None
+
+   Return Value:
+   It returns an An Integer which is defined as followings:
+   Bit [0] – Set if the device is present.
+   Bit [1] – Set if the device is enabled and decoding its resources.
+   Bit [2] – Set if the device should be shown in the UI.
+   Bit [3] – Set if the device is functioning properly (cleared if device
+             failed its diagnostics).
+   Bit [4] – Set if the battery is present.
+   Bits [31:5] – Reserved (must be cleared).
+
+2) _DSM (Device Specific Method)
+   It is a control method that enables devices to provide device specific
+   control functions that are consumed by the device driver.
+   The NVDIMM DSM specification can be found at:
+        http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+
+   Arguments:
+   Arg0 – A Buffer containing a UUID (16 Bytes)
+   Arg1 – An Integer containing the Revision ID (4 Bytes)
+   Arg2 – An Integer containing the Function Index (4 Bytes)
+   Arg3 – A package containing parameters for the function specified by the
+          UUID, Revision ID, and Function Index
+
+   Return Value:
+   If Function Index = 0, a Buffer containing a function index bitfield.
+   Otherwise, the return value and type depends on the UUID, revision ID
+   and function index which are described in the DSM specification.
+
+Methods on NVDIMM ROOT Device
+_FIT(Firmware Interface Table)
+   It evaluates to a buffer returning data in the format of a series of NFIT
+   Type Structure.
+
+   Arguments: None
+
+   Return Value:
+   A Buffer containing a list of NFIT Type structure entries.
+
+   The detailed definition of the structure can be found at ACPI 6.0: 5.2.25
+   NVDIMM Firmware Interface Table (NFIT).
+
+QEMU NVDIMM Implemention
+========================
+QEMU reserves the memory region, 0xFF00000 ~ 0xFFF00000, for NVDIMM ACPI.
+
+0xFF00000 - 0xFF00FFF:
+   The first page of the region is MMIO-based that means any access in this
+   region will be emulated by QEMU. ACPU uses it to transfer control from
+   guest to QEMU.
+
+   Write Access:
+       [0xFF00000 - 0xFF00003]: 4 bytes, ACPI write 0x99 to it to transfer
+                                control to QEMU.
+
+0xFF01000 - 0xFF01FFF:
+   This second page of the region is RAM-based and it is used to transfer
+   data between _DSM method and QEMU. If ACPI has control, this pages is
+   owned by ACPI which writes _DSM input data to it, otherwise, it is owned
+   by QEMU which emulates _DSM access and writes the output data to it.
+
+   ACPI Writes _DSM Input Data:
+   [0xFF01000 - 0xFF01003]: 4 bytes, NVDIMM Devcie Handle, 0 is reserved
+                            for NVDIMM Root device.
+   [0xFF01004 - 0xFF01007]: 4 bytes, Revision ID, that is the Arg1 of _DSM
+                            method.
+   [0xFF01008 - 0xFF0100B]: 4 bytes. Function Index, that is the Arg2 of
+                            _DSM method.
+   [0xFF0100C - 0xFF01FFF]: 4084 bytes, the Arg3 of _DSM method
+
+   QEMU Writes Output Data
+   [0xFF01000 - 0xFF01003]: 4 bytes, @buffer-size, see below.
+   [0xFF01004 - @buffer-size]: the size is depends on the value read from
+                               0xFF01000 - 0xFF01003. It is the buffer
+                               returned by _DSM
+
+0xFF02000 - 0xFFF00000:
+   It is RAM-based mapping. QEMU inquires all the NVDIMM device plugged into
+   the platform and saves their structures to this region while system is
+   booting or NVDIMM device is being hot added or removed (not enabled yet).
+
+   _FIT method gets system structure information from this region and returns
+   it to Guest.
+
+_DSM process diagram:
+---------------------
+The second page in the reserved region, 0xFF01000 - 0xFF01FFF, is used by
+_DSM Virtualization.
+
+ +----------------------+      +-----------------------+
+ |    1. OSPM           |      |    2. OSPM            |
+ | save _DSM input data |      | write 0x99 to         | Exit to QEMU
+ | to the page          +----->| 0xFF00000 - 0xFF00003 +------------+
+ |                      |      |                       |            |
+ +----------------------+      +-----------------------+            |
+                                                                    |
+                                                                    v
+ +-------------   ----+       +-----------+      +------------------+--------+
+ |      5 QEMU        |       | 4 QEMU    |      |        3. QEMU            |
+ | write buffer size  |       |  emulate  |      | get _DSM input parameters |
+ | and buffer to      +<------+ _DSM      +<-----+ from the page             |
+ | the page           |       |           |      |                           |
+ +--------+-----------+       +-----------+      +---------------------------+
+          |
+          | Enter Guest
+          |
+          v
+ +--------------------------+      +--------------+
+ |     6 OSPM               |      |   7 OSPM     |
+ | get buffer size          |      |  _DSM return |
+ | and buffer from the page +----->+              |
+ |                          |      |              |
+ +--------------------------+      +--------------+
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

We reserve the memory region 0xFF00000 ~ 0xFFF00000 for NVDIMM ACPI
which is used as:
- the first page is mapped as MMIO, ACPI write data to this page to
  transfer the control to QEMU

- the second page is RAM-based which used to save the input info of
  _DSM method and QEMU reuse it store output info

- the left is mapped as RAM, it's the buffer returned by _FIT method,
  this is needed by NVDIMM hotplug

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/Makefile.objs   |   1 +
 hw/acpi/nvdimm.c        | 143 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc.c            |   2 +
 include/hw/i386/pc.h    |   2 +
 include/hw/mem/nvdimm.h |  18 ++++++
 5 files changed, 166 insertions(+)
 create mode 100644 hw/acpi/nvdimm.c

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 7d3230c..80426b4 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -2,6 +2,7 @@ common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
 common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
 common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
+common-obj-$(CONFIG_NVDIMM) += nvdimm.o
 common-obj-$(CONFIG_ACPI) += acpi_interface.o
 common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
 common-obj-$(CONFIG_ACPI) += aml-build.o
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
new file mode 100644
index 0000000..fd70de2
--- /dev/null
+++ b/hw/acpi/nvdimm.c
@@ -0,0 +1,143 @@
+/*
+ * NVDIMM ACPI Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * NFIT is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
+ * and the DSM specification can be found at:
+ *       http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+ *
+ * Currently, it only supports PMEM Virtualization.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "qemu-common.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/mem/nvdimm.h"
+
+/*
+ * System Physical Address Range Structure
+ *
+ * It describes the system physical address ranges occupied by NVDIMMs and
+ * the types of the regions.
+ */
+struct nfit_spa {
+    uint16_t type;
+    uint16_t length;
+    uint16_t spa_index;
+    uint16_t flags;
+    uint32_t reserved;
+    uint32_t proximity_domain;
+    uint8_t type_guid[16];
+    uint64_t spa_base;
+    uint64_t spa_length;
+    uint64_t mem_attr;
+} QEMU_PACKED;
+typedef struct nfit_spa nfit_spa;
+
+/*
+ * Memory Device to System Physical Address Range Mapping Structure
+ *
+ * It enables identifying each NVDIMM region and the corresponding SPA
+ * describing the memory interleave
+ */
+struct nfit_memdev {
+    uint16_t type;
+    uint16_t length;
+    uint32_t nfit_handle;
+    uint16_t phys_id;
+    uint16_t region_id;
+    uint16_t spa_index;
+    uint16_t dcr_index;
+    uint64_t region_len;
+    uint64_t region_offset;
+    uint64_t region_dpa;
+    uint16_t interleave_index;
+    uint16_t interleave_ways;
+    uint16_t flags;
+    uint16_t reserved;
+} QEMU_PACKED;
+typedef struct nfit_memdev nfit_memdev;
+
+/*
+ * NVDIMM Control Region Structure
+ *
+ * It describes the NVDIMM and if applicable, Block Control Window.
+ */
+struct nfit_dcr {
+    uint16_t type;
+    uint16_t length;
+    uint16_t dcr_index;
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint16_t revision_id;
+    uint16_t sub_vendor_id;
+    uint16_t sub_device_id;
+    uint16_t sub_revision_id;
+    uint8_t reserved[6];
+    uint32_t serial_number;
+    uint16_t fic;
+    uint16_t num_bcw;
+    uint64_t bcw_size;
+    uint64_t cmd_offset;
+    uint64_t cmd_size;
+    uint64_t status_offset;
+    uint64_t status_size;
+    uint16_t flags;
+    uint8_t reserved2[6];
+} QEMU_PACKED;
+typedef struct nfit_dcr nfit_dcr;
+
+/*
+ * calculate the size of structures which describe all NVDIMM devices.
+ * Currently each device has three structures as only PMEM is supported
+ * now.
+ */
+static uint64_t nvdimm_device_structure_size(uint64_t slots)
+{
+    return slots * (sizeof(nfit_spa) + sizeof(nfit_memdev) + sizeof(nfit_dcr));
+}
+
+/*
+ * calculate the size of the memory used to implement NVDIMM ACPI operations
+ * which include:
+ * - __DSM method: it needs two pages to transfer control and data between
+ *   Guest ACPI and QEMU.
+ *
+ * - _FIT method: it returns a buffer to Guest which contains the structures
+ *   describing all the present NVDIMM devices in the system.
+ */
+static uint64_t nvdimm_acpi_memory_size(uint64_t slots)
+{
+    uint64_t size = nvdimm_device_structure_size(slots);
+
+    return size + getpagesize() * 2;
+}
+
+void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
+                              MachineState *machine)
+{
+    QEMU_BUILD_BUG_ON(nvdimm_acpi_memory_size(ACPI_MAX_RAM_SLOTS)
+                         >= NVDIMM_ACPI_MEM_SIZE);
+
+    state->base = NVDIMM_ACPI_MEM_BASE;
+    memory_region_init(&state->mr, OBJECT(machine), "nvdimm-acpi",
+                       NVDIMM_ACPI_MEM_SIZE);
+    memory_region_add_subregion(system_memory, state->base, &state->mr);
+}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 6694b18..2207e09 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1360,6 +1360,8 @@ FWCfgState *pc_memory_init(PCMachineState *pcms,
             exit(EXIT_FAILURE);
         }
 
+        nvdimm_init_memory_state(&pcms->nvdimm_memory, system_memory, machine);
+
         pcms->hotplug_memory.base =
             ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30);
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 693b6c5..fd65c27 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -17,6 +17,7 @@
 #include "hw/boards.h"
 #include "hw/compat.h"
 #include "hw/mem/dimm.h"
+#include "hw/mem/nvdimm.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
@@ -32,6 +33,7 @@ struct PCMachineState {
 
     /* <public> */
     MemoryHotplugState hotplug_memory;
+    NVDIMMState nvdimm_memory;
 
     HotplugHandler *acpi_dev;
     ISADevice *rtc;
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 60399d8..8e31983 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -33,6 +33,10 @@
  */
 #define MIN_NAMESPACE_LABEL_SIZE      (128UL << 10)
 
+/* Memory region 0xFF00000 ~ 0xFFF00000 is reserved for NVDIMM ACPI. */
+#define NVDIMM_ACPI_MEM_BASE          0xFF000000ULL
+#define NVDIMM_ACPI_MEM_SIZE          0xF00000ULL
+
 #define TYPE_NVDIMM      "nvdimm"
 #define NVDIMM(obj)      OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
 
@@ -63,4 +67,18 @@ struct NVDIMMDevice {
 };
 typedef struct NVDIMMDevice NVDIMMDevice;
 
+/*
+ * NVDIMMState:
+ * @base: address in guest address space where NVDIMM ACPI memory begins.
+ * @mr: NVDIMM ACPI memory address space container.
+ */
+struct NVDIMMState {
+    ram_addr_t base;
+    MemoryRegion mr;
+};
+typedef struct NVDIMMState NVDIMMState;
+
+/* Initialize the memory region needed by NVDIMM ACPI.*/
+void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
+                              MachineState *machine);
 #endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

We reserve the memory region 0xFF00000 ~ 0xFFF00000 for NVDIMM ACPI
which is used as:
- the first page is mapped as MMIO, ACPI write data to this page to
  transfer the control to QEMU

- the second page is RAM-based which used to save the input info of
  _DSM method and QEMU reuse it store output info

- the left is mapped as RAM, it's the buffer returned by _FIT method,
  this is needed by NVDIMM hotplug

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/Makefile.objs   |   1 +
 hw/acpi/nvdimm.c        | 143 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc.c            |   2 +
 include/hw/i386/pc.h    |   2 +
 include/hw/mem/nvdimm.h |  18 ++++++
 5 files changed, 166 insertions(+)
 create mode 100644 hw/acpi/nvdimm.c

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 7d3230c..80426b4 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -2,6 +2,7 @@ common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
 common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
 common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
+common-obj-$(CONFIG_NVDIMM) += nvdimm.o
 common-obj-$(CONFIG_ACPI) += acpi_interface.o
 common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
 common-obj-$(CONFIG_ACPI) += aml-build.o
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
new file mode 100644
index 0000000..fd70de2
--- /dev/null
+++ b/hw/acpi/nvdimm.c
@@ -0,0 +1,143 @@
+/*
+ * NVDIMM ACPI Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *  Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * NFIT is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
+ * and the DSM specification can be found at:
+ *       http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+ *
+ * Currently, it only supports PMEM Virtualization.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "qemu-common.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/mem/nvdimm.h"
+
+/*
+ * System Physical Address Range Structure
+ *
+ * It describes the system physical address ranges occupied by NVDIMMs and
+ * the types of the regions.
+ */
+struct nfit_spa {
+    uint16_t type;
+    uint16_t length;
+    uint16_t spa_index;
+    uint16_t flags;
+    uint32_t reserved;
+    uint32_t proximity_domain;
+    uint8_t type_guid[16];
+    uint64_t spa_base;
+    uint64_t spa_length;
+    uint64_t mem_attr;
+} QEMU_PACKED;
+typedef struct nfit_spa nfit_spa;
+
+/*
+ * Memory Device to System Physical Address Range Mapping Structure
+ *
+ * It enables identifying each NVDIMM region and the corresponding SPA
+ * describing the memory interleave
+ */
+struct nfit_memdev {
+    uint16_t type;
+    uint16_t length;
+    uint32_t nfit_handle;
+    uint16_t phys_id;
+    uint16_t region_id;
+    uint16_t spa_index;
+    uint16_t dcr_index;
+    uint64_t region_len;
+    uint64_t region_offset;
+    uint64_t region_dpa;
+    uint16_t interleave_index;
+    uint16_t interleave_ways;
+    uint16_t flags;
+    uint16_t reserved;
+} QEMU_PACKED;
+typedef struct nfit_memdev nfit_memdev;
+
+/*
+ * NVDIMM Control Region Structure
+ *
+ * It describes the NVDIMM and if applicable, Block Control Window.
+ */
+struct nfit_dcr {
+    uint16_t type;
+    uint16_t length;
+    uint16_t dcr_index;
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint16_t revision_id;
+    uint16_t sub_vendor_id;
+    uint16_t sub_device_id;
+    uint16_t sub_revision_id;
+    uint8_t reserved[6];
+    uint32_t serial_number;
+    uint16_t fic;
+    uint16_t num_bcw;
+    uint64_t bcw_size;
+    uint64_t cmd_offset;
+    uint64_t cmd_size;
+    uint64_t status_offset;
+    uint64_t status_size;
+    uint16_t flags;
+    uint8_t reserved2[6];
+} QEMU_PACKED;
+typedef struct nfit_dcr nfit_dcr;
+
+/*
+ * calculate the size of structures which describe all NVDIMM devices.
+ * Currently each device has three structures as only PMEM is supported
+ * now.
+ */
+static uint64_t nvdimm_device_structure_size(uint64_t slots)
+{
+    return slots * (sizeof(nfit_spa) + sizeof(nfit_memdev) + sizeof(nfit_dcr));
+}
+
+/*
+ * calculate the size of the memory used to implement NVDIMM ACPI operations
+ * which include:
+ * - __DSM method: it needs two pages to transfer control and data between
+ *   Guest ACPI and QEMU.
+ *
+ * - _FIT method: it returns a buffer to Guest which contains the structures
+ *   describing all the present NVDIMM devices in the system.
+ */
+static uint64_t nvdimm_acpi_memory_size(uint64_t slots)
+{
+    uint64_t size = nvdimm_device_structure_size(slots);
+
+    return size + getpagesize() * 2;
+}
+
+void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
+                              MachineState *machine)
+{
+    QEMU_BUILD_BUG_ON(nvdimm_acpi_memory_size(ACPI_MAX_RAM_SLOTS)
+                         >= NVDIMM_ACPI_MEM_SIZE);
+
+    state->base = NVDIMM_ACPI_MEM_BASE;
+    memory_region_init(&state->mr, OBJECT(machine), "nvdimm-acpi",
+                       NVDIMM_ACPI_MEM_SIZE);
+    memory_region_add_subregion(system_memory, state->base, &state->mr);
+}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 6694b18..2207e09 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1360,6 +1360,8 @@ FWCfgState *pc_memory_init(PCMachineState *pcms,
             exit(EXIT_FAILURE);
         }
 
+        nvdimm_init_memory_state(&pcms->nvdimm_memory, system_memory, machine);
+
         pcms->hotplug_memory.base =
             ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30);
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 693b6c5..fd65c27 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -17,6 +17,7 @@
 #include "hw/boards.h"
 #include "hw/compat.h"
 #include "hw/mem/dimm.h"
+#include "hw/mem/nvdimm.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
@@ -32,6 +33,7 @@ struct PCMachineState {
 
     /* <public> */
     MemoryHotplugState hotplug_memory;
+    NVDIMMState nvdimm_memory;
 
     HotplugHandler *acpi_dev;
     ISADevice *rtc;
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 60399d8..8e31983 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -33,6 +33,10 @@
  */
 #define MIN_NAMESPACE_LABEL_SIZE      (128UL << 10)
 
+/* Memory region 0xFF00000 ~ 0xFFF00000 is reserved for NVDIMM ACPI. */
+#define NVDIMM_ACPI_MEM_BASE          0xFF000000ULL
+#define NVDIMM_ACPI_MEM_SIZE          0xF00000ULL
+
 #define TYPE_NVDIMM      "nvdimm"
 #define NVDIMM(obj)      OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
 
@@ -63,4 +67,18 @@ struct NVDIMMDevice {
 };
 typedef struct NVDIMMDevice NVDIMMDevice;
 
+/*
+ * NVDIMMState:
+ * @base: address in guest address space where NVDIMM ACPI memory begins.
+ * @mr: NVDIMM ACPI memory address space container.
+ */
+struct NVDIMMState {
+    ram_addr_t base;
+    MemoryRegion mr;
+};
+typedef struct NVDIMMState NVDIMMState;
+
+/* Initialize the memory region needed by NVDIMM ACPI.*/
+void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
+                              MachineState *machine);
 #endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 24/33] nvdimm acpi: build ACPI NFIT table
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

NFIT is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)

Currently, we only support PMEM mode. Each device has 3 structures:
- SPA structure, defines the PMEM region info

- MEM DEV structure, it has the @handle which is used to associate specified
  ACPI NVDIMM  device we will introduce in later patch.
  Also we can happily ignored the memory device's interleave, the real
  nvdimm hardware access is hidden behind host

- DCR structure, it defines vendor ID used to associate specified vendor
  nvdimm driver. Since we only implement PMEM mode this time, Command
  window and Data window are not needed

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 286 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c    |  10 ++
 hw/mem/nvdimm.c         |  24 ++++
 include/hw/mem/nvdimm.h |  13 +++
 4 files changed, 333 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index fd70de2..8d8376c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -31,6 +31,72 @@
 #include "hw/acpi/aml-build.h"
 #include "hw/mem/nvdimm.h"
 
+#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)             \
+   { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+     (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff,          \
+     (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
+
+/*
+ * This GUID defines a Byte Addressable Persistent Memory (PM) Region.
+ * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
+ * Structure.
+ */
+static const uint8_t nfit_spa_uuid_pm[] = NVDIMM_UUID_LE(0x66f0d379, 0xb4f3,
+                0x4074, 0xac, 0x43, 0x0d, 0x33, 0x18, 0xb7, 0x8c, 0xdb);
+
+/* NFIT Structure Types. */
+enum {
+    NFIT_STRUCTURE_SPA = 0,
+    NFIT_STRUCTURE_MEMDEV = 1,
+    NFIT_STRUCTURE_IDT = 2,
+    NFIT_STRUCTURE_SMBIOS = 3,
+    NFIT_STRUCTURE_DCR = 4,
+    NFIT_STRUCTURE_BDW = 5,
+    NFIT_STRUCTURE_FLUSH = 6,
+};
+
+/*
+ * NVDIMM Firmware Interface Table
+ * @signature: "NFIT"
+ *
+ * It provides information that allows OSPM to enumerate NVDIMM present in
+ * the platform and associate system physical address ranges created by the
+ * NVDIMMs.
+ *
+ * Detailed info please refer to ACPI 6.0: 5.2.25 NVDIMM Firmware Interface
+ * Table (NFIT)
+ */
+struct nfit {
+    ACPI_TABLE_HEADER_DEF
+    uint32_t reserved;
+} QEMU_PACKED;
+typedef struct nfit nfit;
+
+/*
+ * Memory mapping attributes for the address range described in system
+ * physical address range structure.
+ */
+enum {
+    EFI_MEMORY_UC = 0x1ULL,
+    EFI_MEMORY_WC = 0x2ULL,
+    EFI_MEMORY_WT = 0x4ULL,
+    EFI_MEMORY_WB = 0x8ULL,
+    EFI_MEMORY_UCE = 0x10ULL,
+    EFI_MEMORY_WP = 0x1000ULL,
+    EFI_MEMORY_RP = 0x2000ULL,
+    EFI_MEMORY_XP = 0x4000ULL,
+    EFI_MEMORY_NV = 0x8000ULL,
+    EFI_MEMORY_MORE_RELIABLE = 0x10000ULL,
+};
+
+/*
+ * Control region is strictly for management during hot add/online
+ * operation.
+ */
+#define SPA_FLAGS_ADD_ONLINE_ONLY     (1)
+/* Data in Proximity Domain field is valid. */
+#define SPA_FLAGS_PROXIMITY_VALID     (1 << 1)
+
 /*
  * System Physical Address Range Structure
  *
@@ -76,6 +142,14 @@ struct nfit_memdev {
 typedef struct nfit_memdev nfit_memdev;
 
 /*
+ * please refer to DSM specification, Chapter 2 NVDIMM Device Specific
+ * Method (DSM).
+ */
+#define REVSISON_ID    1
+/* the format interface code supported by DSM specification. */
+#define NFIT_FIC1      0x201
+
+/*
  * NVDIMM Control Region Structure
  *
  * It describes the NVDIMM and if applicable, Block Control Window.
@@ -141,3 +215,215 @@ void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
                        NVDIMM_ACPI_MEM_SIZE);
     memory_region_add_subregion(system_memory, state->base, &state->mr);
 }
+
+/*
+ * Module serial number is a unique number for each device. We use the
+ * slot id of NVDIMM device to generate this number so that each device
+ * associates with a different number.
+ *
+ * 0x123456 is a magic number we arbitrarily chose.
+ */
+static uint32_t nvdimm_slot_to_sn(int slot)
+{
+    return 0x123456 + slot;
+}
+
+/*
+ * handle is used to uniquely associate nfit_memdev structure with NVDIMM
+ * ACPI device - nfit_memdev.nfit_handle matches with the value returned
+ * by ACPI device _ADR method.
+ *
+ * We generate the handle with the slot id of NVDIMM device and reserve
+ * 0 for NVDIMM root device.
+ */
+static uint32_t nvdimm_slot_to_handle(int slot)
+{
+    return slot + 1;
+}
+
+/*
+ * index uniquely identifies the structure, 0 is reserved which indicates
+ * that the structure is not valid or the associated structure is not
+ * present.
+ *
+ * Each NVDIMM device needs two indexes, one for nfit_spa and another for
+ * nfit_dc which are generated by the slot id of NVDIMM device.
+ */
+static uint16_t nvdimm_slot_to_spa_index(int slot)
+{
+    return (slot + 1) << 1;
+}
+
+/* See the comment of nvdimm_slot_to_spa_index(). */
+static uint32_t nvdimm_slot_to_dcr_index(int slot)
+{
+    return nvdimm_slot_to_spa_index(slot) + 1;
+}
+
+/*
+ * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
+ * Structure
+ */
+static void
+nvdimm_build_structure_spa(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_spa *nfit_spa;
+    uint64_t addr = object_property_get_int(OBJECT(nvdimm), DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(nvdimm), DIMM_SIZE_PROP,
+                                            NULL);
+    uint32_t node = object_property_get_int(OBJECT(nvdimm), DIMM_NODE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                            NULL);
+
+    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
+
+    /* System Physical Address Range Structure */
+    nfit_spa->type = cpu_to_le16(NFIT_STRUCTURE_SPA);
+    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
+    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+
+    /*
+     * - Proximity Domain field is valid as NUMA node is valid.
+     * - Control region is strictly during hot add as all the device
+     *   info, such as SN, index, is associated with slot id.
+     */
+    nfit_spa->flags = cpu_to_le16(SPA_FLAGS_PROXIMITY_VALID |
+                                  SPA_FLAGS_ADD_ONLINE_ONLY);
+
+    /* NUMA node. */
+    nfit_spa->proximity_domain = cpu_to_le32(node);
+    /* the region reported as PMEM. */
+    memcpy(nfit_spa->type_guid, nfit_spa_uuid_pm, sizeof(nfit_spa_uuid_pm));
+
+    nfit_spa->spa_base = cpu_to_le64(addr);
+    nfit_spa->spa_length = cpu_to_le64(size);
+
+    /* It is the PMEM and can be cached as writeback. */
+    nfit_spa->mem_attr = cpu_to_le64(EFI_MEMORY_WB | EFI_MEMORY_NV);
+}
+
+/*
+ * Please refer to ACPI 6.0: 5.2.25.2 Memory Device to System Physical
+ * Address Range Mapping Structure
+ */
+static void
+nvdimm_build_structure_memdev(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_memdev *nfit_memdev;
+    uint64_t addr = object_property_get_int(OBJECT(nvdimm), DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(nvdimm), DIMM_SIZE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                            NULL);
+    uint32_t handle = nvdimm_slot_to_handle(slot);
+
+    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
+
+    /* Memory Device to System Address Range Map Structure */
+    nfit_memdev->type = cpu_to_le16(NFIT_STRUCTURE_MEMDEV);
+    nfit_memdev->length = cpu_to_le16(sizeof(*nfit_memdev));
+    nfit_memdev->nfit_handle = cpu_to_le32(handle);
+
+    /*
+     * associate memory device with System Physical Address Range
+     * Structure.
+     */
+    nfit_memdev->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+    /* associate memory device with Control Region Structure. */
+    nfit_memdev->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
+
+    /* The memory region on the device. */
+    nfit_memdev->region_len = cpu_to_le64(size);
+    nfit_memdev->region_dpa = cpu_to_le64(addr);
+
+    /* Only one interleave for PMEM. */
+    nfit_memdev->interleave_ways = cpu_to_le16(1);
+}
+
+/* Please refer to ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure */
+static void nvdimm_build_structure_dcr(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_dcr *nfit_dcr;
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                       NULL);
+    uint32_t sn = nvdimm_slot_to_sn(slot);
+
+    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
+
+    /* NVDIMM Control Region Structure */
+    nfit_dcr->type = cpu_to_le16(NFIT_STRUCTURE_DCR);
+    nfit_dcr->length = cpu_to_le16(sizeof(*nfit_dcr));
+    nfit_dcr->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
+
+    /* vendor: Intel. */
+    nfit_dcr->vendor_id = cpu_to_le16(0x8086);
+    nfit_dcr->device_id = cpu_to_le16(1);
+
+    /* The _DSM method is following Intel's DSM specification. */
+    nfit_dcr->revision_id = cpu_to_le16(REVSISON_ID);
+    nfit_dcr->serial_number = cpu_to_le32(sn);
+    nfit_dcr->fic = cpu_to_le16(NFIT_FIC1);
+}
+
+static GArray *nvdimm_build_device_structure(GSList *device_list)
+{
+    GArray *structures = g_array_new(false, true /* clear */, 1);
+
+    for (; device_list; device_list = device_list->next) {
+        NVDIMMDevice *nvdimm = device_list->data;
+
+        /* build System Physical Address Range Structure. */
+        nvdimm_build_structure_spa(structures, nvdimm);
+
+        /*
+         * build Memory Device to System Physical Address Range Mapping
+         * Structure.
+         */
+        nvdimm_build_structure_memdev(structures, nvdimm);
+
+        /* build NVDIMM Control Region Structure. */
+        nvdimm_build_structure_dcr(structures, nvdimm);
+    }
+
+    return structures;
+}
+
+static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
+                              GArray *table_data, GArray *linker)
+{
+    GArray *structures = nvdimm_build_device_structure(device_list);
+    void *header;
+
+    acpi_add_table(table_offsets, table_data);
+
+    /* NFIT header. */
+    header = acpi_data_push(table_data, sizeof(nfit));
+
+    /* NVDIMM device structures. */
+    g_array_append_vals(table_data, structures->data, structures->len);
+
+    build_header(linker, table_data, header, "NFIT",
+                 sizeof(nfit) + structures->len, 1);
+    g_array_free(structures, true);
+}
+
+void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
+                       GArray *table_data, GArray *linker)
+{
+    GSList *device_list = nvdimm_get_plugged_device_list();
+
+    if (!memory_region_size(&state->mr)) {
+        assert(!device_list);
+        return;
+    }
+
+    if (!device_list) {
+        return;
+    }
+
+    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    g_slist_free(device_list);
+}
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..7531537 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1658,6 +1658,13 @@ static bool acpi_has_iommu(void)
     return intel_iommu && !ambiguous;
 }
 
+static NVDIMMState *acpi_get_nvdimm_state(void)
+{
+    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+
+    return &pcms->nvdimm_memory;
+}
+
 static
 void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 {
@@ -1742,6 +1749,9 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
         build_dmar_q35(tables_blob, tables->linker);
     }
 
+    nvdimm_build_acpi(acpi_get_nvdimm_state(), table_offsets, tables_blob,
+                      tables->linker);
+
     /* Add tables supplied by user (if any) */
     for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
         unsigned len = acpi_table_len(u);
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 51494b6..2d121f6 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -25,6 +25,30 @@
 #include "qapi/visitor.h"
 #include "hw/mem/nvdimm.h"
 
+static int nvdimm_plugged_device_list(Object *obj, void *opaque)
+{
+    GSList **list = opaque;
+
+    if (object_dynamic_cast(obj, TYPE_NVDIMM)) {
+        NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+        if (memory_region_is_mapped(&nvdimm->nvdimm_mr)) {
+            *list = g_slist_append(*list, DEVICE(obj));
+        }
+    }
+
+    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
+    return 0;
+}
+
+GSList *nvdimm_get_plugged_device_list(void)
+{
+    GSList *list = NULL;
+
+    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list, &list);
+    return list;
+}
+
 static MemoryRegion *nvdimm_get_memory_region(DIMMDevice *dimm)
 {
     NVDIMMDevice *nvdimm = NVDIMM(dimm);
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 8e31983..dc77a1f 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -68,6 +68,15 @@ struct NVDIMMDevice {
 typedef struct NVDIMMDevice NVDIMMDevice;
 
 /*
+ * inquire plugged NVDIMM devices and link them into the list which is
+ * returned to the caller.
+ *
+ * Note: it is the caller's responsibility to free the list to avoid
+ * memory leak.
+ */
+GSList *nvdimm_get_plugged_device_list(void);
+
+/*
  * NVDIMMState:
  * @base: address in guest address space where NVDIMM ACPI memory begins.
  * @mr: NVDIMM ACPI memory address space container.
@@ -81,4 +90,8 @@ typedef struct NVDIMMState NVDIMMState;
 /* Initialize the memory region needed by NVDIMM ACPI.*/
 void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
                               MachineState *machine);
+
+/* Build NVDIMM ACPI including NFIT, NVDIMM devices, etc. */
+void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
+                       GArray *table_data, GArray *linker);
 #endif
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 24/33] nvdimm acpi: build ACPI NFIT table
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

NFIT is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)

Currently, we only support PMEM mode. Each device has 3 structures:
- SPA structure, defines the PMEM region info

- MEM DEV structure, it has the @handle which is used to associate specified
  ACPI NVDIMM  device we will introduce in later patch.
  Also we can happily ignored the memory device's interleave, the real
  nvdimm hardware access is hidden behind host

- DCR structure, it defines vendor ID used to associate specified vendor
  nvdimm driver. Since we only implement PMEM mode this time, Command
  window and Data window are not needed

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 286 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c    |  10 ++
 hw/mem/nvdimm.c         |  24 ++++
 include/hw/mem/nvdimm.h |  13 +++
 4 files changed, 333 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index fd70de2..8d8376c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -31,6 +31,72 @@
 #include "hw/acpi/aml-build.h"
 #include "hw/mem/nvdimm.h"
 
+#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)             \
+   { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+     (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff,          \
+     (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
+
+/*
+ * This GUID defines a Byte Addressable Persistent Memory (PM) Region.
+ * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
+ * Structure.
+ */
+static const uint8_t nfit_spa_uuid_pm[] = NVDIMM_UUID_LE(0x66f0d379, 0xb4f3,
+                0x4074, 0xac, 0x43, 0x0d, 0x33, 0x18, 0xb7, 0x8c, 0xdb);
+
+/* NFIT Structure Types. */
+enum {
+    NFIT_STRUCTURE_SPA = 0,
+    NFIT_STRUCTURE_MEMDEV = 1,
+    NFIT_STRUCTURE_IDT = 2,
+    NFIT_STRUCTURE_SMBIOS = 3,
+    NFIT_STRUCTURE_DCR = 4,
+    NFIT_STRUCTURE_BDW = 5,
+    NFIT_STRUCTURE_FLUSH = 6,
+};
+
+/*
+ * NVDIMM Firmware Interface Table
+ * @signature: "NFIT"
+ *
+ * It provides information that allows OSPM to enumerate NVDIMM present in
+ * the platform and associate system physical address ranges created by the
+ * NVDIMMs.
+ *
+ * Detailed info please refer to ACPI 6.0: 5.2.25 NVDIMM Firmware Interface
+ * Table (NFIT)
+ */
+struct nfit {
+    ACPI_TABLE_HEADER_DEF
+    uint32_t reserved;
+} QEMU_PACKED;
+typedef struct nfit nfit;
+
+/*
+ * Memory mapping attributes for the address range described in system
+ * physical address range structure.
+ */
+enum {
+    EFI_MEMORY_UC = 0x1ULL,
+    EFI_MEMORY_WC = 0x2ULL,
+    EFI_MEMORY_WT = 0x4ULL,
+    EFI_MEMORY_WB = 0x8ULL,
+    EFI_MEMORY_UCE = 0x10ULL,
+    EFI_MEMORY_WP = 0x1000ULL,
+    EFI_MEMORY_RP = 0x2000ULL,
+    EFI_MEMORY_XP = 0x4000ULL,
+    EFI_MEMORY_NV = 0x8000ULL,
+    EFI_MEMORY_MORE_RELIABLE = 0x10000ULL,
+};
+
+/*
+ * Control region is strictly for management during hot add/online
+ * operation.
+ */
+#define SPA_FLAGS_ADD_ONLINE_ONLY     (1)
+/* Data in Proximity Domain field is valid. */
+#define SPA_FLAGS_PROXIMITY_VALID     (1 << 1)
+
 /*
  * System Physical Address Range Structure
  *
@@ -76,6 +142,14 @@ struct nfit_memdev {
 typedef struct nfit_memdev nfit_memdev;
 
 /*
+ * please refer to DSM specification, Chapter 2 NVDIMM Device Specific
+ * Method (DSM).
+ */
+#define REVSISON_ID    1
+/* the format interface code supported by DSM specification. */
+#define NFIT_FIC1      0x201
+
+/*
  * NVDIMM Control Region Structure
  *
  * It describes the NVDIMM and if applicable, Block Control Window.
@@ -141,3 +215,215 @@ void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
                        NVDIMM_ACPI_MEM_SIZE);
     memory_region_add_subregion(system_memory, state->base, &state->mr);
 }
+
+/*
+ * Module serial number is a unique number for each device. We use the
+ * slot id of NVDIMM device to generate this number so that each device
+ * associates with a different number.
+ *
+ * 0x123456 is a magic number we arbitrarily chose.
+ */
+static uint32_t nvdimm_slot_to_sn(int slot)
+{
+    return 0x123456 + slot;
+}
+
+/*
+ * handle is used to uniquely associate nfit_memdev structure with NVDIMM
+ * ACPI device - nfit_memdev.nfit_handle matches with the value returned
+ * by ACPI device _ADR method.
+ *
+ * We generate the handle with the slot id of NVDIMM device and reserve
+ * 0 for NVDIMM root device.
+ */
+static uint32_t nvdimm_slot_to_handle(int slot)
+{
+    return slot + 1;
+}
+
+/*
+ * index uniquely identifies the structure, 0 is reserved which indicates
+ * that the structure is not valid or the associated structure is not
+ * present.
+ *
+ * Each NVDIMM device needs two indexes, one for nfit_spa and another for
+ * nfit_dc which are generated by the slot id of NVDIMM device.
+ */
+static uint16_t nvdimm_slot_to_spa_index(int slot)
+{
+    return (slot + 1) << 1;
+}
+
+/* See the comment of nvdimm_slot_to_spa_index(). */
+static uint32_t nvdimm_slot_to_dcr_index(int slot)
+{
+    return nvdimm_slot_to_spa_index(slot) + 1;
+}
+
+/*
+ * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
+ * Structure
+ */
+static void
+nvdimm_build_structure_spa(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_spa *nfit_spa;
+    uint64_t addr = object_property_get_int(OBJECT(nvdimm), DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(nvdimm), DIMM_SIZE_PROP,
+                                            NULL);
+    uint32_t node = object_property_get_int(OBJECT(nvdimm), DIMM_NODE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                            NULL);
+
+    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
+
+    /* System Physical Address Range Structure */
+    nfit_spa->type = cpu_to_le16(NFIT_STRUCTURE_SPA);
+    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
+    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+
+    /*
+     * - Proximity Domain field is valid as NUMA node is valid.
+     * - Control region is strictly during hot add as all the device
+     *   info, such as SN, index, is associated with slot id.
+     */
+    nfit_spa->flags = cpu_to_le16(SPA_FLAGS_PROXIMITY_VALID |
+                                  SPA_FLAGS_ADD_ONLINE_ONLY);
+
+    /* NUMA node. */
+    nfit_spa->proximity_domain = cpu_to_le32(node);
+    /* the region reported as PMEM. */
+    memcpy(nfit_spa->type_guid, nfit_spa_uuid_pm, sizeof(nfit_spa_uuid_pm));
+
+    nfit_spa->spa_base = cpu_to_le64(addr);
+    nfit_spa->spa_length = cpu_to_le64(size);
+
+    /* It is the PMEM and can be cached as writeback. */
+    nfit_spa->mem_attr = cpu_to_le64(EFI_MEMORY_WB | EFI_MEMORY_NV);
+}
+
+/*
+ * Please refer to ACPI 6.0: 5.2.25.2 Memory Device to System Physical
+ * Address Range Mapping Structure
+ */
+static void
+nvdimm_build_structure_memdev(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_memdev *nfit_memdev;
+    uint64_t addr = object_property_get_int(OBJECT(nvdimm), DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(nvdimm), DIMM_SIZE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                            NULL);
+    uint32_t handle = nvdimm_slot_to_handle(slot);
+
+    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
+
+    /* Memory Device to System Address Range Map Structure */
+    nfit_memdev->type = cpu_to_le16(NFIT_STRUCTURE_MEMDEV);
+    nfit_memdev->length = cpu_to_le16(sizeof(*nfit_memdev));
+    nfit_memdev->nfit_handle = cpu_to_le32(handle);
+
+    /*
+     * associate memory device with System Physical Address Range
+     * Structure.
+     */
+    nfit_memdev->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+    /* associate memory device with Control Region Structure. */
+    nfit_memdev->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
+
+    /* The memory region on the device. */
+    nfit_memdev->region_len = cpu_to_le64(size);
+    nfit_memdev->region_dpa = cpu_to_le64(addr);
+
+    /* Only one interleave for PMEM. */
+    nfit_memdev->interleave_ways = cpu_to_le16(1);
+}
+
+/* Please refer to ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure */
+static void nvdimm_build_structure_dcr(GArray *structures, NVDIMMDevice *nvdimm)
+{
+    nfit_dcr *nfit_dcr;
+    int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                       NULL);
+    uint32_t sn = nvdimm_slot_to_sn(slot);
+
+    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
+
+    /* NVDIMM Control Region Structure */
+    nfit_dcr->type = cpu_to_le16(NFIT_STRUCTURE_DCR);
+    nfit_dcr->length = cpu_to_le16(sizeof(*nfit_dcr));
+    nfit_dcr->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
+
+    /* vendor: Intel. */
+    nfit_dcr->vendor_id = cpu_to_le16(0x8086);
+    nfit_dcr->device_id = cpu_to_le16(1);
+
+    /* The _DSM method is following Intel's DSM specification. */
+    nfit_dcr->revision_id = cpu_to_le16(REVSISON_ID);
+    nfit_dcr->serial_number = cpu_to_le32(sn);
+    nfit_dcr->fic = cpu_to_le16(NFIT_FIC1);
+}
+
+static GArray *nvdimm_build_device_structure(GSList *device_list)
+{
+    GArray *structures = g_array_new(false, true /* clear */, 1);
+
+    for (; device_list; device_list = device_list->next) {
+        NVDIMMDevice *nvdimm = device_list->data;
+
+        /* build System Physical Address Range Structure. */
+        nvdimm_build_structure_spa(structures, nvdimm);
+
+        /*
+         * build Memory Device to System Physical Address Range Mapping
+         * Structure.
+         */
+        nvdimm_build_structure_memdev(structures, nvdimm);
+
+        /* build NVDIMM Control Region Structure. */
+        nvdimm_build_structure_dcr(structures, nvdimm);
+    }
+
+    return structures;
+}
+
+static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
+                              GArray *table_data, GArray *linker)
+{
+    GArray *structures = nvdimm_build_device_structure(device_list);
+    void *header;
+
+    acpi_add_table(table_offsets, table_data);
+
+    /* NFIT header. */
+    header = acpi_data_push(table_data, sizeof(nfit));
+
+    /* NVDIMM device structures. */
+    g_array_append_vals(table_data, structures->data, structures->len);
+
+    build_header(linker, table_data, header, "NFIT",
+                 sizeof(nfit) + structures->len, 1);
+    g_array_free(structures, true);
+}
+
+void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
+                       GArray *table_data, GArray *linker)
+{
+    GSList *device_list = nvdimm_get_plugged_device_list();
+
+    if (!memory_region_size(&state->mr)) {
+        assert(!device_list);
+        return;
+    }
+
+    if (!device_list) {
+        return;
+    }
+
+    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    g_slist_free(device_list);
+}
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..7531537 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1658,6 +1658,13 @@ static bool acpi_has_iommu(void)
     return intel_iommu && !ambiguous;
 }
 
+static NVDIMMState *acpi_get_nvdimm_state(void)
+{
+    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+
+    return &pcms->nvdimm_memory;
+}
+
 static
 void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 {
@@ -1742,6 +1749,9 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
         build_dmar_q35(tables_blob, tables->linker);
     }
 
+    nvdimm_build_acpi(acpi_get_nvdimm_state(), table_offsets, tables_blob,
+                      tables->linker);
+
     /* Add tables supplied by user (if any) */
     for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
         unsigned len = acpi_table_len(u);
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 51494b6..2d121f6 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -25,6 +25,30 @@
 #include "qapi/visitor.h"
 #include "hw/mem/nvdimm.h"
 
+static int nvdimm_plugged_device_list(Object *obj, void *opaque)
+{
+    GSList **list = opaque;
+
+    if (object_dynamic_cast(obj, TYPE_NVDIMM)) {
+        NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+        if (memory_region_is_mapped(&nvdimm->nvdimm_mr)) {
+            *list = g_slist_append(*list, DEVICE(obj));
+        }
+    }
+
+    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
+    return 0;
+}
+
+GSList *nvdimm_get_plugged_device_list(void)
+{
+    GSList *list = NULL;
+
+    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list, &list);
+    return list;
+}
+
 static MemoryRegion *nvdimm_get_memory_region(DIMMDevice *dimm)
 {
     NVDIMMDevice *nvdimm = NVDIMM(dimm);
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 8e31983..dc77a1f 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -68,6 +68,15 @@ struct NVDIMMDevice {
 typedef struct NVDIMMDevice NVDIMMDevice;
 
 /*
+ * inquire plugged NVDIMM devices and link them into the list which is
+ * returned to the caller.
+ *
+ * Note: it is the caller's responsibility to free the list to avoid
+ * memory leak.
+ */
+GSList *nvdimm_get_plugged_device_list(void);
+
+/*
  * NVDIMMState:
  * @base: address in guest address space where NVDIMM ACPI memory begins.
  * @mr: NVDIMM ACPI memory address space container.
@@ -81,4 +90,8 @@ typedef struct NVDIMMState NVDIMMState;
 /* Initialize the memory region needed by NVDIMM ACPI.*/
 void nvdimm_init_memory_state(NVDIMMState *state, MemoryRegion *system_memory,
                               MachineState *machine);
+
+/* Build NVDIMM ACPI including NFIT, NVDIMM devices, etc. */
+void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
+                       GArray *table_data, GArray *linker);
 #endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 25/33] nvdimm acpi: init the address region used by DSM
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Map the NVDIMM ACPI memory region to guest address space

Detailed DSM design please refer to docs/specs/acpi_nvdimm.txt

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 87 ++++++++++++++++++++++++++++++++++++++++++++++---
 include/hw/mem/nvdimm.h |  8 +++++
 2 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 8d8376c..bc28828 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -391,10 +391,9 @@ static GArray *nvdimm_build_device_structure(GSList *device_list)
     return structures;
 }
 
-static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
+static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
                               GArray *table_data, GArray *linker)
 {
-    GArray *structures = nvdimm_build_device_structure(device_list);
     void *header;
 
     acpi_add_table(table_offsets, table_data);
@@ -407,12 +406,80 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
 
     build_header(linker, table_data, header, "NFIT",
                  sizeof(nfit) + structures->len, 1);
-    g_array_free(structures, true);
+}
+
+static uint64_t
+nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0;
+}
+
+static void
+nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+}
+
+static const MemoryRegionOps nvdimm_dsm_ops = {
+    .read = nvdimm_dsm_read,
+    .write = nvdimm_dsm_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static MemoryRegion *nvdimm_build_dsm_memory(NVDIMMState *state)
+{
+    MemoryRegion *dsm_ram_mr, *dsm_mmio_mr, *dsm_fit_mr;
+    uint64_t page_size = getpagesize();
+    uint64_t fit_size = memory_region_size(&state->mr) - page_size * 2;
+
+    /* DSM memory has already been built. */
+    dsm_fit_mr = memory_region_find(&state->mr, page_size * 2,
+                                    fit_size).mr;
+    if (dsm_fit_mr) {
+        nvdimm_debug("DSM FIT has already been built by %s.\n",
+                     dsm_fit_mr->name);
+        return dsm_fit_mr;
+    }
+
+    /*
+     * the first page is MMIO-based used to transfer control from guest
+     * ACPI to QEMU.
+     */
+    dsm_mmio_mr = g_new(MemoryRegion, 1);
+    memory_region_init_io(dsm_mmio_mr, NULL, &nvdimm_dsm_ops, state,
+                          "nvdimm.dsm_mmio", page_size);
+
+    /*
+     * the second page is RAM-based used to transfer data between guest
+     * ACPI and QEMU.
+     */
+    dsm_ram_mr = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dsm_ram_mr, NULL, "nvdimm.dsm_ram",
+                           page_size, &error_abort);
+    vmstate_register_ram_global(dsm_ram_mr);
+
+    /*
+     * the left is RAM-based which is _FIT buffer returned by _FIT
+     * method.
+     */
+    dsm_fit_mr = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dsm_fit_mr, NULL, "nvdimm.fit", fit_size,
+                           &error_abort);
+    vmstate_register_ram_global(dsm_fit_mr);
+
+    memory_region_add_subregion(&state->mr, 0, dsm_mmio_mr);
+    memory_region_add_subregion(&state->mr, page_size, dsm_ram_mr);
+    memory_region_add_subregion(&state->mr, page_size * 2, dsm_fit_mr);
+
+    /* the caller will unref it. */
+    memory_region_ref(dsm_fit_mr);
+    return dsm_fit_mr;
 }
 
 void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
                        GArray *table_data, GArray *linker)
 {
+    MemoryRegion *fit_mr;
+    GArray *structures;
     GSList *device_list = nvdimm_get_plugged_device_list();
 
     if (!memory_region_size(&state->mr)) {
@@ -424,6 +491,18 @@ void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
         return;
     }
 
-    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    fit_mr = nvdimm_build_dsm_memory(state);
+
+    structures = nvdimm_build_device_structure(device_list);
+
+    /* Build fit memory which is presented to guest via _FIT method. */
+    assert(memory_region_size(fit_mr) >= structures->len);
+    memcpy(memory_region_get_ram_ptr(fit_mr), structures->data,
+           structures->len);
+
+    nvdimm_build_nfit(structures, table_offsets, table_data, linker);
+
+    memory_region_unref(fit_mr);
     g_slist_free(device_list);
+    g_array_free(structures, true);
 }
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index dc77a1f..c2dc635 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -25,6 +25,14 @@
 
 #include "hw/mem/dimm.h"
 
+#define NVDIMM_DEBUG 0
+#define nvdimm_debug(fmt, ...)                                \
+    do {                                                      \
+        if (NVDIMM_DEBUG) {                                   \
+            fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__);  \
+        }                                                     \
+    } while (0)
+
 /*
  * The minimum label data size is required by NVDIMM Namespace
  * specification, please refer to chapter 2 Namespaces:
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 25/33] nvdimm acpi: init the address region used by DSM
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Map the NVDIMM ACPI memory region to guest address space

Detailed DSM design please refer to docs/specs/acpi_nvdimm.txt

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 87 ++++++++++++++++++++++++++++++++++++++++++++++---
 include/hw/mem/nvdimm.h |  8 +++++
 2 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 8d8376c..bc28828 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -391,10 +391,9 @@ static GArray *nvdimm_build_device_structure(GSList *device_list)
     return structures;
 }
 
-static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
+static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
                               GArray *table_data, GArray *linker)
 {
-    GArray *structures = nvdimm_build_device_structure(device_list);
     void *header;
 
     acpi_add_table(table_offsets, table_data);
@@ -407,12 +406,80 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
 
     build_header(linker, table_data, header, "NFIT",
                  sizeof(nfit) + structures->len, 1);
-    g_array_free(structures, true);
+}
+
+static uint64_t
+nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0;
+}
+
+static void
+nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+}
+
+static const MemoryRegionOps nvdimm_dsm_ops = {
+    .read = nvdimm_dsm_read,
+    .write = nvdimm_dsm_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static MemoryRegion *nvdimm_build_dsm_memory(NVDIMMState *state)
+{
+    MemoryRegion *dsm_ram_mr, *dsm_mmio_mr, *dsm_fit_mr;
+    uint64_t page_size = getpagesize();
+    uint64_t fit_size = memory_region_size(&state->mr) - page_size * 2;
+
+    /* DSM memory has already been built. */
+    dsm_fit_mr = memory_region_find(&state->mr, page_size * 2,
+                                    fit_size).mr;
+    if (dsm_fit_mr) {
+        nvdimm_debug("DSM FIT has already been built by %s.\n",
+                     dsm_fit_mr->name);
+        return dsm_fit_mr;
+    }
+
+    /*
+     * the first page is MMIO-based used to transfer control from guest
+     * ACPI to QEMU.
+     */
+    dsm_mmio_mr = g_new(MemoryRegion, 1);
+    memory_region_init_io(dsm_mmio_mr, NULL, &nvdimm_dsm_ops, state,
+                          "nvdimm.dsm_mmio", page_size);
+
+    /*
+     * the second page is RAM-based used to transfer data between guest
+     * ACPI and QEMU.
+     */
+    dsm_ram_mr = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dsm_ram_mr, NULL, "nvdimm.dsm_ram",
+                           page_size, &error_abort);
+    vmstate_register_ram_global(dsm_ram_mr);
+
+    /*
+     * the left is RAM-based which is _FIT buffer returned by _FIT
+     * method.
+     */
+    dsm_fit_mr = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dsm_fit_mr, NULL, "nvdimm.fit", fit_size,
+                           &error_abort);
+    vmstate_register_ram_global(dsm_fit_mr);
+
+    memory_region_add_subregion(&state->mr, 0, dsm_mmio_mr);
+    memory_region_add_subregion(&state->mr, page_size, dsm_ram_mr);
+    memory_region_add_subregion(&state->mr, page_size * 2, dsm_fit_mr);
+
+    /* the caller will unref it. */
+    memory_region_ref(dsm_fit_mr);
+    return dsm_fit_mr;
 }
 
 void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
                        GArray *table_data, GArray *linker)
 {
+    MemoryRegion *fit_mr;
+    GArray *structures;
     GSList *device_list = nvdimm_get_plugged_device_list();
 
     if (!memory_region_size(&state->mr)) {
@@ -424,6 +491,18 @@ void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
         return;
     }
 
-    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    fit_mr = nvdimm_build_dsm_memory(state);
+
+    structures = nvdimm_build_device_structure(device_list);
+
+    /* Build fit memory which is presented to guest via _FIT method. */
+    assert(memory_region_size(fit_mr) >= structures->len);
+    memcpy(memory_region_get_ram_ptr(fit_mr), structures->data,
+           structures->len);
+
+    nvdimm_build_nfit(structures, table_offsets, table_data, linker);
+
+    memory_region_unref(fit_mr);
     g_slist_free(device_list);
+    g_array_free(structures, true);
 }
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index dc77a1f..c2dc635 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -25,6 +25,14 @@
 
 #include "hw/mem/dimm.h"
 
+#define NVDIMM_DEBUG 0
+#define nvdimm_debug(fmt, ...)                                \
+    do {                                                      \
+        if (NVDIMM_DEBUG) {                                   \
+            fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__);  \
+        }                                                     \
+    } while (0)
+
 /*
  * The minimum label data size is required by NVDIMM Namespace
  * specification, please refer to chapter 2 Namespaces:
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 26/33] nvdimm acpi: build ACPI nvdimm devices
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices

There is a root device under \_SB and specified NVDIMM devices are under the
root device. Each NVDIMM device has _ADR which returns its handle used to
associate MEMDEV structure in NFIT

We reserve handle 0 for root device. In this patch, we save handle, arg0,
arg1 and arg2. Arg3 is conditionally saved in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 216 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index bc28828..7e99889 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -408,15 +408,38 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
                  sizeof(nfit) + structures->len, 1);
 }
 
+/* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
+#define NOTIFY_VALUE      0x99
+
+struct dsm_in {
+    uint32_t handle;
+    uint32_t revision;
+    uint32_t function;
+   /* the remaining size in the page is used by arg3. */
+    uint8_t arg3[0];
+} QEMU_PACKED;
+typedef struct dsm_in dsm_in;
+
+struct dsm_out {
+    /* the size of buffer filled by QEMU. */
+    uint32_t len;
+    uint8_t data[0];
+} QEMU_PACKED;
+typedef struct dsm_out dsm_out;
+
 static uint64_t
 nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 {
+    fprintf(stderr, "BUG: we never read DSM notification MMIO.\n");
     return 0;
 }
 
 static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
+    if (val != NOTIFY_VALUE) {
+        fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
+    }
 }
 
 static const MemoryRegionOps nvdimm_dsm_ops = {
@@ -475,6 +498,196 @@ static MemoryRegion *nvdimm_build_dsm_memory(NVDIMMState *state)
     return dsm_fit_mr;
 }
 
+#define BUILD_STA_METHOD(_dev_, _method_)                                  \
+    do {                                                                   \
+        _method_ = aml_method("_STA", 0);                                  \
+        aml_append(_method_, aml_return(aml_int(0x0f)));                   \
+        aml_append(_dev_, _method_);                                       \
+    } while (0)
+
+#define BUILD_DSM_METHOD(_dev_, _method_, _handle_, _errcode_, _uuid_)     \
+    do {                                                                   \
+        Aml *ifctx, *uuid;                                                 \
+        _method_ = aml_method("_DSM", 4);                                  \
+        /* check UUID if it is we expect, return the errorcode if not.*/   \
+        uuid = aml_touuid(_uuid_);                                         \
+        ifctx = aml_if(aml_lnot(aml_equal(aml_arg(0), uuid)));             \
+        aml_append(ifctx, aml_return(aml_int(_errcode_)));                 \
+        aml_append(method, ifctx);                                         \
+        aml_append(method, aml_return(aml_call4("NCAL", aml_int(_handle_), \
+                   aml_arg(1), aml_arg(2), aml_arg(3))));                  \
+        aml_append(_dev_, _method_);                                       \
+    } while (0)
+
+#define BUILD_FIELD_UNIT_STRUCT(_field_, _s_, _f_, _name_)                 \
+    aml_append(_field_, aml_named_field(_name_,                            \
+               sizeof(typeof_field(_s_, _f_)) * BITS_PER_BYTE))
+
+#define BUILD_FIELD_UNIT_SIZE(_field_, _byte_, _name_)                     \
+    aml_append(_field_, aml_named_field(_name_, (_byte_) * BITS_PER_BYTE))
+
+static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
+                                 Aml *root_dev)
+{
+    for (; device_list; device_list = device_list->next) {
+        NVDIMMDevice *nvdimm = device_list->data;
+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                           NULL);
+        uint32_t handle = nvdimm_slot_to_handle(slot);
+        Aml *dev, *method;
+
+        dev = aml_device("NV%02X", slot);
+        aml_append(dev, aml_name_decl("_ADR", aml_int(handle)));
+
+        BUILD_STA_METHOD(dev, method);
+
+        /*
+         * Please refer to DSM specification Chapter 4 _DSM Interface
+         * for NVDIMM Device (non-root) - Example
+         */
+        BUILD_DSM_METHOD(dev, method,
+                         handle /* NVDIMM Device Handle */,
+                         3 /* Invalid Input Parameters */,
+                         "4309AC30-0D11-11E4-9191-0800200C9A66"
+                         /* UUID for NVDIMM Devices. */);
+
+        aml_append(root_dev, dev);
+    }
+}
+
+static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
+                                      Aml *sb_scope)
+{
+    Aml *dev, *method, *field;
+    uint64_t page_size = getpagesize();
+    int fit_size = nvdimm_device_structure_size(g_slist_length(device_list));
+
+    dev = aml_device("NVDR");
+    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
+
+    /* map DSM memory into ACPI namespace. */
+    aml_append(dev, aml_operation_region("NMIO", AML_SYSTEM_MEMORY,
+               state->base, page_size));
+    aml_append(dev, aml_operation_region("NRAM", AML_SYSTEM_MEMORY,
+               state->base + page_size, page_size));
+    aml_append(dev, aml_operation_region("NFIT", AML_SYSTEM_MEMORY,
+               state->base + page_size * 2,
+               memory_region_size(&state->mr) - page_size * 2));
+
+    /*
+     * DSM notifier:
+     * @NOTI: write value to it will notify QEMU that _DSM method is being
+     *        called and the parameters can be found in dsm_in.
+     *
+     * It is MMIO mapping on host so that it will cause VM-exit then QEMU
+     * gets control.
+     */
+    field = aml_field("NMIO", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_SIZE(field, sizeof(uint32_t), "NOTI");
+    aml_append(dev, field);
+
+    /*
+     * DSM input:
+     * @HDLE: store device's handle, it's zero if the _DSM call happens
+     *        on ROOT.
+     * @ARG0 ~ @ARG3: store the parameters of _DSM call.
+     *
+     * They are ram mapping on host so that these accesses never cause
+     * VM-EXIT.
+     */
+    field = aml_field("NRAM", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, handle, "HDLE");
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, revision, "REVS");
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, function, "FUNC");
+    BUILD_FIELD_UNIT_SIZE(field, page_size - offsetof(dsm_in, arg3),
+                          "ARG3");
+    aml_append(dev, field);
+
+    /*
+     * DSM output:
+     * @RLEN: the size of buffer filled by QEMU
+     * @ODAT: the buffer QEMU uses to store the result
+     *
+     * Since the page is reused by both input and out, the input data
+     * will be lost after storing new result into @RLEN and @ODAT
+    */
+    field = aml_field("NRAM", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_out, len, "RLEN");
+    BUILD_FIELD_UNIT_SIZE(field, page_size - offsetof(dsm_out, data),
+                          "ODAT");
+    aml_append(dev, field);
+
+    /* @RFIT, returned by _FIT method. */
+    field = aml_field("NFIT", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_SIZE(field, fit_size, "RFIT");
+    aml_append(dev, field);
+
+    method = aml_method_serialized("NCAL", 4);
+    {
+        aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
+        aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
+        aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
+
+        aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
+
+        aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
+        aml_append(method, aml_store(aml_shiftleft(aml_local(6),
+                                       aml_int(3)), aml_local(6)));
+        aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
+                                            aml_local(6) , "OBUF"));
+        aml_append(method, aml_name_decl("ZBUF", aml_buffer(0, NULL)));
+        aml_append(method, aml_concatenate(aml_name("ZBUF"),
+                                           aml_name("OBUF"), aml_arg(6)));
+        aml_append(method, aml_return(aml_arg(6)));
+    }
+    aml_append(dev, method);
+
+    BUILD_STA_METHOD(dev, method);
+
+    /*
+     * please refer to DSM specification Chapter 3 _DSM Interface for
+     * NVDIMM Root Device - Example
+     */
+    BUILD_DSM_METHOD(dev, method,
+                     0 /* 0 is reserved for NVDIMM Root Device*/,
+                     2 /* Invalid Input Parameters */,
+                     "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
+                     /* UUID for NVDIMM Root Devices. */);
+
+    method = aml_method("_FIT", 0);
+    {
+        aml_append(method, aml_return(aml_name("RFIT")));
+    }
+    aml_append(dev, method);
+
+    build_nvdimm_devices(state, device_list, dev);
+
+    aml_append(sb_scope, dev);
+}
+
+static void nvdimm_build_ssdt(NVDIMMState *state, GSList *device_list,
+                              GArray *table_offsets, GArray *table_data,
+                              GArray *linker)
+{
+    Aml *ssdt, *sb_scope;
+
+    acpi_add_table(table_offsets, table_data);
+
+    ssdt = init_aml_allocator();
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    sb_scope = aml_scope("\\_SB");
+    nvdimm_build_acpi_devices(state, device_list, sb_scope);
+
+    aml_append(ssdt, sb_scope);
+    /* copy AML table into ACPI tables blob and patch header there */
+    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
+    build_header(linker, table_data,
+        (void *)(table_data->data + table_data->len - ssdt->buf->len),
+        "SSDT", ssdt->buf->len, 1);
+    free_aml_allocator();
+}
+
 void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
                        GArray *table_data, GArray *linker)
 {
@@ -502,6 +715,9 @@ void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
 
     nvdimm_build_nfit(structures, table_offsets, table_data, linker);
 
+    nvdimm_build_ssdt(state, device_list, table_offsets, table_data,
+                      linker);
+
     memory_region_unref(fit_mr);
     g_slist_free(device_list);
     g_array_free(structures, true);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 26/33] nvdimm acpi: build ACPI nvdimm devices
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices

There is a root device under \_SB and specified NVDIMM devices are under the
root device. Each NVDIMM device has _ADR which returns its handle used to
associate MEMDEV structure in NFIT

We reserve handle 0 for root device. In this patch, we save handle, arg0,
arg1 and arg2. Arg3 is conditionally saved in later patch

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 216 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index bc28828..7e99889 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -408,15 +408,38 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
                  sizeof(nfit) + structures->len, 1);
 }
 
+/* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
+#define NOTIFY_VALUE      0x99
+
+struct dsm_in {
+    uint32_t handle;
+    uint32_t revision;
+    uint32_t function;
+   /* the remaining size in the page is used by arg3. */
+    uint8_t arg3[0];
+} QEMU_PACKED;
+typedef struct dsm_in dsm_in;
+
+struct dsm_out {
+    /* the size of buffer filled by QEMU. */
+    uint32_t len;
+    uint8_t data[0];
+} QEMU_PACKED;
+typedef struct dsm_out dsm_out;
+
 static uint64_t
 nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 {
+    fprintf(stderr, "BUG: we never read DSM notification MMIO.\n");
     return 0;
 }
 
 static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
+    if (val != NOTIFY_VALUE) {
+        fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
+    }
 }
 
 static const MemoryRegionOps nvdimm_dsm_ops = {
@@ -475,6 +498,196 @@ static MemoryRegion *nvdimm_build_dsm_memory(NVDIMMState *state)
     return dsm_fit_mr;
 }
 
+#define BUILD_STA_METHOD(_dev_, _method_)                                  \
+    do {                                                                   \
+        _method_ = aml_method("_STA", 0);                                  \
+        aml_append(_method_, aml_return(aml_int(0x0f)));                   \
+        aml_append(_dev_, _method_);                                       \
+    } while (0)
+
+#define BUILD_DSM_METHOD(_dev_, _method_, _handle_, _errcode_, _uuid_)     \
+    do {                                                                   \
+        Aml *ifctx, *uuid;                                                 \
+        _method_ = aml_method("_DSM", 4);                                  \
+        /* check UUID if it is we expect, return the errorcode if not.*/   \
+        uuid = aml_touuid(_uuid_);                                         \
+        ifctx = aml_if(aml_lnot(aml_equal(aml_arg(0), uuid)));             \
+        aml_append(ifctx, aml_return(aml_int(_errcode_)));                 \
+        aml_append(method, ifctx);                                         \
+        aml_append(method, aml_return(aml_call4("NCAL", aml_int(_handle_), \
+                   aml_arg(1), aml_arg(2), aml_arg(3))));                  \
+        aml_append(_dev_, _method_);                                       \
+    } while (0)
+
+#define BUILD_FIELD_UNIT_STRUCT(_field_, _s_, _f_, _name_)                 \
+    aml_append(_field_, aml_named_field(_name_,                            \
+               sizeof(typeof_field(_s_, _f_)) * BITS_PER_BYTE))
+
+#define BUILD_FIELD_UNIT_SIZE(_field_, _byte_, _name_)                     \
+    aml_append(_field_, aml_named_field(_name_, (_byte_) * BITS_PER_BYTE))
+
+static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
+                                 Aml *root_dev)
+{
+    for (; device_list; device_list = device_list->next) {
+        NVDIMMDevice *nvdimm = device_list->data;
+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                           NULL);
+        uint32_t handle = nvdimm_slot_to_handle(slot);
+        Aml *dev, *method;
+
+        dev = aml_device("NV%02X", slot);
+        aml_append(dev, aml_name_decl("_ADR", aml_int(handle)));
+
+        BUILD_STA_METHOD(dev, method);
+
+        /*
+         * Please refer to DSM specification Chapter 4 _DSM Interface
+         * for NVDIMM Device (non-root) - Example
+         */
+        BUILD_DSM_METHOD(dev, method,
+                         handle /* NVDIMM Device Handle */,
+                         3 /* Invalid Input Parameters */,
+                         "4309AC30-0D11-11E4-9191-0800200C9A66"
+                         /* UUID for NVDIMM Devices. */);
+
+        aml_append(root_dev, dev);
+    }
+}
+
+static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
+                                      Aml *sb_scope)
+{
+    Aml *dev, *method, *field;
+    uint64_t page_size = getpagesize();
+    int fit_size = nvdimm_device_structure_size(g_slist_length(device_list));
+
+    dev = aml_device("NVDR");
+    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
+
+    /* map DSM memory into ACPI namespace. */
+    aml_append(dev, aml_operation_region("NMIO", AML_SYSTEM_MEMORY,
+               state->base, page_size));
+    aml_append(dev, aml_operation_region("NRAM", AML_SYSTEM_MEMORY,
+               state->base + page_size, page_size));
+    aml_append(dev, aml_operation_region("NFIT", AML_SYSTEM_MEMORY,
+               state->base + page_size * 2,
+               memory_region_size(&state->mr) - page_size * 2));
+
+    /*
+     * DSM notifier:
+     * @NOTI: write value to it will notify QEMU that _DSM method is being
+     *        called and the parameters can be found in dsm_in.
+     *
+     * It is MMIO mapping on host so that it will cause VM-exit then QEMU
+     * gets control.
+     */
+    field = aml_field("NMIO", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_SIZE(field, sizeof(uint32_t), "NOTI");
+    aml_append(dev, field);
+
+    /*
+     * DSM input:
+     * @HDLE: store device's handle, it's zero if the _DSM call happens
+     *        on ROOT.
+     * @ARG0 ~ @ARG3: store the parameters of _DSM call.
+     *
+     * They are ram mapping on host so that these accesses never cause
+     * VM-EXIT.
+     */
+    field = aml_field("NRAM", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, handle, "HDLE");
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, revision, "REVS");
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_in, function, "FUNC");
+    BUILD_FIELD_UNIT_SIZE(field, page_size - offsetof(dsm_in, arg3),
+                          "ARG3");
+    aml_append(dev, field);
+
+    /*
+     * DSM output:
+     * @RLEN: the size of buffer filled by QEMU
+     * @ODAT: the buffer QEMU uses to store the result
+     *
+     * Since the page is reused by both input and out, the input data
+     * will be lost after storing new result into @RLEN and @ODAT
+    */
+    field = aml_field("NRAM", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_STRUCT(field, dsm_out, len, "RLEN");
+    BUILD_FIELD_UNIT_SIZE(field, page_size - offsetof(dsm_out, data),
+                          "ODAT");
+    aml_append(dev, field);
+
+    /* @RFIT, returned by _FIT method. */
+    field = aml_field("NFIT", AML_DWORD_ACC, AML_PRESERVE);
+    BUILD_FIELD_UNIT_SIZE(field, fit_size, "RFIT");
+    aml_append(dev, field);
+
+    method = aml_method_serialized("NCAL", 4);
+    {
+        aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
+        aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
+        aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
+
+        aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
+
+        aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
+        aml_append(method, aml_store(aml_shiftleft(aml_local(6),
+                                       aml_int(3)), aml_local(6)));
+        aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
+                                            aml_local(6) , "OBUF"));
+        aml_append(method, aml_name_decl("ZBUF", aml_buffer(0, NULL)));
+        aml_append(method, aml_concatenate(aml_name("ZBUF"),
+                                           aml_name("OBUF"), aml_arg(6)));
+        aml_append(method, aml_return(aml_arg(6)));
+    }
+    aml_append(dev, method);
+
+    BUILD_STA_METHOD(dev, method);
+
+    /*
+     * please refer to DSM specification Chapter 3 _DSM Interface for
+     * NVDIMM Root Device - Example
+     */
+    BUILD_DSM_METHOD(dev, method,
+                     0 /* 0 is reserved for NVDIMM Root Device*/,
+                     2 /* Invalid Input Parameters */,
+                     "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
+                     /* UUID for NVDIMM Root Devices. */);
+
+    method = aml_method("_FIT", 0);
+    {
+        aml_append(method, aml_return(aml_name("RFIT")));
+    }
+    aml_append(dev, method);
+
+    build_nvdimm_devices(state, device_list, dev);
+
+    aml_append(sb_scope, dev);
+}
+
+static void nvdimm_build_ssdt(NVDIMMState *state, GSList *device_list,
+                              GArray *table_offsets, GArray *table_data,
+                              GArray *linker)
+{
+    Aml *ssdt, *sb_scope;
+
+    acpi_add_table(table_offsets, table_data);
+
+    ssdt = init_aml_allocator();
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    sb_scope = aml_scope("\\_SB");
+    nvdimm_build_acpi_devices(state, device_list, sb_scope);
+
+    aml_append(ssdt, sb_scope);
+    /* copy AML table into ACPI tables blob and patch header there */
+    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
+    build_header(linker, table_data,
+        (void *)(table_data->data + table_data->len - ssdt->buf->len),
+        "SSDT", ssdt->buf->len, 1);
+    free_aml_allocator();
+}
+
 void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
                        GArray *table_data, GArray *linker)
 {
@@ -502,6 +715,9 @@ void nvdimm_build_acpi(NVDIMMState *state, GArray *table_offsets,
 
     nvdimm_build_nfit(structures, table_offsets, table_data, linker);
 
+    nvdimm_build_ssdt(state, device_list, table_offsets, table_data,
+                      linker);
+
     memory_region_unref(fit_mr);
     g_slist_free(device_list);
     g_array_free(structures, true);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Check if the input Arg3 is valid then store it into dsm_in if needed

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 7e99889..b211b8b 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
 
     method = aml_method_serialized("NCAL", 4);
     {
+        Aml *ifctx;
+
         aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
         aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
         aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
 
+        /* Arg3 is passed as Package and it has one element? */
+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
+                                         aml_int(4)),
+                               aml_equal(aml_sizeof(aml_arg(3)),
+                                         aml_int(1))));
+        {
+            /* Local0 = Index(Arg3, 0) */
+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
+                                        aml_local(0)));
+            /* Local3 = DeRefOf(Local0) */
+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
+                                        aml_local(3)));
+            /* ARG3 = Local3 */
+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
+        }
+        aml_append(method, ifctx);
+
         aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
 
         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Check if the input Arg3 is valid then store it into dsm_in if needed

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 7e99889..b211b8b 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
 
     method = aml_method_serialized("NCAL", 4);
     {
+        Aml *ifctx;
+
         aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
         aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
         aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
 
+        /* Arg3 is passed as Package and it has one element? */
+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
+                                         aml_int(4)),
+                               aml_equal(aml_sizeof(aml_arg(3)),
+                                         aml_int(1))));
+        {
+            /* Local0 = Index(Arg3, 0) */
+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
+                                        aml_local(0)));
+            /* Local3 = DeRefOf(Local0) */
+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
+                                        aml_local(3)));
+            /* ARG3 = Local3 */
+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
+        }
+        aml_append(method, ifctx);
+
         aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
 
         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

__DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)

Function 0 is a query function. We do not support any function on root
device and only 3 functions are support for NVDIMM device,
DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
access device's Label Namespace

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index b211b8b..37fea1c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
     return nvdimm_slot_to_spa_index(slot) + 1;
 }
 
+static NVDIMMDevice
+*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
+{
+    for (; list; list = list->next) {
+        NVDIMMDevice *nvdimm = list->data;
+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                           NULL);
+
+        if (nvdimm_slot_to_handle(slot) == handle) {
+            return nvdimm;
+        }
+    }
+
+    return NULL;
+}
+
 /*
  * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
  * Structure
@@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
 /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
 #define NOTIFY_VALUE      0x99
 
+enum {
+    DSM_FUN_IMPLEMENTED = 0,
+
+    /* NVDIMM Root Device Functions */
+    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
+    DSM_ROOT_DEV_FUN_ARS_START = 2,
+    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
+
+    /* NVDIMM Device (non-root) Functions */
+    DSM_DEV_FUN_SMART = 1,
+    DSM_DEV_FUN_SMART_THRESHOLD = 2,
+    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
+    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
+    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
+    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
+    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
+    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
+    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
+};
+
+enum {
+    /* Common return status codes. */
+    DSM_STATUS_SUCCESS = 0,                   /* Success */
+    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
+
+    /* NVDIMM Root Device _DSM function return status codes*/
+    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
+    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
+                                                        Error */
+
+    /* NVDIMM Device (non-root) _DSM function return status codes*/
+    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
+    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
+    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
+};
+
+/* Current revision supported by DSM specification is 1. */
+#define DSM_REVISION        (1)
+
+/*
+ * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
+ * Value Information:
+ *   if set to zero, no functions are supported (other than function zero)
+ *   for the specified UUID and Revision ID. If set to one, at least one
+ *   additional function is supported.
+ */
+
+/* do not support any function on root. */
+#define ROOT_SUPPORT_FUN     (0ULL)
+#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
+                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
+                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
+                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
+
 struct dsm_in {
     uint32_t handle;
     uint32_t revision;
@@ -420,6 +490,11 @@ struct dsm_in {
 } QEMU_PACKED;
 typedef struct dsm_in dsm_in;
 
+struct cmd_out_implemented {
+    uint64_t cmd_list;
+};
+typedef struct cmd_out_implemented cmd_out_implemented;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
@@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
     return 0;
 }
 
+static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
+{
+    /* status locates in the first 4 bytes in the dsm memory. */
+    assert(!out->len);
+
+    status = cpu_to_le32(status);
+    g_array_append_vals(out, &status, sizeof(status));
+}
+
+static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
+{
+    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
+
+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
+    if (in->function == DSM_FUN_IMPLEMENTED) {
+        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
+
+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
+        return;
+    }
+
+    nvdimm_debug("Return status %#x.\n", status);
+    nvdimm_dsm_write_status(out, status);
+}
+
+static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
+{
+    GSList *list = nvdimm_get_plugged_device_list();
+    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
+    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
+    uint64_t cmd_list;
+
+    if (!nvdimm) {
+        goto set_status_free;
+    }
+
+    switch (in->function) {
+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
+    case DSM_FUN_IMPLEMENTED:
+        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
+        goto free;
+    default:
+        status = DSM_STATUS_NOT_SUPPORTED;
+    };
+
+set_status_free:
+    nvdimm_debug("Return status %#x.\n", status);
+    nvdimm_dsm_write_status(out, status);
+free:
+    g_slist_free(list);
+}
+
 static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
+    NVDIMMState *state = opaque;
+    MemoryRegion *dsm_ram_mr;
+    dsm_in *in;
+    GArray *out;
+    void *dsm_ram_addr;
+
     if (val != NOTIFY_VALUE) {
         fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
     }
+
+    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
+                                    getpagesize()).mr;
+    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
+
+    /*
+     * copy all input data to our local memory to avoid potential issue
+     * as the dsm memory is visible to guest.
+     */
+    in = g_malloc(memory_region_size(dsm_ram_mr));
+    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
+
+    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);
+
+    if (in->revision != DSM_REVISION) {
+        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
+                      in->revision, DSM_REVISION);
+        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
+        goto exit;
+    }
+
+    /* Handle 0 is reserved for NVDIMM Root Device. */
+    if (!in->handle) {
+        nvdimm_dsm_write_root(in, out);
+        goto exit;
+    }
+
+    nvdimm_dsm_write_nvdimm(in, out);
+
+exit:
+    /* Write our output result to dsm memory. */
+    ((dsm_out *)dsm_ram_addr)->len = out->len;
+    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
+
+    g_free(in);
+    g_array_free(out, true);
+    memory_region_unref(dsm_ram_mr);
 }
 
 static const MemoryRegionOps nvdimm_dsm_ops = {
@@ -547,7 +725,8 @@ static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
          */
         BUILD_DSM_METHOD(dev, method,
                          handle /* NVDIMM Device Handle */,
-                         3 /* Invalid Input Parameters */,
+                         DSM_DEV_STATUS_INVALID_PARAS, /* error code if UUID
+                                                         is not matched. */
                          "4309AC30-0D11-11E4-9191-0800200C9A66"
                          /* UUID for NVDIMM Devices. */);
 
@@ -669,7 +848,8 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
      */
     BUILD_DSM_METHOD(dev, method,
                      0 /* 0 is reserved for NVDIMM Root Device*/,
-                     2 /* Invalid Input Parameters */,
+                     DSM_ROOT_DEV_STATUS_INVALID_PARAS, /* error code if
+                                                     UUID is not matched. */
                      "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
                      /* UUID for NVDIMM Root Devices. */);
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

__DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)

Function 0 is a query function. We do not support any function on root
device and only 3 functions are support for NVDIMM device,
DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
access device's Label Namespace

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index b211b8b..37fea1c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
     return nvdimm_slot_to_spa_index(slot) + 1;
 }
 
+static NVDIMMDevice
+*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
+{
+    for (; list; list = list->next) {
+        NVDIMMDevice *nvdimm = list->data;
+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
+                                           NULL);
+
+        if (nvdimm_slot_to_handle(slot) == handle) {
+            return nvdimm;
+        }
+    }
+
+    return NULL;
+}
+
 /*
  * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
  * Structure
@@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
 /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
 #define NOTIFY_VALUE      0x99
 
+enum {
+    DSM_FUN_IMPLEMENTED = 0,
+
+    /* NVDIMM Root Device Functions */
+    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
+    DSM_ROOT_DEV_FUN_ARS_START = 2,
+    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
+
+    /* NVDIMM Device (non-root) Functions */
+    DSM_DEV_FUN_SMART = 1,
+    DSM_DEV_FUN_SMART_THRESHOLD = 2,
+    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
+    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
+    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
+    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
+    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
+    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
+    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
+};
+
+enum {
+    /* Common return status codes. */
+    DSM_STATUS_SUCCESS = 0,                   /* Success */
+    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
+
+    /* NVDIMM Root Device _DSM function return status codes*/
+    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
+    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
+                                                        Error */
+
+    /* NVDIMM Device (non-root) _DSM function return status codes*/
+    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
+    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
+    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
+};
+
+/* Current revision supported by DSM specification is 1. */
+#define DSM_REVISION        (1)
+
+/*
+ * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
+ * Value Information:
+ *   if set to zero, no functions are supported (other than function zero)
+ *   for the specified UUID and Revision ID. If set to one, at least one
+ *   additional function is supported.
+ */
+
+/* do not support any function on root. */
+#define ROOT_SUPPORT_FUN     (0ULL)
+#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
+                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
+                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
+                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
+
 struct dsm_in {
     uint32_t handle;
     uint32_t revision;
@@ -420,6 +490,11 @@ struct dsm_in {
 } QEMU_PACKED;
 typedef struct dsm_in dsm_in;
 
+struct cmd_out_implemented {
+    uint64_t cmd_list;
+};
+typedef struct cmd_out_implemented cmd_out_implemented;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
@@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
     return 0;
 }
 
+static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
+{
+    /* status locates in the first 4 bytes in the dsm memory. */
+    assert(!out->len);
+
+    status = cpu_to_le32(status);
+    g_array_append_vals(out, &status, sizeof(status));
+}
+
+static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
+{
+    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
+
+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
+    if (in->function == DSM_FUN_IMPLEMENTED) {
+        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
+
+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
+        return;
+    }
+
+    nvdimm_debug("Return status %#x.\n", status);
+    nvdimm_dsm_write_status(out, status);
+}
+
+static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
+{
+    GSList *list = nvdimm_get_plugged_device_list();
+    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
+    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
+    uint64_t cmd_list;
+
+    if (!nvdimm) {
+        goto set_status_free;
+    }
+
+    switch (in->function) {
+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
+    case DSM_FUN_IMPLEMENTED:
+        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
+        goto free;
+    default:
+        status = DSM_STATUS_NOT_SUPPORTED;
+    };
+
+set_status_free:
+    nvdimm_debug("Return status %#x.\n", status);
+    nvdimm_dsm_write_status(out, status);
+free:
+    g_slist_free(list);
+}
+
 static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
+    NVDIMMState *state = opaque;
+    MemoryRegion *dsm_ram_mr;
+    dsm_in *in;
+    GArray *out;
+    void *dsm_ram_addr;
+
     if (val != NOTIFY_VALUE) {
         fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
     }
+
+    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
+                                    getpagesize()).mr;
+    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
+
+    /*
+     * copy all input data to our local memory to avoid potential issue
+     * as the dsm memory is visible to guest.
+     */
+    in = g_malloc(memory_region_size(dsm_ram_mr));
+    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
+
+    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);
+
+    if (in->revision != DSM_REVISION) {
+        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
+                      in->revision, DSM_REVISION);
+        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
+        goto exit;
+    }
+
+    /* Handle 0 is reserved for NVDIMM Root Device. */
+    if (!in->handle) {
+        nvdimm_dsm_write_root(in, out);
+        goto exit;
+    }
+
+    nvdimm_dsm_write_nvdimm(in, out);
+
+exit:
+    /* Write our output result to dsm memory. */
+    ((dsm_out *)dsm_ram_addr)->len = out->len;
+    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
+
+    g_free(in);
+    g_array_free(out, true);
+    memory_region_unref(dsm_ram_mr);
 }
 
 static const MemoryRegionOps nvdimm_dsm_ops = {
@@ -547,7 +725,8 @@ static void build_nvdimm_devices(NVDIMMState *state, GSList *device_list,
          */
         BUILD_DSM_METHOD(dev, method,
                          handle /* NVDIMM Device Handle */,
-                         3 /* Invalid Input Parameters */,
+                         DSM_DEV_STATUS_INVALID_PARAS, /* error code if UUID
+                                                         is not matched. */
                          "4309AC30-0D11-11E4-9191-0800200C9A66"
                          /* UUID for NVDIMM Devices. */);
 
@@ -669,7 +848,8 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
      */
     BUILD_DSM_METHOD(dev, method,
                      0 /* 0 is reserved for NVDIMM Root Device*/,
-                     2 /* Invalid Input Parameters */,
+                     DSM_ROOT_DEV_STATUS_INVALID_PARAS, /* error code if
+                                                     UUID is not matched. */
                      "2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
                      /* UUID for NVDIMM Root Devices. */);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 29/33] nvdimm acpi: support DSM_DEV_FUN_NAMESPACE_LABEL_SIZE function
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Function 4 is used to get Namespace label size

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 37fea1c..1274d95 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -481,12 +481,28 @@ enum {
                            | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
                            | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
 
+struct cmd_in_get_label_data {
+    uint32_t offset; /* the offset in the namespace label data area. */
+    uint32_t length; /* the size of data is to be read via the function. */
+} QEMU_PACKED;
+typedef struct cmd_in_get_label_data cmd_in_get_label_data;
+
+struct cmd_in_set_label_data {
+    uint32_t offset; /* the offset in the namespace label data area. */
+    uint32_t length; /* the size of data is to be written via the function. */
+    uint8_t in_buf[0]; /* the data written to label data area. */
+} QEMU_PACKED;
+typedef struct cmd_in_set_label_data cmd_in_set_label_data;
+
 struct dsm_in {
     uint32_t handle;
     uint32_t revision;
     uint32_t function;
    /* the remaining size in the page is used by arg3. */
-    uint8_t arg3[0];
+    union {
+        uint8_t arg3[0];
+        cmd_in_set_label_data cmd_set_label_data;
+    };
 } QEMU_PACKED;
 typedef struct dsm_in dsm_in;
 
@@ -495,10 +511,32 @@ struct cmd_out_implemented {
 };
 typedef struct cmd_out_implemented cmd_out_implemented;
 
+struct cmd_out_label_size {
+    uint32_t status;     /* return status code. */
+    uint32_t label_size; /* the size of label data area. */
+    /*
+     * Maximum size of the namespace label data length supported by
+     * the platform in Get/Set Namespace Label Data functions.
+     */
+    uint32_t max_xfer;
+} QEMU_PACKED;
+typedef struct cmd_out_label_size cmd_out_label_size;
+
+struct cmd_out_get_label_data {
+    uint32_t status;    /*return status code. */
+    uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */
+} QEMU_PACKED;
+typedef struct cmd_out_get_label_data cmd_out_get_label_data;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
-    uint8_t data[0];
+    union {
+        uint8_t data[0];
+        cmd_out_implemented cmd_implemented;
+        cmd_out_label_size cmd_label_size;
+        cmd_out_get_label_data cmd_get_label_data;
+    };
 } QEMU_PACKED;
 typedef struct dsm_out dsm_out;
 
@@ -534,6 +572,58 @@ static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
     nvdimm_dsm_write_status(out, status);
 }
 
+/*
+ * the max transfer size is the max size transferred by both a
+ * DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and a
+ * DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA command.
+ */
+static uint32_t nvdimm_get_max_xfer_label_size(void)
+{
+    dsm_in *in;
+    dsm_out *out;
+    uint32_t max_get_size, max_set_size, dsm_memory_size = getpagesize();
+
+    /*
+     * the max data ACPI can read one time which is transferred by
+     * the response of DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA.
+     */
+    max_get_size = dsm_memory_size - offsetof(dsm_out, data) -
+                   sizeof(out->cmd_get_label_data);
+
+    /*
+     * the max data ACPI can write one time which is transferred by
+     * DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
+     */
+    max_set_size = dsm_memory_size - offsetof(dsm_in, arg3) -
+                   sizeof(in->cmd_set_label_data);
+
+    return MIN(max_get_size, max_set_size);
+}
+
+/*
+ * Please refer to DSM specification 4.4.1 Get Namespace Label Size
+ * (Function Index 4).
+ *
+ * It gets the size of Namespace Label data area and the max data size
+ * that Get/Set Namespace Label Data functions can transfer.
+ */
+static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
+{
+    cmd_out_label_size cmd_label_size;
+    uint32_t label_size, mxfer;
+
+    label_size = nvdimm->label_size;
+    mxfer = nvdimm_get_max_xfer_label_size();
+
+    nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer);
+
+    cmd_label_size.status = cpu_to_le32(DSM_STATUS_SUCCESS);
+    cmd_label_size.label_size = cpu_to_le32(label_size);
+    cmd_label_size.max_xfer = cpu_to_le32(mxfer);
+
+    g_array_append_vals(out, &cmd_label_size, sizeof(cmd_label_size));
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -551,6 +641,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
         cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
         g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
         goto free;
+    case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
+        nvdimm_dsm_func_label_size(nvdimm, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 29/33] nvdimm acpi: support DSM_DEV_FUN_NAMESPACE_LABEL_SIZE function
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Function 4 is used to get Namespace label size

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 37fea1c..1274d95 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -481,12 +481,28 @@ enum {
                            | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
                            | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
 
+struct cmd_in_get_label_data {
+    uint32_t offset; /* the offset in the namespace label data area. */
+    uint32_t length; /* the size of data is to be read via the function. */
+} QEMU_PACKED;
+typedef struct cmd_in_get_label_data cmd_in_get_label_data;
+
+struct cmd_in_set_label_data {
+    uint32_t offset; /* the offset in the namespace label data area. */
+    uint32_t length; /* the size of data is to be written via the function. */
+    uint8_t in_buf[0]; /* the data written to label data area. */
+} QEMU_PACKED;
+typedef struct cmd_in_set_label_data cmd_in_set_label_data;
+
 struct dsm_in {
     uint32_t handle;
     uint32_t revision;
     uint32_t function;
    /* the remaining size in the page is used by arg3. */
-    uint8_t arg3[0];
+    union {
+        uint8_t arg3[0];
+        cmd_in_set_label_data cmd_set_label_data;
+    };
 } QEMU_PACKED;
 typedef struct dsm_in dsm_in;
 
@@ -495,10 +511,32 @@ struct cmd_out_implemented {
 };
 typedef struct cmd_out_implemented cmd_out_implemented;
 
+struct cmd_out_label_size {
+    uint32_t status;     /* return status code. */
+    uint32_t label_size; /* the size of label data area. */
+    /*
+     * Maximum size of the namespace label data length supported by
+     * the platform in Get/Set Namespace Label Data functions.
+     */
+    uint32_t max_xfer;
+} QEMU_PACKED;
+typedef struct cmd_out_label_size cmd_out_label_size;
+
+struct cmd_out_get_label_data {
+    uint32_t status;    /*return status code. */
+    uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */
+} QEMU_PACKED;
+typedef struct cmd_out_get_label_data cmd_out_get_label_data;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
-    uint8_t data[0];
+    union {
+        uint8_t data[0];
+        cmd_out_implemented cmd_implemented;
+        cmd_out_label_size cmd_label_size;
+        cmd_out_get_label_data cmd_get_label_data;
+    };
 } QEMU_PACKED;
 typedef struct dsm_out dsm_out;
 
@@ -534,6 +572,58 @@ static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
     nvdimm_dsm_write_status(out, status);
 }
 
+/*
+ * the max transfer size is the max size transferred by both a
+ * DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and a
+ * DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA command.
+ */
+static uint32_t nvdimm_get_max_xfer_label_size(void)
+{
+    dsm_in *in;
+    dsm_out *out;
+    uint32_t max_get_size, max_set_size, dsm_memory_size = getpagesize();
+
+    /*
+     * the max data ACPI can read one time which is transferred by
+     * the response of DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA.
+     */
+    max_get_size = dsm_memory_size - offsetof(dsm_out, data) -
+                   sizeof(out->cmd_get_label_data);
+
+    /*
+     * the max data ACPI can write one time which is transferred by
+     * DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
+     */
+    max_set_size = dsm_memory_size - offsetof(dsm_in, arg3) -
+                   sizeof(in->cmd_set_label_data);
+
+    return MIN(max_get_size, max_set_size);
+}
+
+/*
+ * Please refer to DSM specification 4.4.1 Get Namespace Label Size
+ * (Function Index 4).
+ *
+ * It gets the size of Namespace Label data area and the max data size
+ * that Get/Set Namespace Label Data functions can transfer.
+ */
+static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
+{
+    cmd_out_label_size cmd_label_size;
+    uint32_t label_size, mxfer;
+
+    label_size = nvdimm->label_size;
+    mxfer = nvdimm_get_max_xfer_label_size();
+
+    nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer);
+
+    cmd_label_size.status = cpu_to_le32(DSM_STATUS_SUCCESS);
+    cmd_label_size.label_size = cpu_to_le32(label_size);
+    cmd_label_size.max_xfer = cpu_to_le32(mxfer);
+
+    g_array_append_vals(out, &cmd_label_size, sizeof(cmd_label_size));
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -551,6 +641,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
         cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
         g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
         goto free;
+    case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
+        nvdimm_dsm_func_label_size(nvdimm, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 30/33] nvdimm acpi: support DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Function 5 is used to get Namespace Label Data

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 1274d95..1683a82 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -501,6 +501,7 @@ struct dsm_in {
    /* the remaining size in the page is used by arg3. */
     union {
         uint8_t arg3[0];
+        cmd_in_get_label_data cmd_get_label_data;
         cmd_in_set_label_data cmd_set_label_data;
     };
 } QEMU_PACKED;
@@ -624,6 +625,47 @@ static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
     g_array_append_vals(out, &cmd_label_size, sizeof(cmd_label_size));
 }
 
+/*
+ * please refer to DSM specification 4.5 Get Namespace Label Data (Function
+ * Index 5).
+ */
+static void
+nvdimm_dsm_cmd_get_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
+{
+    cmd_in_get_label_data *cmd_in = &in->cmd_get_label_data;
+    uint32_t status = DSM_STATUS_SUCCESS;
+
+    le32_to_cpus(&cmd_in->offset);
+    le32_to_cpus(&cmd_in->length);
+
+    nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
+                 cmd_in->offset, cmd_in->length);
+
+    if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
+        nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
+                     cmd_in->offset + cmd_in->length, nvdimm->label_size);
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    if (cmd_in->length > nvdimm_get_max_xfer_label_size()) {
+        nvdimm_debug("get length (%#x) is larger than max_xfer (%#x).\n",
+                     cmd_in->length, nvdimm_get_max_xfer_label_size());
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    /* write cmd_out_get_label_data.status. */
+    nvdimm_dsm_write_status(out, status);
+    /* write cmd_out_get_label_data.out_buf. */
+    g_array_append_vals(out, nvdimm->label_data + cmd_in->offset,
+                        cmd_in->length);
+    return;
+
+exit:
+    nvdimm_dsm_write_status(out, status);
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -644,6 +686,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
         nvdimm_dsm_func_label_size(nvdimm, out);
         goto free;
+    case DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA:
+        nvdimm_dsm_cmd_get_label_data(nvdimm, in, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 30/33] nvdimm acpi: support DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Function 5 is used to get Namespace Label Data

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 1274d95..1683a82 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -501,6 +501,7 @@ struct dsm_in {
    /* the remaining size in the page is used by arg3. */
     union {
         uint8_t arg3[0];
+        cmd_in_get_label_data cmd_get_label_data;
         cmd_in_set_label_data cmd_set_label_data;
     };
 } QEMU_PACKED;
@@ -624,6 +625,47 @@ static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
     g_array_append_vals(out, &cmd_label_size, sizeof(cmd_label_size));
 }
 
+/*
+ * please refer to DSM specification 4.5 Get Namespace Label Data (Function
+ * Index 5).
+ */
+static void
+nvdimm_dsm_cmd_get_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
+{
+    cmd_in_get_label_data *cmd_in = &in->cmd_get_label_data;
+    uint32_t status = DSM_STATUS_SUCCESS;
+
+    le32_to_cpus(&cmd_in->offset);
+    le32_to_cpus(&cmd_in->length);
+
+    nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
+                 cmd_in->offset, cmd_in->length);
+
+    if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
+        nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
+                     cmd_in->offset + cmd_in->length, nvdimm->label_size);
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    if (cmd_in->length > nvdimm_get_max_xfer_label_size()) {
+        nvdimm_debug("get length (%#x) is larger than max_xfer (%#x).\n",
+                     cmd_in->length, nvdimm_get_max_xfer_label_size());
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    /* write cmd_out_get_label_data.status. */
+    nvdimm_dsm_write_status(out, status);
+    /* write cmd_out_get_label_data.out_buf. */
+    g_array_append_vals(out, nvdimm->label_data + cmd_in->offset,
+                        cmd_in->length);
+    return;
+
+exit:
+    nvdimm_dsm_write_status(out, status);
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -644,6 +686,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
         nvdimm_dsm_func_label_size(nvdimm, out);
         goto free;
+    case DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA:
+        nvdimm_dsm_cmd_get_label_data(nvdimm, in, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 31/33] nvdimm acpi: support DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Function 6 is used to set Namespace Label Data

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 1683a82..838a57e 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -529,6 +529,11 @@ struct cmd_out_get_label_data {
 } QEMU_PACKED;
 typedef struct cmd_out_get_label_data cmd_out_get_label_data;
 
+struct cmd_out_set_label_data {
+    uint32_t status;
+};
+typedef struct cmd_out_set_label_data cmd_out_set_label_data;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
@@ -537,6 +542,7 @@ struct dsm_out {
         cmd_out_implemented cmd_implemented;
         cmd_out_label_size cmd_label_size;
         cmd_out_get_label_data cmd_get_label_data;
+        cmd_out_set_label_data cmd_set_label_data;
     };
 } QEMU_PACKED;
 typedef struct dsm_out dsm_out;
@@ -666,6 +672,43 @@ exit:
     nvdimm_dsm_write_status(out, status);
 }
 
+/*
+ * please refer to DSM specification 4.6 Set Namespace Label Data
+ * (Function Index 6).
+ */
+static void
+nvdimm_dsm_cmd_set_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
+{
+    cmd_in_set_label_data *cmd_in = &in->cmd_set_label_data;
+    uint32_t status;
+
+    le32_to_cpus(&cmd_in->offset);
+    le32_to_cpus(&cmd_in->length);
+
+    nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
+                 cmd_in->offset, cmd_in->length);
+    if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
+        nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
+                     cmd_in->offset + cmd_in->length, nvdimm->label_size);
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    if (cmd_in->length > nvdimm_get_max_xfer_label_size()) {
+        nvdimm_debug("set length (%#x) is larger than max_xfer (%#x).\n",
+                     cmd_in->length, nvdimm_get_max_xfer_label_size());
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    status = DSM_STATUS_SUCCESS;
+    memcpy(nvdimm->label_data + cmd_in->offset, cmd_in->in_buf,
+           cmd_in->length);
+
+exit:
+    nvdimm_dsm_write_status(out, status);
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -689,6 +732,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     case DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA:
         nvdimm_dsm_cmd_get_label_data(nvdimm, in, out);
         goto free;
+    case DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA:
+        nvdimm_dsm_cmd_set_label_data(nvdimm, in, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 31/33] nvdimm acpi: support DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Function 6 is used to set Namespace Label Data

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 1683a82..838a57e 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -529,6 +529,11 @@ struct cmd_out_get_label_data {
 } QEMU_PACKED;
 typedef struct cmd_out_get_label_data cmd_out_get_label_data;
 
+struct cmd_out_set_label_data {
+    uint32_t status;
+};
+typedef struct cmd_out_set_label_data cmd_out_set_label_data;
+
 struct dsm_out {
     /* the size of buffer filled by QEMU. */
     uint32_t len;
@@ -537,6 +542,7 @@ struct dsm_out {
         cmd_out_implemented cmd_implemented;
         cmd_out_label_size cmd_label_size;
         cmd_out_get_label_data cmd_get_label_data;
+        cmd_out_set_label_data cmd_set_label_data;
     };
 } QEMU_PACKED;
 typedef struct dsm_out dsm_out;
@@ -666,6 +672,43 @@ exit:
     nvdimm_dsm_write_status(out, status);
 }
 
+/*
+ * please refer to DSM specification 4.6 Set Namespace Label Data
+ * (Function Index 6).
+ */
+static void
+nvdimm_dsm_cmd_set_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
+{
+    cmd_in_set_label_data *cmd_in = &in->cmd_set_label_data;
+    uint32_t status;
+
+    le32_to_cpus(&cmd_in->offset);
+    le32_to_cpus(&cmd_in->length);
+
+    nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
+                 cmd_in->offset, cmd_in->length);
+    if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
+        nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
+                     cmd_in->offset + cmd_in->length, nvdimm->label_size);
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    if (cmd_in->length > nvdimm_get_max_xfer_label_size()) {
+        nvdimm_debug("set length (%#x) is larger than max_xfer (%#x).\n",
+                     cmd_in->length, nvdimm_get_max_xfer_label_size());
+        status = DSM_DEV_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    status = DSM_STATUS_SUCCESS;
+    memcpy(nvdimm->label_data + cmd_in->offset, cmd_in->in_buf,
+           cmd_in->length);
+
+exit:
+    nvdimm_dsm_write_status(out, status);
+}
+
 static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
 {
     GSList *list = nvdimm_get_plugged_device_list();
@@ -689,6 +732,9 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     case DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA:
         nvdimm_dsm_cmd_get_label_data(nvdimm, in, out);
         goto free;
+    case DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA:
+        nvdimm_dsm_cmd_set_label_data(nvdimm, in, out);
+        goto free;
     default:
         status = DSM_STATUS_NOT_SUPPORTED;
     };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 32/33] nvdimm: allow using whole backend memory as pmem
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Introduce a parameter, named "reserve-label-data", if it is
false which indicates that QEMU does not reserve any region
on the backend memory to support label data. It is a
'label-less' NVDIMM device mode that linux will use whole
memory on the device as a single namesapce

This is useful for the users who want to pass whole nvdimm
device and make its data completely be visible to guest

The parameter is false on default

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 21 +++++++++++++++++++++
 hw/mem/nvdimm.c         | 37 ++++++++++++++++++++++++++++++++-----
 include/hw/mem/nvdimm.h |  6 ++++++
 3 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 838a57e..f69bb39 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -647,6 +647,13 @@ nvdimm_dsm_cmd_get_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
     nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
                  cmd_in->offset, cmd_in->length);
 
+    if (!nvdimm->reserve_label_data) {
+        nvdimm_debug("read label request on the device without "
+                     "label data reserved.\n");
+        status = DSM_STATUS_NOT_SUPPORTED;
+        goto exit;
+    }
+
     if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
         nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
                      cmd_in->offset + cmd_in->length, nvdimm->label_size);
@@ -687,6 +694,14 @@ nvdimm_dsm_cmd_set_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
 
     nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
                  cmd_in->offset, cmd_in->length);
+
+    if (!nvdimm->reserve_label_data) {
+        nvdimm_debug("write label request on the device without "
+                     "label data reserved.\n");
+        status = DSM_STATUS_NOT_SUPPORTED;
+        goto exit;
+    }
+
     if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
         nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
                      cmd_in->offset + cmd_in->length, nvdimm->label_size);
@@ -724,6 +739,12 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
     case DSM_FUN_IMPLEMENTED:
         cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
+
+        /* no function support if the device does not have label data. */
+        if (!nvdimm->reserve_label_data) {
+            cmd_list = cpu_to_le64(0UL);
+        }
+
         g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
         goto free;
     case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 2d121f6..cc69a3e 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -60,14 +60,15 @@ static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
 {
     MemoryRegion *mr;
     NVDIMMDevice *nvdimm = NVDIMM(dimm);
-    uint64_t size;
+    uint64_t reserved_label_size, size;
 
     nvdimm->label_size = MIN_NAMESPACE_LABEL_SIZE;
+    reserved_label_size = nvdimm->reserve_label_data ? nvdimm->label_size : 0;
 
     mr = host_memory_backend_get_memory(dimm->hostmem, errp);
     size = memory_region_size(mr);
 
-    if (size <= nvdimm->label_size) {
+    if (size <= reserved_label_size) {
         char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem));
         error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too small"
                    " to contain nvdimm namespace label (0x%" PRIx64 ")", path,
@@ -76,9 +77,12 @@ static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
     }
 
     memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm), "nvdimm-memory",
-                             mr, 0, size - nvdimm->label_size);
-    nvdimm->label_data = memory_region_get_ram_ptr(mr) +
-                         memory_region_size(&nvdimm->nvdimm_mr);
+                             mr, 0, size - reserved_label_size);
+
+    if (reserved_label_size) {
+        nvdimm->label_data = memory_region_get_ram_ptr(mr) +
+                             memory_region_size(&nvdimm->nvdimm_mr);
+    }
 }
 
 static void nvdimm_class_init(ObjectClass *oc, void *data)
@@ -93,10 +97,33 @@ static void nvdimm_class_init(ObjectClass *oc, void *data)
     ddc->get_memory_region = nvdimm_get_memory_region;
 }
 
+static bool nvdimm_get_reserve_label_data(Object *obj, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+    return nvdimm->reserve_label_data;
+}
+
+static void
+nvdimm_set_reserve_label_data(Object *obj, bool value, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+    nvdimm->reserve_label_data = value;
+}
+
+static void nvdimm_init(Object *obj)
+{
+    object_property_add_bool(obj, "reserve-label-data",
+                             nvdimm_get_reserve_label_data,
+                             nvdimm_set_reserve_label_data, NULL);
+}
+
 static TypeInfo nvdimm_info = {
     .name          = TYPE_NVDIMM,
     .parent        = TYPE_DIMM,
     .instance_size = sizeof(NVDIMMDevice),
+    .instance_init = nvdimm_init,
     .class_init    = nvdimm_class_init,
 };
 
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index c2dc635..10f85ec 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -55,6 +55,12 @@ struct NVDIMMDevice {
     /* public */
 
     /*
+     * if we need to reserve memory region for NVDIMM label data at
+     * the end of backend memory?
+     */
+    bool reserve_label_data;
+
+    /*
      * the size of label data in NVDIMM device which is presented to
      * guest via __DSM "Get Namespace Label Size" command.
      */
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 32/33] nvdimm: allow using whole backend memory as pmem
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Introduce a parameter, named "reserve-label-data", if it is
false which indicates that QEMU does not reserve any region
on the backend memory to support label data. It is a
'label-less' NVDIMM device mode that linux will use whole
memory on the device as a single namesapce

This is useful for the users who want to pass whole nvdimm
device and make its data completely be visible to guest

The parameter is false on default

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c        | 21 +++++++++++++++++++++
 hw/mem/nvdimm.c         | 37 ++++++++++++++++++++++++++++++++-----
 include/hw/mem/nvdimm.h |  6 ++++++
 3 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 838a57e..f69bb39 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -647,6 +647,13 @@ nvdimm_dsm_cmd_get_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
     nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
                  cmd_in->offset, cmd_in->length);
 
+    if (!nvdimm->reserve_label_data) {
+        nvdimm_debug("read label request on the device without "
+                     "label data reserved.\n");
+        status = DSM_STATUS_NOT_SUPPORTED;
+        goto exit;
+    }
+
     if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
         nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
                      cmd_in->offset + cmd_in->length, nvdimm->label_size);
@@ -687,6 +694,14 @@ nvdimm_dsm_cmd_set_label_data(NVDIMMDevice *nvdimm, dsm_in *in, GArray *out)
 
     nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
                  cmd_in->offset, cmd_in->length);
+
+    if (!nvdimm->reserve_label_data) {
+        nvdimm_debug("write label request on the device without "
+                     "label data reserved.\n");
+        status = DSM_STATUS_NOT_SUPPORTED;
+        goto exit;
+    }
+
     if (nvdimm->label_size < cmd_in->offset + cmd_in->length) {
         nvdimm_debug("position %#x is beyond label data (len = %#lx).\n",
                      cmd_in->offset + cmd_in->length, nvdimm->label_size);
@@ -724,6 +739,12 @@ static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
     /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
     case DSM_FUN_IMPLEMENTED:
         cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
+
+        /* no function support if the device does not have label data. */
+        if (!nvdimm->reserve_label_data) {
+            cmd_list = cpu_to_le64(0UL);
+        }
+
         g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
         goto free;
     case DSM_DEV_FUN_NAMESPACE_LABEL_SIZE:
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 2d121f6..cc69a3e 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -60,14 +60,15 @@ static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
 {
     MemoryRegion *mr;
     NVDIMMDevice *nvdimm = NVDIMM(dimm);
-    uint64_t size;
+    uint64_t reserved_label_size, size;
 
     nvdimm->label_size = MIN_NAMESPACE_LABEL_SIZE;
+    reserved_label_size = nvdimm->reserve_label_data ? nvdimm->label_size : 0;
 
     mr = host_memory_backend_get_memory(dimm->hostmem, errp);
     size = memory_region_size(mr);
 
-    if (size <= nvdimm->label_size) {
+    if (size <= reserved_label_size) {
         char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem));
         error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too small"
                    " to contain nvdimm namespace label (0x%" PRIx64 ")", path,
@@ -76,9 +77,12 @@ static void nvdimm_realize(DIMMDevice *dimm, Error **errp)
     }
 
     memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm), "nvdimm-memory",
-                             mr, 0, size - nvdimm->label_size);
-    nvdimm->label_data = memory_region_get_ram_ptr(mr) +
-                         memory_region_size(&nvdimm->nvdimm_mr);
+                             mr, 0, size - reserved_label_size);
+
+    if (reserved_label_size) {
+        nvdimm->label_data = memory_region_get_ram_ptr(mr) +
+                             memory_region_size(&nvdimm->nvdimm_mr);
+    }
 }
 
 static void nvdimm_class_init(ObjectClass *oc, void *data)
@@ -93,10 +97,33 @@ static void nvdimm_class_init(ObjectClass *oc, void *data)
     ddc->get_memory_region = nvdimm_get_memory_region;
 }
 
+static bool nvdimm_get_reserve_label_data(Object *obj, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+    return nvdimm->reserve_label_data;
+}
+
+static void
+nvdimm_set_reserve_label_data(Object *obj, bool value, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+    nvdimm->reserve_label_data = value;
+}
+
+static void nvdimm_init(Object *obj)
+{
+    object_property_add_bool(obj, "reserve-label-data",
+                             nvdimm_get_reserve_label_data,
+                             nvdimm_set_reserve_label_data, NULL);
+}
+
 static TypeInfo nvdimm_info = {
     .name          = TYPE_NVDIMM,
     .parent        = TYPE_DIMM,
     .instance_size = sizeof(NVDIMMDevice),
+    .instance_init = nvdimm_init,
     .class_init    = nvdimm_class_init,
 };
 
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index c2dc635..10f85ec 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -55,6 +55,12 @@ struct NVDIMMDevice {
     /* public */
 
     /*
+     * if we need to reserve memory region for NVDIMM label data at
+     * the end of backend memory?
+     */
+    bool reserve_label_data;
+
+    /*
      * the size of label data in NVDIMM device which is presented to
      * guest via __DSM "Get Namespace Label Size" command.
      */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v4 33/33] nvdimm: add maintain info
  2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  0:54   ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Add NVDIMM maintainer

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9bde832..cf259f9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -868,6 +868,13 @@ M: Jiri Pirko <jiri@resnulli.us>
 S: Maintained
 F: hw/net/rocker/
 
+NVDIMM
+M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+S: Maintained
+F: hw/acpi/nvdimm.c
+F: hw/mem/nvdimm.c
+F: include/hw/mem/nvdimm.h
+
 Subsystems
 ----------
 Audio
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [Qemu-devel] [PATCH v4 33/33] nvdimm: add maintain info
@ 2015-10-19  0:54   ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  0:54 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Add NVDIMM maintainer

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9bde832..cf259f9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -868,6 +868,13 @@ M: Jiri Pirko <jiri@resnulli.us>
 S: Maintained
 F: hw/net/rocker/
 
+NVDIMM
+M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+S: Maintained
+F: hw/acpi/nvdimm.c
+F: hw/mem/nvdimm.c
+F: include/hw/mem/nvdimm.h
+
 Subsystems
 ----------
 Audio
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
  2015-10-18 17:15     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19  3:58       ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  3:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 10/19/2015 01:15 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:09AM +0800, Xiao Guangrong wrote:
>> +typedef struct nfit_spa nfit_spa;
>
> There are still multiple coding style violations.  Pls fix all code to
> match coding style.  I commented on this before.
>

Er, i thought what you disliked is just function names... Now I know i
was misunderstanding it and sorry for wasting your time on it.

I will change all structs in this patch that:
struct nfit_spa -> struct nvdimm_nfit_spa
struct nfit_memdev -> struct nvdimm_nfit_memdev
struct nfit_dcr nfit_dcr -> struct nvdimm_nfit_dcr nfit_dcr;

and also copy the spec reference from where these struct was used to
where these struct was defined.



^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI
@ 2015-10-19  3:58       ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  3:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 10/19/2015 01:15 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:09AM +0800, Xiao Guangrong wrote:
>> +typedef struct nfit_spa nfit_spa;
>
> There are still multiple coding style violations.  Pls fix all code to
> match coding style.  I commented on this before.
>

Er, i thought what you disliked is just function names... Now I know i
was misunderstanding it and sorry for wasting your time on it.

I will change all structs in this patch that:
struct nfit_spa -> struct nvdimm_nfit_spa
struct nfit_memdev -> struct nvdimm_nfit_memdev
struct nfit_dcr nfit_dcr -> struct nvdimm_nfit_dcr nfit_dcr;

and also copy the spec reference from where these struct was used to
where these struct was defined.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-18 17:16     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19  4:04       ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  4:04 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
>> Check if the input Arg3 is valid then store it into dsm_in if needed
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 19 +++++++++++++++++++
>>   1 file changed, 19 insertions(+)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index 7e99889..b211b8b 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>>
>>       method = aml_method_serialized("NCAL", 4);
>>       {
>> +        Aml *ifctx;
>> +
>>           aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
>>           aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
>>           aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
>>
>> +        /* Arg3 is passed as Package and it has one element? */
>> +        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
>> +                                         aml_int(4)),
>> +                               aml_equal(aml_sizeof(aml_arg(3)),
>> +                                         aml_int(1))));
>> +        {
>> +            /* Local0 = Index(Arg3, 0) */
>> +            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
>> +                                        aml_local(0)));
>> +            /* Local3 = DeRefOf(Local0) */
>> +            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
>> +                                        aml_local(3)));
>> +            /* ARG3 = Local3 */
>> +            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
>> +        }
>> +        aml_append(method, ifctx);
>> +
>>           aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
>>
>>           aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>
> I commented on this patch on v3.
> It doesn't look like this was addressed.
>

Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
device	_DSM method) on v3.

Do you mean we need more and better comment to explain arg3? Or anything else?



^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19  4:04       ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  4:04 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
>> Check if the input Arg3 is valid then store it into dsm_in if needed
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 19 +++++++++++++++++++
>>   1 file changed, 19 insertions(+)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index 7e99889..b211b8b 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
>>
>>       method = aml_method_serialized("NCAL", 4);
>>       {
>> +        Aml *ifctx;
>> +
>>           aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
>>           aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
>>           aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
>>
>> +        /* Arg3 is passed as Package and it has one element? */
>> +        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
>> +                                         aml_int(4)),
>> +                               aml_equal(aml_sizeof(aml_arg(3)),
>> +                                         aml_int(1))));
>> +        {
>> +            /* Local0 = Index(Arg3, 0) */
>> +            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
>> +                                        aml_local(0)));
>> +            /* Local3 = DeRefOf(Local0) */
>> +            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
>> +                                        aml_local(3)));
>> +            /* ARG3 = Local3 */
>> +            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
>> +        }
>> +        aml_append(method, ifctx);
>> +
>>           aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
>>
>>           aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>
> I commented on this patch on v3.
> It doesn't look like this was addressed.
>

Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
device	_DSM method) on v3.

Do you mean we need more and better comment to explain arg3? Or anything else?

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-18 18:05     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19  4:39       ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  4:39 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
>>
>> Function 0 is a query function. We do not support any function on root
>> device and only 3 functions are support for NVDIMM device,
>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
>> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
>> access device's Label Namespace
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 182 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index b211b8b..37fea1c 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>>       return nvdimm_slot_to_spa_index(slot) + 1;
>>   }
>>
>> +static NVDIMMDevice
>> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
>> +{
>> +    for (; list; list = list->next) {
>> +        NVDIMMDevice *nvdimm = list->data;
>> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
>> +                                           NULL);
>> +
>> +        if (nvdimm_slot_to_handle(slot) == handle) {
>> +            return nvdimm;
>> +        }
>> +    }
>> +
>> +    return NULL;
>> +}
>> +
>>   /*
>>    * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>>    * Structure
>> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>>   /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>>   #define NOTIFY_VALUE      0x99
>
> Again, please prefix everything consistently.

Okay, will do. Sorry for i missed it.

>
>>
>> +enum {
>> +    DSM_FUN_IMPLEMENTED = 0,
>> +
>> +    /* NVDIMM Root Device Functions */
>> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
>> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
>> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
>> +
>> +    /* NVDIMM Device (non-root) Functions */
>> +    DSM_DEV_FUN_SMART = 1,
>> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
>> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
>> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
>> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
>> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
>> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
>> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
>> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
>> +};
>
> Does FUN stand for "function"? FUNC or FN is probably better.
>

Yes.

> Please list exact names as they appear in spec so
> they can be searched for.

The spec reference was at where this _FUN_ is used, eg:

/*
  * Please refer to DSM specification 4.4.1 Get Namespace Label Size
  * (Function Index 4).
  *
  * It gets the size of Namespace Label data area and the max data size
  * that Get/Set Namespace Label Data functions can transfer.
  */
static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)

I will follow your ‘single use’ comments below, these definitions will
be dropped, the code will be like this:

switch (function) {
case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
nvdimm_dsm_func_label_size();
case ...
...
};

>
>
>
>> +
>> +enum {
>> +    /* Common return status codes. */
>> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
>> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
>> +
>> +    /* NVDIMM Root Device _DSM function return status codes*/
>> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
>> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
>> +                                                        Error */
>> +
>> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
>> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
>> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
>> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
>> +};
>> +
>> +/* Current revision supported by DSM specification is 1. */
>> +#define DSM_REVISION        (1)
>> +
>> +/*
>> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
>> + * Value Information:
>
> Drop "please refer to".

Okay.

>
>> + *   if set to zero, no functions are supported (other than function zero)
>> + *   for the specified UUID and Revision ID. If set to one, at least one
>> + *   additional function is supported.
>> + */
>> +
>> +/* do not support any function on root. */
>> +#define ROOT_SUPPORT_FUN     (0ULL)
>
> Needs a name that implies the comment somehow.
>
>> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
>> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
>> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
>> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
>> +
>
> I think it's best to just drop these macros.
> There's a single point of use - just add a comment there
> explaining what does it mean.

Okay. Good to me.

> You will be able to drop all _FUN_ macros too.

Yes, it's good for code reduction.

>
>
>>   struct dsm_in {
>>       uint32_t handle;
>>       uint32_t revision;
>> @@ -420,6 +490,11 @@ struct dsm_in {
>>   } QEMU_PACKED;
>>   typedef struct dsm_in dsm_in;
>>
>> +struct cmd_out_implemented {
>> +    uint64_t cmd_list;
>> +};
>> +typedef struct cmd_out_implemented cmd_out_implemented;
>> +
>>   struct dsm_out {
>>       /* the size of buffer filled by QEMU. */
>>       uint32_t len;
>> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>>       return 0;
>>   }
>>
>> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
>> +{
>> +    /* status locates in the first 4 bytes in the dsm memory. */
>
> located?

Yes...
>
>> +    assert(!out->len);
>
>
> But dsm itself can be part of a bigger table.
> So don't do it.

Okay, will drop it.

>
>> +
>> +    status = cpu_to_le32(status);
>> +    g_array_append_vals(out, &status, sizeof(status));
>
> I think this should just use the (unfortunately named)
> build_append_int_noprefix. Same applied everywhere
> where you add single values.

Okay, will use it instead.

>
>> +}
>> +
>> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
>> +{
>> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
>> +
>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>> +    if (in->function == DSM_FUN_IMPLEMENTED) {
>> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
>
> see about about single use values.
>

Yes, it is good to me, will follow it.

>
>> +
>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>> +        return;
>> +    }
>> +
>> +    nvdimm_debug("Return status %#x.\n", status);
>> +    nvdimm_dsm_write_status(out, status);
>> +}
>> +
>> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
>> +{
>> +    GSList *list = nvdimm_get_plugged_device_list();
>> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
>> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
>> +    uint64_t cmd_list;
>> +
>> +    if (!nvdimm) {
>> +        goto set_status_free;
>> +    }
>> +
>> +    switch (in->function) {
>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>> +    case DSM_FUN_IMPLEMENTED:
>> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>> +        goto free;
>> +    default:
>> +        status = DSM_STATUS_NOT_SUPPORTED;
>> +    };
>> +
>> +set_status_free:
>> +    nvdimm_debug("Return status %#x.\n", status);
>> +    nvdimm_dsm_write_status(out, status);
>> +free:
>> +    g_slist_free(list);
>> +}
>> +
>>   static void
>>   nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>>   {
>> +    NVDIMMState *state = opaque;
>> +    MemoryRegion *dsm_ram_mr;
>> +    dsm_in *in;
>> +    GArray *out;
>> +    void *dsm_ram_addr;
>
>
> Why don't you give this the correct type? Will avoid need for casts.

If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
little strange.

I will do it as your suggestion, and make a comment for the copy operation:
/*
  * The DSM memory is used for both OSPM saves its input parameter and QEMU
  * saves its output result.
  */
>
>> +
>>       if (val != NOTIFY_VALUE) {
>>           fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>>       }
>> +
>> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
>> +                                    getpagesize()).mr;
>> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
>
>
> This needs a validity check for size.

Okay, will add this:

assert(memory_region_size(dsm_ram_mr) == getpagesize());

>
>> +
>> +    /*
>> +     * copy all input data to our local memory to avoid potential issue
>> +     * as the dsm memory is visible to guest.
>
> this comment doesn't help.
> pls replace "potential issue" with an explanation.

Okay, will change the comment to:
/* As DSM memory is mapped to guest address space so that evil guest can change
  * its content while we are doing DSM emulation. Avoid it by copying DSM memory
  * to QEMU local memory
  */

>
>> +     */
>> +    in = g_malloc(memory_region_size(dsm_ram_mr));
>> +    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
>> +
>> +    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);
>> +
>> +    if (in->revision != DSM_REVISION) {
>> +        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
>> +                      in->revision, DSM_REVISION);
>> +        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
>> +        goto exit;
>> +    }
>> +
>> +    /* Handle 0 is reserved for NVDIMM Root Device. */
>> +    if (!in->handle) {
>> +        nvdimm_dsm_write_root(in, out);
>> +        goto exit;
>> +    }
>> +
>> +    nvdimm_dsm_write_nvdimm(in, out);
>> +
>> +exit:
>> +    /* Write our output result to dsm memory. */
>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>> +    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
>
> This breaks migration as memory is not dirtied.
>
> address_space_write is generally preferable to change memory.

Good point, will fix.


^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-19  4:39       ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  4:39 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
>>
>> Function 0 is a query function. We do not support any function on root
>> device and only 3 functions are support for NVDIMM device,
>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
>> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
>> access device's Label Namespace
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 182 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index b211b8b..37fea1c 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>>       return nvdimm_slot_to_spa_index(slot) + 1;
>>   }
>>
>> +static NVDIMMDevice
>> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
>> +{
>> +    for (; list; list = list->next) {
>> +        NVDIMMDevice *nvdimm = list->data;
>> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
>> +                                           NULL);
>> +
>> +        if (nvdimm_slot_to_handle(slot) == handle) {
>> +            return nvdimm;
>> +        }
>> +    }
>> +
>> +    return NULL;
>> +}
>> +
>>   /*
>>    * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>>    * Structure
>> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>>   /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>>   #define NOTIFY_VALUE      0x99
>
> Again, please prefix everything consistently.

Okay, will do. Sorry for i missed it.

>
>>
>> +enum {
>> +    DSM_FUN_IMPLEMENTED = 0,
>> +
>> +    /* NVDIMM Root Device Functions */
>> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
>> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
>> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
>> +
>> +    /* NVDIMM Device (non-root) Functions */
>> +    DSM_DEV_FUN_SMART = 1,
>> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
>> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
>> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
>> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
>> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
>> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
>> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
>> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
>> +};
>
> Does FUN stand for "function"? FUNC or FN is probably better.
>

Yes.

> Please list exact names as they appear in spec so
> they can be searched for.

The spec reference was at where this _FUN_ is used, eg:

/*
  * Please refer to DSM specification 4.4.1 Get Namespace Label Size
  * (Function Index 4).
  *
  * It gets the size of Namespace Label data area and the max data size
  * that Get/Set Namespace Label Data functions can transfer.
  */
static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)

I will follow your ‘single use’ comments below, these definitions will
be dropped, the code will be like this:

switch (function) {
case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
nvdimm_dsm_func_label_size();
case ...
...
};

>
>
>
>> +
>> +enum {
>> +    /* Common return status codes. */
>> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
>> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
>> +
>> +    /* NVDIMM Root Device _DSM function return status codes*/
>> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
>> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
>> +                                                        Error */
>> +
>> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
>> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
>> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
>> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
>> +};
>> +
>> +/* Current revision supported by DSM specification is 1. */
>> +#define DSM_REVISION        (1)
>> +
>> +/*
>> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
>> + * Value Information:
>
> Drop "please refer to".

Okay.

>
>> + *   if set to zero, no functions are supported (other than function zero)
>> + *   for the specified UUID and Revision ID. If set to one, at least one
>> + *   additional function is supported.
>> + */
>> +
>> +/* do not support any function on root. */
>> +#define ROOT_SUPPORT_FUN     (0ULL)
>
> Needs a name that implies the comment somehow.
>
>> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
>> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
>> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
>> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
>> +
>
> I think it's best to just drop these macros.
> There's a single point of use - just add a comment there
> explaining what does it mean.

Okay. Good to me.

> You will be able to drop all _FUN_ macros too.

Yes, it's good for code reduction.

>
>
>>   struct dsm_in {
>>       uint32_t handle;
>>       uint32_t revision;
>> @@ -420,6 +490,11 @@ struct dsm_in {
>>   } QEMU_PACKED;
>>   typedef struct dsm_in dsm_in;
>>
>> +struct cmd_out_implemented {
>> +    uint64_t cmd_list;
>> +};
>> +typedef struct cmd_out_implemented cmd_out_implemented;
>> +
>>   struct dsm_out {
>>       /* the size of buffer filled by QEMU. */
>>       uint32_t len;
>> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>>       return 0;
>>   }
>>
>> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
>> +{
>> +    /* status locates in the first 4 bytes in the dsm memory. */
>
> located?

Yes...
>
>> +    assert(!out->len);
>
>
> But dsm itself can be part of a bigger table.
> So don't do it.

Okay, will drop it.

>
>> +
>> +    status = cpu_to_le32(status);
>> +    g_array_append_vals(out, &status, sizeof(status));
>
> I think this should just use the (unfortunately named)
> build_append_int_noprefix. Same applied everywhere
> where you add single values.

Okay, will use it instead.

>
>> +}
>> +
>> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
>> +{
>> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
>> +
>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>> +    if (in->function == DSM_FUN_IMPLEMENTED) {
>> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
>
> see about about single use values.
>

Yes, it is good to me, will follow it.

>
>> +
>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>> +        return;
>> +    }
>> +
>> +    nvdimm_debug("Return status %#x.\n", status);
>> +    nvdimm_dsm_write_status(out, status);
>> +}
>> +
>> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
>> +{
>> +    GSList *list = nvdimm_get_plugged_device_list();
>> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
>> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
>> +    uint64_t cmd_list;
>> +
>> +    if (!nvdimm) {
>> +        goto set_status_free;
>> +    }
>> +
>> +    switch (in->function) {
>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>> +    case DSM_FUN_IMPLEMENTED:
>> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>> +        goto free;
>> +    default:
>> +        status = DSM_STATUS_NOT_SUPPORTED;
>> +    };
>> +
>> +set_status_free:
>> +    nvdimm_debug("Return status %#x.\n", status);
>> +    nvdimm_dsm_write_status(out, status);
>> +free:
>> +    g_slist_free(list);
>> +}
>> +
>>   static void
>>   nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>>   {
>> +    NVDIMMState *state = opaque;
>> +    MemoryRegion *dsm_ram_mr;
>> +    dsm_in *in;
>> +    GArray *out;
>> +    void *dsm_ram_addr;
>
>
> Why don't you give this the correct type? Will avoid need for casts.

If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
little strange.

I will do it as your suggestion, and make a comment for the copy operation:
/*
  * The DSM memory is used for both OSPM saves its input parameter and QEMU
  * saves its output result.
  */
>
>> +
>>       if (val != NOTIFY_VALUE) {
>>           fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>>       }
>> +
>> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
>> +                                    getpagesize()).mr;
>> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
>
>
> This needs a validity check for size.

Okay, will add this:

assert(memory_region_size(dsm_ram_mr) == getpagesize());

>
>> +
>> +    /*
>> +     * copy all input data to our local memory to avoid potential issue
>> +     * as the dsm memory is visible to guest.
>
> this comment doesn't help.
> pls replace "potential issue" with an explanation.

Okay, will change the comment to:
/* As DSM memory is mapped to guest address space so that evil guest can change
  * its content while we are doing DSM emulation. Avoid it by copying DSM memory
  * to QEMU local memory
  */

>
>> +     */
>> +    in = g_malloc(memory_region_size(dsm_ram_mr));
>> +    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
>> +
>> +    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);
>> +
>> +    if (in->revision != DSM_REVISION) {
>> +        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
>> +                      in->revision, DSM_REVISION);
>> +        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
>> +        goto exit;
>> +    }
>> +
>> +    /* Handle 0 is reserved for NVDIMM Root Device. */
>> +    if (!in->handle) {
>> +        nvdimm_dsm_write_root(in, out);
>> +        goto exit;
>> +    }
>> +
>> +    nvdimm_dsm_write_nvdimm(in, out);
>> +
>> +exit:
>> +    /* Write our output result to dsm memory. */
>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>> +    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
>
> This breaks migration as memory is not dirtied.
>
> address_space_write is generally preferable to change memory.

Good point, will fix.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19  4:04       ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  6:57         ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  6:57 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> >>Check if the input Arg3 is valid then store it into dsm_in if needed
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index 7e99889..b211b8b 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
> >>
> >>      method = aml_method_serialized("NCAL", 4);
> >>      {
> >>+        Aml *ifctx;
> >>+
> >>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
> >>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
> >>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
> >>
> >>+        /* Arg3 is passed as Package and it has one element? */
> >>+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> >>+                                         aml_int(4)),
> >>+                               aml_equal(aml_sizeof(aml_arg(3)),
> >>+                                         aml_int(1))));
> >>+        {
> >>+            /* Local0 = Index(Arg3, 0) */
> >>+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> >>+                                        aml_local(0)));
> >>+            /* Local3 = DeRefOf(Local0) */
> >>+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> >>+                                        aml_local(3)));
> >>+            /* ARG3 = Local3 */
> >>+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> >>+        }
> >>+        aml_append(method, ifctx);
> >>+
> >>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
> >>
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >
> >I commented on this patch on v3.
> >It doesn't look like this was addressed.
> >
> 
> Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
> device	_DSM method) on v3.
> 
> Do you mean we need more and better comment to explain arg3? Or anything else?

Interesting. I have it in my sent mail file, but it doesn't seem to
be on list. I've just resent it, and a couple of other messages
that seem to have disappeared into the ether.

These are the messages I have for v3:

33587   F To Xiao Guangro Re: [PATCH v3 26/32] nvdimm: save arg3 for NVDIMM device _DSM method
33588   F To Xiao Guangro Re: [PATCH v3 22/32] nvdimm: init the address region used by NVDIMM ACPI
33589   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table
33590   F To Xiao Guangro Re: [PATCH v3 00/32] implement vNVDIMM
33597   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table
33598   F To Xiao Guangro Re: [PATCH v3 00/32] implement vNVDIMM
33599   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table

-- 
MST

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19  6:57         ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  6:57 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> >>Check if the input Arg3 is valid then store it into dsm_in if needed
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index 7e99889..b211b8b 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
> >>
> >>      method = aml_method_serialized("NCAL", 4);
> >>      {
> >>+        Aml *ifctx;
> >>+
> >>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
> >>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
> >>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
> >>
> >>+        /* Arg3 is passed as Package and it has one element? */
> >>+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> >>+                                         aml_int(4)),
> >>+                               aml_equal(aml_sizeof(aml_arg(3)),
> >>+                                         aml_int(1))));
> >>+        {
> >>+            /* Local0 = Index(Arg3, 0) */
> >>+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> >>+                                        aml_local(0)));
> >>+            /* Local3 = DeRefOf(Local0) */
> >>+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> >>+                                        aml_local(3)));
> >>+            /* ARG3 = Local3 */
> >>+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> >>+        }
> >>+        aml_append(method, ifctx);
> >>+
> >>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
> >>
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >
> >I commented on this patch on v3.
> >It doesn't look like this was addressed.
> >
> 
> Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
> device	_DSM method) on v3.
> 
> Do you mean we need more and better comment to explain arg3? Or anything else?

Interesting. I have it in my sent mail file, but it doesn't seem to
be on list. I've just resent it, and a couple of other messages
that seem to have disappeared into the ether.

These are the messages I have for v3:

33587   F To Xiao Guangro Re: [PATCH v3 26/32] nvdimm: save arg3 for NVDIMM device _DSM method
33588   F To Xiao Guangro Re: [PATCH v3 22/32] nvdimm: init the address region used by NVDIMM ACPI
33589   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table
33590   F To Xiao Guangro Re: [PATCH v3 00/32] implement vNVDIMM
33597   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table
33598   F To Xiao Guangro Re: [PATCH v3 00/32] implement vNVDIMM
33599   F To Xiao Guangro Re: [PATCH v3 23/32] nvdimm: build ACPI NFIT table

-- 
MST

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-19  4:39       ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  7:06         ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  7:06 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 12:39:24PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>__DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
> >>
> >>Function 0 is a query function. We do not support any function on root
> >>device and only 3 functions are support for NVDIMM device,
> >>DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
> >>DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
> >>access device's Label Namespace
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 182 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index b211b8b..37fea1c 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
> >>      return nvdimm_slot_to_spa_index(slot) + 1;
> >>  }
> >>
> >>+static NVDIMMDevice
> >>+*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
> >>+{
> >>+    for (; list; list = list->next) {
> >>+        NVDIMMDevice *nvdimm = list->data;
> >>+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
> >>+                                           NULL);
> >>+
> >>+        if (nvdimm_slot_to_handle(slot) == handle) {
> >>+            return nvdimm;
> >>+        }
> >>+    }
> >>+
> >>+    return NULL;
> >>+}
> >>+
> >>  /*
> >>   * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
> >>   * Structure
> >>@@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
> >>  /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
> >>  #define NOTIFY_VALUE      0x99
> >
> >Again, please prefix everything consistently.
> 
> Okay, will do. Sorry for i missed it.
> 
> >
> >>
> >>+enum {
> >>+    DSM_FUN_IMPLEMENTED = 0,
> >>+
> >>+    /* NVDIMM Root Device Functions */
> >>+    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
> >>+    DSM_ROOT_DEV_FUN_ARS_START = 2,
> >>+    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
> >>+
> >>+    /* NVDIMM Device (non-root) Functions */
> >>+    DSM_DEV_FUN_SMART = 1,
> >>+    DSM_DEV_FUN_SMART_THRESHOLD = 2,
> >>+    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
> >>+    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
> >>+    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
> >>+    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
> >>+    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
> >>+    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
> >>+    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
> >>+};
> >
> >Does FUN stand for "function"? FUNC or FN is probably better.
> >
> 
> Yes.
> 
> >Please list exact names as they appear in spec so
> >they can be searched for.
> 
> The spec reference was at where this _FUN_ is used, eg:
> 
> /*
>  * Please refer to DSM specification 4.4.1 Get Namespace Label Size
>  * (Function Index 4).
>  *
>  * It gets the size of Namespace Label data area and the max data size
>  * that Get/Set Namespace Label Data functions can transfer.
>  */
> static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
> 
> I will follow your ‘single use’ comments below, these definitions will
> be dropped, the code will be like this:
> 
> switch (function) {
> case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:

If it's the same spec, you don't have to repeat it:

/* Encode function according to DSM Spec rev 1.0 */
> switch (function) {
>     case 4 /* 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:

same for chapter etc.

> nvdimm_dsm_func_label_size();
> case ...
> ...
> };
> 
> >
> >
> >
> >>+
> >>+enum {
> >>+    /* Common return status codes. */
> >>+    DSM_STATUS_SUCCESS = 0,                   /* Success */
> >>+    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
> >>+
> >>+    /* NVDIMM Root Device _DSM function return status codes*/
> >>+    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
> >>+    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
> >>+                                                        Error */
> >>+
> >>+    /* NVDIMM Device (non-root) _DSM function return status codes*/
> >>+    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
> >>+    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
> >>+    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
> >>+};
> >>+
> >>+/* Current revision supported by DSM specification is 1. */
> >>+#define DSM_REVISION        (1)
> >>+
> >>+/*
> >>+ * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
> >>+ * Value Information:
> >
> >Drop "please refer to".
> 
> Okay.
> 
> >
> >>+ *   if set to zero, no functions are supported (other than function zero)
> >>+ *   for the specified UUID and Revision ID. If set to one, at least one
> >>+ *   additional function is supported.
> >>+ */
> >>+
> >>+/* do not support any function on root. */
> >>+#define ROOT_SUPPORT_FUN     (0ULL)
> >
> >Needs a name that implies the comment somehow.
> >
> >>+#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
> >>+                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
> >>+                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
> >>+                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
> >>+
> >
> >I think it's best to just drop these macros.
> >There's a single point of use - just add a comment there
> >explaining what does it mean.
> 
> Okay. Good to me.
> 
> >You will be able to drop all _FUN_ macros too.
> 
> Yes, it's good for code reduction.
> 
> >
> >
> >>  struct dsm_in {
> >>      uint32_t handle;
> >>      uint32_t revision;
> >>@@ -420,6 +490,11 @@ struct dsm_in {
> >>  } QEMU_PACKED;
> >>  typedef struct dsm_in dsm_in;
> >>
> >>+struct cmd_out_implemented {
> >>+    uint64_t cmd_list;
> >>+};
> >>+typedef struct cmd_out_implemented cmd_out_implemented;
> >>+
> >>  struct dsm_out {
> >>      /* the size of buffer filled by QEMU. */
> >>      uint32_t len;
> >>@@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
> >>      return 0;
> >>  }
> >>
> >>+static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
> >>+{
> >>+    /* status locates in the first 4 bytes in the dsm memory. */
> >
> >located?
> 
> Yes...
> >
> >>+    assert(!out->len);
> >
> >
> >But dsm itself can be part of a bigger table.
> >So don't do it.
> 
> Okay, will drop it.
> 
> >
> >>+
> >>+    status = cpu_to_le32(status);
> >>+    g_array_append_vals(out, &status, sizeof(status));
> >
> >I think this should just use the (unfortunately named)
> >build_append_int_noprefix. Same applied everywhere
> >where you add single values.
> 
> Okay, will use it instead.
> 
> >
> >>+}
> >>+
> >>+static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
> >>+{
> >>+    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
> >>+
> >>+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> >>+    if (in->function == DSM_FUN_IMPLEMENTED) {
> >>+        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
> >
> >see about about single use values.
> >
> 
> Yes, it is good to me, will follow it.
> 
> >
> >>+
> >>+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> >>+        return;
> >>+    }
> >>+
> >>+    nvdimm_debug("Return status %#x.\n", status);
> >>+    nvdimm_dsm_write_status(out, status);
> >>+}
> >>+
> >>+static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
> >>+{
> >>+    GSList *list = nvdimm_get_plugged_device_list();
> >>+    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
> >>+    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
> >>+    uint64_t cmd_list;
> >>+
> >>+    if (!nvdimm) {
> >>+        goto set_status_free;
> >>+    }
> >>+
> >>+    switch (in->function) {
> >>+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> >>+    case DSM_FUN_IMPLEMENTED:
> >>+        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
> >>+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> >>+        goto free;
> >>+    default:
> >>+        status = DSM_STATUS_NOT_SUPPORTED;
> >>+    };
> >>+
> >>+set_status_free:
> >>+    nvdimm_debug("Return status %#x.\n", status);
> >>+    nvdimm_dsm_write_status(out, status);
> >>+free:
> >>+    g_slist_free(list);
> >>+}
> >>+
> >>  static void
> >>  nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> >>  {
> >>+    NVDIMMState *state = opaque;
> >>+    MemoryRegion *dsm_ram_mr;
> >>+    dsm_in *in;
> >>+    GArray *out;
> >>+    void *dsm_ram_addr;
> >
> >
> >Why don't you give this the correct type? Will avoid need for casts.
> 
> If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
> little strange.
> 
> I will do it as your suggestion, and make a comment for the copy operation:
> /*
>  * The DSM memory is used for both OSPM saves its input parameter and QEMU
>  * saves its output result.
>  */

Fix up the english here pls:
>  * The DSM memory has two uses: OSPM saves its input parameter there, QEMU
>  * uses it to save its output result.


> >
> >>+
> >>      if (val != NOTIFY_VALUE) {
> >>          fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
> >>      }
> >>+
> >>+    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
> >>+                                    getpagesize()).mr;
> >>+    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
> >
> >
> >This needs a validity check for size.
> 
> Okay, will add this:
> 
> assert(memory_region_size(dsm_ram_mr) == getpagesize());

No, the point is to make sure getpagesize is big enough to hold
the structure.

> >
> >>+
> >>+    /*
> >>+     * copy all input data to our local memory to avoid potential issue
> >>+     * as the dsm memory is visible to guest.
> >
> >this comment doesn't help.
> >pls replace "potential issue" with an explanation.
> 
> Okay, will change the comment to:
> /* As DSM memory is mapped to guest address space so that evil guest can change

s/As/The/
s/that evil/an evil/

>  * its content while we are doing DSM emulation. Avoid it by copying DSM memory

s/Avoid it/Avoid this/

>  * to QEMU local memory
>  */
> 
> >
> >>+     */
> >>+    in = g_malloc(memory_region_size(dsm_ram_mr));
> >>+    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
> >>+
> >>+    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);
> >>+
> >>+    if (in->revision != DSM_REVISION) {
> >>+        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
> >>+                      in->revision, DSM_REVISION);
> >>+        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
> >>+        goto exit;
> >>+    }
> >>+
> >>+    /* Handle 0 is reserved for NVDIMM Root Device. */
> >>+    if (!in->handle) {
> >>+        nvdimm_dsm_write_root(in, out);
> >>+        goto exit;
> >>+    }
> >>+
> >>+    nvdimm_dsm_write_nvdimm(in, out);
> >>+
> >>+exit:
> >>+    /* Write our output result to dsm memory. */
> >>+    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >>+    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
> >
> >This breaks migration as memory is not dirtied.
> >
> >address_space_write is generally preferable to change memory.
> 
> Good point, will fix.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-19  7:06         ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  7:06 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 12:39:24PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>__DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
> >>
> >>Function 0 is a query function. We do not support any function on root
> >>device and only 3 functions are support for NVDIMM device,
> >>DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
> >>DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
> >>access device's Label Namespace
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 182 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index b211b8b..37fea1c 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
> >>      return nvdimm_slot_to_spa_index(slot) + 1;
> >>  }
> >>
> >>+static NVDIMMDevice
> >>+*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
> >>+{
> >>+    for (; list; list = list->next) {
> >>+        NVDIMMDevice *nvdimm = list->data;
> >>+        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
> >>+                                           NULL);
> >>+
> >>+        if (nvdimm_slot_to_handle(slot) == handle) {
> >>+            return nvdimm;
> >>+        }
> >>+    }
> >>+
> >>+    return NULL;
> >>+}
> >>+
> >>  /*
> >>   * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
> >>   * Structure
> >>@@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
> >>  /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
> >>  #define NOTIFY_VALUE      0x99
> >
> >Again, please prefix everything consistently.
> 
> Okay, will do. Sorry for i missed it.
> 
> >
> >>
> >>+enum {
> >>+    DSM_FUN_IMPLEMENTED = 0,
> >>+
> >>+    /* NVDIMM Root Device Functions */
> >>+    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
> >>+    DSM_ROOT_DEV_FUN_ARS_START = 2,
> >>+    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
> >>+
> >>+    /* NVDIMM Device (non-root) Functions */
> >>+    DSM_DEV_FUN_SMART = 1,
> >>+    DSM_DEV_FUN_SMART_THRESHOLD = 2,
> >>+    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
> >>+    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
> >>+    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
> >>+    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
> >>+    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
> >>+    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
> >>+    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
> >>+};
> >
> >Does FUN stand for "function"? FUNC or FN is probably better.
> >
> 
> Yes.
> 
> >Please list exact names as they appear in spec so
> >they can be searched for.
> 
> The spec reference was at where this _FUN_ is used, eg:
> 
> /*
>  * Please refer to DSM specification 4.4.1 Get Namespace Label Size
>  * (Function Index 4).
>  *
>  * It gets the size of Namespace Label data area and the max data size
>  * that Get/Set Namespace Label Data functions can transfer.
>  */
> static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
> 
> I will follow your ‘single use’ comments below, these definitions will
> be dropped, the code will be like this:
> 
> switch (function) {
> case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:

If it's the same spec, you don't have to repeat it:

/* Encode function according to DSM Spec rev 1.0 */
> switch (function) {
>     case 4 /* 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:

same for chapter etc.

> nvdimm_dsm_func_label_size();
> case ...
> ...
> };
> 
> >
> >
> >
> >>+
> >>+enum {
> >>+    /* Common return status codes. */
> >>+    DSM_STATUS_SUCCESS = 0,                   /* Success */
> >>+    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
> >>+
> >>+    /* NVDIMM Root Device _DSM function return status codes*/
> >>+    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
> >>+    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
> >>+                                                        Error */
> >>+
> >>+    /* NVDIMM Device (non-root) _DSM function return status codes*/
> >>+    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
> >>+    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
> >>+    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
> >>+};
> >>+
> >>+/* Current revision supported by DSM specification is 1. */
> >>+#define DSM_REVISION        (1)
> >>+
> >>+/*
> >>+ * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
> >>+ * Value Information:
> >
> >Drop "please refer to".
> 
> Okay.
> 
> >
> >>+ *   if set to zero, no functions are supported (other than function zero)
> >>+ *   for the specified UUID and Revision ID. If set to one, at least one
> >>+ *   additional function is supported.
> >>+ */
> >>+
> >>+/* do not support any function on root. */
> >>+#define ROOT_SUPPORT_FUN     (0ULL)
> >
> >Needs a name that implies the comment somehow.
> >
> >>+#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
> >>+                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
> >>+                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
> >>+                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
> >>+
> >
> >I think it's best to just drop these macros.
> >There's a single point of use - just add a comment there
> >explaining what does it mean.
> 
> Okay. Good to me.
> 
> >You will be able to drop all _FUN_ macros too.
> 
> Yes, it's good for code reduction.
> 
> >
> >
> >>  struct dsm_in {
> >>      uint32_t handle;
> >>      uint32_t revision;
> >>@@ -420,6 +490,11 @@ struct dsm_in {
> >>  } QEMU_PACKED;
> >>  typedef struct dsm_in dsm_in;
> >>
> >>+struct cmd_out_implemented {
> >>+    uint64_t cmd_list;
> >>+};
> >>+typedef struct cmd_out_implemented cmd_out_implemented;
> >>+
> >>  struct dsm_out {
> >>      /* the size of buffer filled by QEMU. */
> >>      uint32_t len;
> >>@@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
> >>      return 0;
> >>  }
> >>
> >>+static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
> >>+{
> >>+    /* status locates in the first 4 bytes in the dsm memory. */
> >
> >located?
> 
> Yes...
> >
> >>+    assert(!out->len);
> >
> >
> >But dsm itself can be part of a bigger table.
> >So don't do it.
> 
> Okay, will drop it.
> 
> >
> >>+
> >>+    status = cpu_to_le32(status);
> >>+    g_array_append_vals(out, &status, sizeof(status));
> >
> >I think this should just use the (unfortunately named)
> >build_append_int_noprefix. Same applied everywhere
> >where you add single values.
> 
> Okay, will use it instead.
> 
> >
> >>+}
> >>+
> >>+static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
> >>+{
> >>+    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
> >>+
> >>+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> >>+    if (in->function == DSM_FUN_IMPLEMENTED) {
> >>+        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
> >
> >see about about single use values.
> >
> 
> Yes, it is good to me, will follow it.
> 
> >
> >>+
> >>+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> >>+        return;
> >>+    }
> >>+
> >>+    nvdimm_debug("Return status %#x.\n", status);
> >>+    nvdimm_dsm_write_status(out, status);
> >>+}
> >>+
> >>+static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
> >>+{
> >>+    GSList *list = nvdimm_get_plugged_device_list();
> >>+    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
> >>+    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
> >>+    uint64_t cmd_list;
> >>+
> >>+    if (!nvdimm) {
> >>+        goto set_status_free;
> >>+    }
> >>+
> >>+    switch (in->function) {
> >>+    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
> >>+    case DSM_FUN_IMPLEMENTED:
> >>+        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
> >>+        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
> >>+        goto free;
> >>+    default:
> >>+        status = DSM_STATUS_NOT_SUPPORTED;
> >>+    };
> >>+
> >>+set_status_free:
> >>+    nvdimm_debug("Return status %#x.\n", status);
> >>+    nvdimm_dsm_write_status(out, status);
> >>+free:
> >>+    g_slist_free(list);
> >>+}
> >>+
> >>  static void
> >>  nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> >>  {
> >>+    NVDIMMState *state = opaque;
> >>+    MemoryRegion *dsm_ram_mr;
> >>+    dsm_in *in;
> >>+    GArray *out;
> >>+    void *dsm_ram_addr;
> >
> >
> >Why don't you give this the correct type? Will avoid need for casts.
> 
> If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
> little strange.
> 
> I will do it as your suggestion, and make a comment for the copy operation:
> /*
>  * The DSM memory is used for both OSPM saves its input parameter and QEMU
>  * saves its output result.
>  */

Fix up the english here pls:
>  * The DSM memory has two uses: OSPM saves its input parameter there, QEMU
>  * uses it to save its output result.


> >
> >>+
> >>      if (val != NOTIFY_VALUE) {
> >>          fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
> >>      }
> >>+
> >>+    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
> >>+                                    getpagesize()).mr;
> >>+    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
> >
> >
> >This needs a validity check for size.
> 
> Okay, will add this:
> 
> assert(memory_region_size(dsm_ram_mr) == getpagesize());

No, the point is to make sure getpagesize is big enough to hold
the structure.

> >
> >>+
> >>+    /*
> >>+     * copy all input data to our local memory to avoid potential issue
> >>+     * as the dsm memory is visible to guest.
> >
> >this comment doesn't help.
> >pls replace "potential issue" with an explanation.
> 
> Okay, will change the comment to:
> /* As DSM memory is mapped to guest address space so that evil guest can change

s/As/The/
s/that evil/an evil/

>  * its content while we are doing DSM emulation. Avoid it by copying DSM memory

s/Avoid it/Avoid this/

>  * to QEMU local memory
>  */
> 
> >
> >>+     */
> >>+    in = g_malloc(memory_region_size(dsm_ram_mr));
> >>+    memcpy(in, dsm_ram_addr, memory_region_size(dsm_ram_mr));
> >>+
> >>+    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);
> >>+
> >>+    if (in->revision != DSM_REVISION) {
> >>+        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
> >>+                      in->revision, DSM_REVISION);
> >>+        nvdimm_dsm_write_status(out, DSM_STATUS_NOT_SUPPORTED);
> >>+        goto exit;
> >>+    }
> >>+
> >>+    /* Handle 0 is reserved for NVDIMM Root Device. */
> >>+    if (!in->handle) {
> >>+        nvdimm_dsm_write_root(in, out);
> >>+        goto exit;
> >>+    }
> >>+
> >>+    nvdimm_dsm_write_nvdimm(in, out);
> >>+
> >>+exit:
> >>+    /* Write our output result to dsm memory. */
> >>+    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >>+    memcpy(((dsm_out *)dsm_ram_addr)->data, out->data, out->len);
> >
> >This breaks migration as memory is not dirtied.
> >
> >address_space_write is generally preferable to change memory.
> 
> Good point, will fix.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19  4:04       ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-19  7:09         ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  7:09 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> >>Check if the input Arg3 is valid then store it into dsm_in if needed
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index 7e99889..b211b8b 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
> >>
> >>      method = aml_method_serialized("NCAL", 4);
> >>      {
> >>+        Aml *ifctx;
> >>+
> >>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
> >>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
> >>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
> >>
> >>+        /* Arg3 is passed as Package and it has one element? */
> >>+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> >>+                                         aml_int(4)),
> >>+                               aml_equal(aml_sizeof(aml_arg(3)),
> >>+                                         aml_int(1))));
> >>+        {
> >>+            /* Local0 = Index(Arg3, 0) */
> >>+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> >>+                                        aml_local(0)));
> >>+            /* Local3 = DeRefOf(Local0) */
> >>+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> >>+                                        aml_local(3)));
> >>+            /* ARG3 = Local3 */
> >>+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> >>+        }
> >>+        aml_append(method, ifctx);
> >>+
> >>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
> >>
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >
> >I commented on this patch on v3.
> >It doesn't look like this was addressed.
> >
> 
> Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
> device	_DSM method) on v3.
> 
> Do you mean we need more and better comment to explain arg3? Or anything else?
> 


I mean don't use ASL to comment C. It's not more readable.
Describe why the code is the way it is. Use variables by preference,
C does not have weird limitations like ASL so you don't need to call
your variables "arg3". What does it hold?


^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19  7:09         ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19  7:09 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/19/2015 01:16 AM, Michael S. Tsirkin wrote:
> >On Mon, Oct 19, 2015 at 08:54:13AM +0800, Xiao Guangrong wrote:
> >>Check if the input Arg3 is valid then store it into dsm_in if needed
> >>
> >>Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >>---
> >>  hw/acpi/nvdimm.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >>diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >>index 7e99889..b211b8b 100644
> >>--- a/hw/acpi/nvdimm.c
> >>+++ b/hw/acpi/nvdimm.c
> >>@@ -624,10 +624,29 @@ static void nvdimm_build_acpi_devices(NVDIMMState *state, GSList *device_list,
> >>
> >>      method = aml_method_serialized("NCAL", 4);
> >>      {
> >>+        Aml *ifctx;
> >>+
> >>          aml_append(method, aml_store(aml_arg(0), aml_name("HDLE")));
> >>          aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
> >>          aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
> >>
> >>+        /* Arg3 is passed as Package and it has one element? */
> >>+        ifctx = aml_if(aml_and(aml_equal(aml_object_type(aml_arg(3)),
> >>+                                         aml_int(4)),
> >>+                               aml_equal(aml_sizeof(aml_arg(3)),
> >>+                                         aml_int(1))));
> >>+        {
> >>+            /* Local0 = Index(Arg3, 0) */
> >>+            aml_append(ifctx, aml_store(aml_index(aml_arg(3), aml_int(0)),
> >>+                                        aml_local(0)));
> >>+            /* Local3 = DeRefOf(Local0) */
> >>+            aml_append(ifctx, aml_store(aml_derefof(aml_local(0)),
> >>+                                        aml_local(3)));
> >>+            /* ARG3 = Local3 */
> >>+            aml_append(ifctx, aml_store(aml_local(3), aml_name("ARG3")));
> >>+        }
> >>+        aml_append(method, ifctx);
> >>+
> >>          aml_append(method, aml_store(aml_int(NOTIFY_VALUE), aml_name("NOTI")));
> >>
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >
> >I commented on this patch on v3.
> >It doesn't look like this was addressed.
> >
> 
> Ah... I see no one commented this patch ([PATCH v3 26/32] nvdimm: save arg3 for NVDIMM
> device	_DSM method) on v3.
> 
> Do you mean we need more and better comment to explain arg3? Or anything else?
> 


I mean don't use ASL to comment C. It's not more readable.
Describe why the code is the way it is. Use variables by preference,
C does not have weird limitations like ASL so you don't need to call
your variables "arg3". What does it hold?

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-19  7:06         ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19  7:39           ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  7:39 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 10/19/2015 03:06 PM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 12:39:24PM +0800, Xiao Guangrong wrote:
>>
>>
>> On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
>>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>>> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
>>>>
>>>> Function 0 is a query function. We do not support any function on root
>>>> device and only 3 functions are support for NVDIMM device,
>>>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
>>>> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
>>>> access device's Label Namespace
>>>>
>>>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>>>> ---
>>>>   hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>>>   1 file changed, 182 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>>>> index b211b8b..37fea1c 100644
>>>> --- a/hw/acpi/nvdimm.c
>>>> +++ b/hw/acpi/nvdimm.c
>>>> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>>>>       return nvdimm_slot_to_spa_index(slot) + 1;
>>>>   }
>>>>
>>>> +static NVDIMMDevice
>>>> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
>>>> +{
>>>> +    for (; list; list = list->next) {
>>>> +        NVDIMMDevice *nvdimm = list->data;
>>>> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
>>>> +                                           NULL);
>>>> +
>>>> +        if (nvdimm_slot_to_handle(slot) == handle) {
>>>> +            return nvdimm;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    return NULL;
>>>> +}
>>>> +
>>>>   /*
>>>>    * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>>>>    * Structure
>>>> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>>>>   /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>>>>   #define NOTIFY_VALUE      0x99
>>>
>>> Again, please prefix everything consistently.
>>
>> Okay, will do. Sorry for i missed it.
>>
>>>
>>>>
>>>> +enum {
>>>> +    DSM_FUN_IMPLEMENTED = 0,
>>>> +
>>>> +    /* NVDIMM Root Device Functions */
>>>> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
>>>> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
>>>> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
>>>> +
>>>> +    /* NVDIMM Device (non-root) Functions */
>>>> +    DSM_DEV_FUN_SMART = 1,
>>>> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
>>>> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
>>>> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
>>>> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
>>>> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
>>>> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
>>>> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
>>>> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
>>>> +};
>>>
>>> Does FUN stand for "function"? FUNC or FN is probably better.
>>>
>>
>> Yes.
>>
>>> Please list exact names as they appear in spec so
>>> they can be searched for.
>>
>> The spec reference was at where this _FUN_ is used, eg:
>>
>> /*
>>   * Please refer to DSM specification 4.4.1 Get Namespace Label Size
>>   * (Function Index 4).
>>   *
>>   * It gets the size of Namespace Label data area and the max data size
>>   * that Get/Set Namespace Label Data functions can transfer.
>>   */
>> static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
>>
>> I will follow your ‘single use’ comments below, these definitions will
>> be dropped, the code will be like this:
>>
>> switch (function) {
>> case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
>
> If it's the same spec, you don't have to repeat it:
>
> /* Encode function according to DSM Spec rev 1.0 */
>> switch (function) {
>>      case 4 /* 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
>
> same for chapter etc.

Okay.

>
>> nvdimm_dsm_func_label_size();
>> case ...
>> ...
>> };
>>
>>>
>>>
>>>
>>>> +
>>>> +enum {
>>>> +    /* Common return status codes. */
>>>> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
>>>> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
>>>> +
>>>> +    /* NVDIMM Root Device _DSM function return status codes*/
>>>> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
>>>> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
>>>> +                                                        Error */
>>>> +
>>>> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
>>>> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
>>>> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
>>>> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
>>>> +};
>>>> +
>>>> +/* Current revision supported by DSM specification is 1. */
>>>> +#define DSM_REVISION        (1)
>>>> +
>>>> +/*
>>>> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
>>>> + * Value Information:
>>>
>>> Drop "please refer to".
>>
>> Okay.
>>
>>>
>>>> + *   if set to zero, no functions are supported (other than function zero)
>>>> + *   for the specified UUID and Revision ID. If set to one, at least one
>>>> + *   additional function is supported.
>>>> + */
>>>> +
>>>> +/* do not support any function on root. */
>>>> +#define ROOT_SUPPORT_FUN     (0ULL)
>>>
>>> Needs a name that implies the comment somehow.
>>>
>>>> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
>>>> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
>>>> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
>>>> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
>>>> +
>>>
>>> I think it's best to just drop these macros.
>>> There's a single point of use - just add a comment there
>>> explaining what does it mean.
>>
>> Okay. Good to me.
>>
>>> You will be able to drop all _FUN_ macros too.
>>
>> Yes, it's good for code reduction.
>>
>>>
>>>
>>>>   struct dsm_in {
>>>>       uint32_t handle;
>>>>       uint32_t revision;
>>>> @@ -420,6 +490,11 @@ struct dsm_in {
>>>>   } QEMU_PACKED;
>>>>   typedef struct dsm_in dsm_in;
>>>>
>>>> +struct cmd_out_implemented {
>>>> +    uint64_t cmd_list;
>>>> +};
>>>> +typedef struct cmd_out_implemented cmd_out_implemented;
>>>> +
>>>>   struct dsm_out {
>>>>       /* the size of buffer filled by QEMU. */
>>>>       uint32_t len;
>>>> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>>>>       return 0;
>>>>   }
>>>>
>>>> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
>>>> +{
>>>> +    /* status locates in the first 4 bytes in the dsm memory. */
>>>
>>> located?
>>
>> Yes...
>>>
>>>> +    assert(!out->len);
>>>
>>>
>>> But dsm itself can be part of a bigger table.
>>> So don't do it.
>>
>> Okay, will drop it.
>>
>>>
>>>> +
>>>> +    status = cpu_to_le32(status);
>>>> +    g_array_append_vals(out, &status, sizeof(status));
>>>
>>> I think this should just use the (unfortunately named)
>>> build_append_int_noprefix. Same applied everywhere
>>> where you add single values.
>>
>> Okay, will use it instead.
>>
>>>
>>>> +}
>>>> +
>>>> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
>>>> +{
>>>> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
>>>> +
>>>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>>>> +    if (in->function == DSM_FUN_IMPLEMENTED) {
>>>> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
>>>
>>> see about about single use values.
>>>
>>
>> Yes, it is good to me, will follow it.
>>
>>>
>>>> +
>>>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    nvdimm_debug("Return status %#x.\n", status);
>>>> +    nvdimm_dsm_write_status(out, status);
>>>> +}
>>>> +
>>>> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
>>>> +{
>>>> +    GSList *list = nvdimm_get_plugged_device_list();
>>>> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
>>>> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
>>>> +    uint64_t cmd_list;
>>>> +
>>>> +    if (!nvdimm) {
>>>> +        goto set_status_free;
>>>> +    }
>>>> +
>>>> +    switch (in->function) {
>>>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>>>> +    case DSM_FUN_IMPLEMENTED:
>>>> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
>>>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>>>> +        goto free;
>>>> +    default:
>>>> +        status = DSM_STATUS_NOT_SUPPORTED;
>>>> +    };
>>>> +
>>>> +set_status_free:
>>>> +    nvdimm_debug("Return status %#x.\n", status);
>>>> +    nvdimm_dsm_write_status(out, status);
>>>> +free:
>>>> +    g_slist_free(list);
>>>> +}
>>>> +
>>>>   static void
>>>>   nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>>>>   {
>>>> +    NVDIMMState *state = opaque;
>>>> +    MemoryRegion *dsm_ram_mr;
>>>> +    dsm_in *in;
>>>> +    GArray *out;
>>>> +    void *dsm_ram_addr;
>>>
>>>
>>> Why don't you give this the correct type? Will avoid need for casts.
>>
>> If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
>> little strange.
>>
>> I will do it as your suggestion, and make a comment for the copy operation:
>> /*
>>   * The DSM memory is used for both OSPM saves its input parameter and QEMU
>>   * saves its output result.
>>   */
>
> Fix up the english here pls:
>>   * The DSM memory has two uses: OSPM saves its input parameter there, QEMU
>>   * uses it to save its output result.
>

Sorry for my English, will fix.

>
>>>
>>>> +
>>>>       if (val != NOTIFY_VALUE) {
>>>>           fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>>>>       }
>>>> +
>>>> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
>>>> +                                    getpagesize()).mr;
>>>> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
>>>
>>>
>>> This needs a validity check for size.
>>
>> Okay, will add this:
>>
>> assert(memory_region_size(dsm_ram_mr) == getpagesize());
>
> No, the point is to make sure getpagesize is big enough to hold
> the structure.

Got it, will change it to:

/*
  * The DSM memory should be big enough to contain Input parameters and
  * output result.
  */
assert(memory_region_size(dsm_ram_mr) >= sizeof(dsm_in) &&
        memory_region_size(dsm_ram_mr) >= sizeof(dsm_out));

>
>>>
>>>> +
>>>> +    /*
>>>> +     * copy all input data to our local memory to avoid potential issue
>>>> +     * as the dsm memory is visible to guest.
>>>
>>> this comment doesn't help.
>>> pls replace "potential issue" with an explanation.
>>
>> Okay, will change the comment to:
>> /* As DSM memory is mapped to guest address space so that evil guest can change
>
> s/As/The/
> s/that evil/an evil/
>
>>   * its content while we are doing DSM emulation. Avoid it by copying DSM memory
>
> s/Avoid it/Avoid this/
>
>>   * to QEMU local memory
>>   */

Thanks for your fix.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-19  7:39           ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-19  7:39 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 10/19/2015 03:06 PM, Michael S. Tsirkin wrote:
> On Mon, Oct 19, 2015 at 12:39:24PM +0800, Xiao Guangrong wrote:
>>
>>
>> On 10/19/2015 02:05 AM, Michael S. Tsirkin wrote:
>>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>>> __DSM is defined in ACPI 6.0: 9.14.1 _DSM (Device Specific Method)
>>>>
>>>> Function 0 is a query function. We do not support any function on root
>>>> device and only 3 functions are support for NVDIMM device,
>>>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE, DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA and
>>>> DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA, that means we currently only allow to
>>>> access device's Label Namespace
>>>>
>>>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>>>> ---
>>>>   hw/acpi/nvdimm.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>>>   1 file changed, 182 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>>>> index b211b8b..37fea1c 100644
>>>> --- a/hw/acpi/nvdimm.c
>>>> +++ b/hw/acpi/nvdimm.c
>>>> @@ -260,6 +260,22 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
>>>>       return nvdimm_slot_to_spa_index(slot) + 1;
>>>>   }
>>>>
>>>> +static NVDIMMDevice
>>>> +*nvdimm_get_device_by_handle(GSList *list, uint32_t handle)
>>>> +{
>>>> +    for (; list; list = list->next) {
>>>> +        NVDIMMDevice *nvdimm = list->data;
>>>> +        int slot = object_property_get_int(OBJECT(nvdimm), DIMM_SLOT_PROP,
>>>> +                                           NULL);
>>>> +
>>>> +        if (nvdimm_slot_to_handle(slot) == handle) {
>>>> +            return nvdimm;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    return NULL;
>>>> +}
>>>> +
>>>>   /*
>>>>    * Please refer to ACPI 6.0: 5.2.25.1 System Physical Address Range
>>>>    * Structure
>>>> @@ -411,6 +427,60 @@ static void nvdimm_build_nfit(GArray *structures, GArray *table_offsets,
>>>>   /* detailed _DSM design please refer to docs/specs/acpi_nvdimm.txt */
>>>>   #define NOTIFY_VALUE      0x99
>>>
>>> Again, please prefix everything consistently.
>>
>> Okay, will do. Sorry for i missed it.
>>
>>>
>>>>
>>>> +enum {
>>>> +    DSM_FUN_IMPLEMENTED = 0,
>>>> +
>>>> +    /* NVDIMM Root Device Functions */
>>>> +    DSM_ROOT_DEV_FUN_ARS_CAP = 1,
>>>> +    DSM_ROOT_DEV_FUN_ARS_START = 2,
>>>> +    DSM_ROOT_DEV_FUN_ARS_QUERY = 3,
>>>> +
>>>> +    /* NVDIMM Device (non-root) Functions */
>>>> +    DSM_DEV_FUN_SMART = 1,
>>>> +    DSM_DEV_FUN_SMART_THRESHOLD = 2,
>>>> +    DSM_DEV_FUN_BLOCK_NVDIMM_FLAGS = 3,
>>>> +    DSM_DEV_FUN_NAMESPACE_LABEL_SIZE = 4,
>>>> +    DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA = 5,
>>>> +    DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA = 6,
>>>> +    DSM_DEV_FUN_VENDOR_EFFECT_LOG_SIZE = 7,
>>>> +    DSM_DEV_FUN_GET_VENDOR_EFFECT_LOG = 8,
>>>> +    DSM_DEV_FUN_VENDOR_SPECIFIC = 9,
>>>> +};
>>>
>>> Does FUN stand for "function"? FUNC or FN is probably better.
>>>
>>
>> Yes.
>>
>>> Please list exact names as they appear in spec so
>>> they can be searched for.
>>
>> The spec reference was at where this _FUN_ is used, eg:
>>
>> /*
>>   * Please refer to DSM specification 4.4.1 Get Namespace Label Size
>>   * (Function Index 4).
>>   *
>>   * It gets the size of Namespace Label data area and the max data size
>>   * that Get/Set Namespace Label Data functions can transfer.
>>   */
>> static void nvdimm_dsm_func_label_size(NVDIMMDevice *nvdimm, GArray *out)
>>
>> I will follow your ‘single use’ comments below, these definitions will
>> be dropped, the code will be like this:
>>
>> switch (function) {
>> case 4 /* DSM Spec 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
>
> If it's the same spec, you don't have to repeat it:
>
> /* Encode function according to DSM Spec rev 1.0 */
>> switch (function) {
>>      case 4 /* 4.4.1 Get Namespace Label Size Get Namespace Label Size. */:
>
> same for chapter etc.

Okay.

>
>> nvdimm_dsm_func_label_size();
>> case ...
>> ...
>> };
>>
>>>
>>>
>>>
>>>> +
>>>> +enum {
>>>> +    /* Common return status codes. */
>>>> +    DSM_STATUS_SUCCESS = 0,                   /* Success */
>>>> +    DSM_STATUS_NOT_SUPPORTED = 1,             /* Not Supported */
>>>> +
>>>> +    /* NVDIMM Root Device _DSM function return status codes*/
>>>> +    DSM_ROOT_DEV_STATUS_INVALID_PARAS = 2,    /* Invalid Input Parameters */
>>>> +    DSM_ROOT_DEV_STATUS_FUNCTION_SPECIFIC_ERROR = 3, /* Function-Specific
>>>> +                                                        Error */
>>>> +
>>>> +    /* NVDIMM Device (non-root) _DSM function return status codes*/
>>>> +    DSM_DEV_STATUS_NON_EXISTING_MEM_DEV = 2,  /* Non-Existing Memory Device */
>>>> +    DSM_DEV_STATUS_INVALID_PARAS = 3,         /* Invalid Input Parameters */
>>>> +    DSM_DEV_STATUS_VENDOR_SPECIFIC_ERROR = 4, /* Vendor Specific Error */
>>>> +};
>>>> +
>>>> +/* Current revision supported by DSM specification is 1. */
>>>> +#define DSM_REVISION        (1)
>>>> +
>>>> +/*
>>>> + * please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method): Return
>>>> + * Value Information:
>>>
>>> Drop "please refer to".
>>
>> Okay.
>>
>>>
>>>> + *   if set to zero, no functions are supported (other than function zero)
>>>> + *   for the specified UUID and Revision ID. If set to one, at least one
>>>> + *   additional function is supported.
>>>> + */
>>>> +
>>>> +/* do not support any function on root. */
>>>> +#define ROOT_SUPPORT_FUN     (0ULL)
>>>
>>> Needs a name that implies the comment somehow.
>>>
>>>> +#define DIMM_SUPPORT_FUN    ((1 << DSM_FUN_IMPLEMENTED)                   \
>>>> +                           | (1 << DSM_DEV_FUN_NAMESPACE_LABEL_SIZE)      \
>>>> +                           | (1 << DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA)  \
>>>> +                           | (1 << DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA))
>>>> +
>>>
>>> I think it's best to just drop these macros.
>>> There's a single point of use - just add a comment there
>>> explaining what does it mean.
>>
>> Okay. Good to me.
>>
>>> You will be able to drop all _FUN_ macros too.
>>
>> Yes, it's good for code reduction.
>>
>>>
>>>
>>>>   struct dsm_in {
>>>>       uint32_t handle;
>>>>       uint32_t revision;
>>>> @@ -420,6 +490,11 @@ struct dsm_in {
>>>>   } QEMU_PACKED;
>>>>   typedef struct dsm_in dsm_in;
>>>>
>>>> +struct cmd_out_implemented {
>>>> +    uint64_t cmd_list;
>>>> +};
>>>> +typedef struct cmd_out_implemented cmd_out_implemented;
>>>> +
>>>>   struct dsm_out {
>>>>       /* the size of buffer filled by QEMU. */
>>>>       uint32_t len;
>>>> @@ -434,12 +509,115 @@ nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
>>>>       return 0;
>>>>   }
>>>>
>>>> +static void nvdimm_dsm_write_status(GArray *out, uint32_t status)
>>>> +{
>>>> +    /* status locates in the first 4 bytes in the dsm memory. */
>>>
>>> located?
>>
>> Yes...
>>>
>>>> +    assert(!out->len);
>>>
>>>
>>> But dsm itself can be part of a bigger table.
>>> So don't do it.
>>
>> Okay, will drop it.
>>
>>>
>>>> +
>>>> +    status = cpu_to_le32(status);
>>>> +    g_array_append_vals(out, &status, sizeof(status));
>>>
>>> I think this should just use the (unfortunately named)
>>> build_append_int_noprefix. Same applied everywhere
>>> where you add single values.
>>
>> Okay, will use it instead.
>>
>>>
>>>> +}
>>>> +
>>>> +static void nvdimm_dsm_write_root(dsm_in *in, GArray *out)
>>>> +{
>>>> +    uint32_t status = DSM_STATUS_NOT_SUPPORTED;
>>>> +
>>>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>>>> +    if (in->function == DSM_FUN_IMPLEMENTED) {
>>>> +        uint64_t cmd_list = cpu_to_le64(ROOT_SUPPORT_FUN);
>>>
>>> see about about single use values.
>>>
>>
>> Yes, it is good to me, will follow it.
>>
>>>
>>>> +
>>>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    nvdimm_debug("Return status %#x.\n", status);
>>>> +    nvdimm_dsm_write_status(out, status);
>>>> +}
>>>> +
>>>> +static void nvdimm_dsm_write_nvdimm(dsm_in *in, GArray *out)
>>>> +{
>>>> +    GSList *list = nvdimm_get_plugged_device_list();
>>>> +    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(list, in->handle);
>>>> +    uint32_t status = DSM_DEV_STATUS_NON_EXISTING_MEM_DEV;
>>>> +    uint64_t cmd_list;
>>>> +
>>>> +    if (!nvdimm) {
>>>> +        goto set_status_free;
>>>> +    }
>>>> +
>>>> +    switch (in->function) {
>>>> +    /* please refer to ACPI 6.0: 9.14.1 _DSM (Device Specific Method) */
>>>> +    case DSM_FUN_IMPLEMENTED:
>>>> +        cmd_list = cpu_to_le64(DIMM_SUPPORT_FUN);
>>>> +        g_array_append_vals(out, &cmd_list, sizeof(cmd_list));
>>>> +        goto free;
>>>> +    default:
>>>> +        status = DSM_STATUS_NOT_SUPPORTED;
>>>> +    };
>>>> +
>>>> +set_status_free:
>>>> +    nvdimm_debug("Return status %#x.\n", status);
>>>> +    nvdimm_dsm_write_status(out, status);
>>>> +free:
>>>> +    g_slist_free(list);
>>>> +}
>>>> +
>>>>   static void
>>>>   nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>>>>   {
>>>> +    NVDIMMState *state = opaque;
>>>> +    MemoryRegion *dsm_ram_mr;
>>>> +    dsm_in *in;
>>>> +    GArray *out;
>>>> +    void *dsm_ram_addr;
>>>
>>>
>>> Why don't you give this the correct type? Will avoid need for casts.
>>
>> If it's defined as "dsm_out *", that will make "copy(in, dsm_ram_addr..)"
>> little strange.
>>
>> I will do it as your suggestion, and make a comment for the copy operation:
>> /*
>>   * The DSM memory is used for both OSPM saves its input parameter and QEMU
>>   * saves its output result.
>>   */
>
> Fix up the english here pls:
>>   * The DSM memory has two uses: OSPM saves its input parameter there, QEMU
>>   * uses it to save its output result.
>

Sorry for my English, will fix.

>
>>>
>>>> +
>>>>       if (val != NOTIFY_VALUE) {
>>>>           fprintf(stderr, "BUG: unexepected notify value 0x%" PRIx64, val);
>>>>       }
>>>> +
>>>> +    dsm_ram_mr = memory_region_find(&state->mr, getpagesize(),
>>>> +                                    getpagesize()).mr;
>>>> +    dsm_ram_addr = memory_region_get_ram_ptr(dsm_ram_mr);
>>>
>>>
>>> This needs a validity check for size.
>>
>> Okay, will add this:
>>
>> assert(memory_region_size(dsm_ram_mr) == getpagesize());
>
> No, the point is to make sure getpagesize is big enough to hold
> the structure.

Got it, will change it to:

/*
  * The DSM memory should be big enough to contain Input parameters and
  * output result.
  */
assert(memory_region_size(dsm_ram_mr) >= sizeof(dsm_in) &&
        memory_region_size(dsm_ram_mr) >= sizeof(dsm_out));

>
>>>
>>>> +
>>>> +    /*
>>>> +     * copy all input data to our local memory to avoid potential issue
>>>> +     * as the dsm memory is visible to guest.
>>>
>>> this comment doesn't help.
>>> pls replace "potential issue" with an explanation.
>>
>> Okay, will change the comment to:
>> /* As DSM memory is mapped to guest address space so that evil guest can change
>
> s/As/The/
> s/that evil/an evil/
>
>>   * its content while we are doing DSM emulation. Avoid it by copying DSM memory
>
> s/Avoid it/Avoid this/
>
>>   * to QEMU local memory
>>   */

Thanks for your fix.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19  7:09         ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19 17:29           ` Dan Williams
  -1 siblings, 0 replies; 112+ messages in thread
From: Dan Williams @ 2015-10-19 17:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Xiao Guangrong, Paolo Bonzini, imammedo, Gleb Natapov, mtosatti,
	stefanha, rth, ehabkost, KVM list, qemu-devel

On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> I mean don't use ASL to comment C. It's not more readable.
> Describe why the code is the way it is. Use variables by preference,
> C does not have weird limitations like ASL so you don't need to call
> your variables "arg3". What does it hold?
>

What it holds is function number specific.  It's similar to
SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
the OS through ACPI to a BIOS routine.  See the definition of the
example _DSM functions here and the usages of "Arg3":
http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19 17:29           ` Dan Williams
  0 siblings, 0 replies; 112+ messages in thread
From: Dan Williams @ 2015-10-19 17:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Xiao Guangrong, ehabkost, KVM list, Gleb Natapov, mtosatti,
	qemu-devel, stefanha, imammedo, Paolo Bonzini, rth

On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> I mean don't use ASL to comment C. It's not more readable.
> Describe why the code is the way it is. Use variables by preference,
> C does not have weird limitations like ASL so you don't need to call
> your variables "arg3". What does it hold?
>

What it holds is function number specific.  It's similar to
SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
the OS through ACPI to a BIOS routine.  See the definition of the
example _DSM functions here and the usages of "Arg3":
http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19 17:29           ` [Qemu-devel] " Dan Williams
@ 2015-10-19 21:19             ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19 21:19 UTC (permalink / raw)
  To: Dan Williams
  Cc: Xiao Guangrong, Paolo Bonzini, imammedo, Gleb Natapov, mtosatti,
	stefanha, rth, ehabkost, KVM list, qemu-devel

On Mon, Oct 19, 2015 at 10:29:50AM -0700, Dan Williams wrote:
> On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> > I mean don't use ASL to comment C. It's not more readable.
> > Describe why the code is the way it is. Use variables by preference,
> > C does not have weird limitations like ASL so you don't need to call
> > your variables "arg3". What does it hold?
> >
> 
> What it holds is function number specific.  It's similar to
> SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
> the OS through ACPI to a BIOS routine.  See the definition of the
> example _DSM functions here and the usages of "Arg3":
> http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf

So it seems to say "3.1.1.1.1 Input (Arg3)".
Is that right? So

Aml *input = aml_arg(3); /* Input (Arg3) */
or even
Aml *input_arg3 =  aml_arg(3); /* Input (Arg3) */

My point is we are not writing ASL. There is no reason
to use cryptic names.



^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19 21:19             ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-19 21:19 UTC (permalink / raw)
  To: Dan Williams
  Cc: Xiao Guangrong, ehabkost, KVM list, Gleb Natapov, mtosatti,
	qemu-devel, stefanha, imammedo, Paolo Bonzini, rth

On Mon, Oct 19, 2015 at 10:29:50AM -0700, Dan Williams wrote:
> On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
> > I mean don't use ASL to comment C. It's not more readable.
> > Describe why the code is the way it is. Use variables by preference,
> > C does not have weird limitations like ASL so you don't need to call
> > your variables "arg3". What does it hold?
> >
> 
> What it holds is function number specific.  It's similar to
> SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
> the OS through ACPI to a BIOS routine.  See the definition of the
> example _DSM functions here and the usages of "Arg3":
> http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf

So it seems to say "3.1.1.1.1 Input (Arg3)".
Is that right? So

Aml *input = aml_arg(3); /* Input (Arg3) */
or even
Aml *input_arg3 =  aml_arg(3); /* Input (Arg3) */

My point is we are not writing ASL. There is no reason
to use cryptic names.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
  2015-10-19 21:19             ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-10-19 21:29               ` Dan Williams
  -1 siblings, 0 replies; 112+ messages in thread
From: Dan Williams @ 2015-10-19 21:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Xiao Guangrong, Paolo Bonzini, imammedo, Gleb Natapov, mtosatti,
	stefanha, rth, ehabkost, KVM list, qemu-devel

On Mon, Oct 19, 2015 at 2:19 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Mon, Oct 19, 2015 at 10:29:50AM -0700, Dan Williams wrote:
>> On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
>> > I mean don't use ASL to comment C. It's not more readable.
>> > Describe why the code is the way it is. Use variables by preference,
>> > C does not have weird limitations like ASL so you don't need to call
>> > your variables "arg3". What does it hold?
>> >
>>
>> What it holds is function number specific.  It's similar to
>> SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
>> the OS through ACPI to a BIOS routine.  See the definition of the
>> example _DSM functions here and the usages of "Arg3":
>> http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
>
> So it seems to say "3.1.1.1.1 Input (Arg3)".
> Is that right? So
>
> Aml *input = aml_arg(3); /* Input (Arg3) */
> or even
> Aml *input_arg3 =  aml_arg(3); /* Input (Arg3) */
>
> My point is we are not writing ASL. There is no reason
> to use cryptic names.
>

Ah, ok, sounds good to me.  ASL is already hard to read and we
shouldn't be using it as code commentary.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method
@ 2015-10-19 21:29               ` Dan Williams
  0 siblings, 0 replies; 112+ messages in thread
From: Dan Williams @ 2015-10-19 21:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Xiao Guangrong, ehabkost, KVM list, Gleb Natapov, mtosatti,
	qemu-devel, stefanha, imammedo, Paolo Bonzini, rth

On Mon, Oct 19, 2015 at 2:19 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Mon, Oct 19, 2015 at 10:29:50AM -0700, Dan Williams wrote:
>> On Mon, Oct 19, 2015 at 12:09 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > On Mon, Oct 19, 2015 at 12:04:48PM +0800, Xiao Guangrong wrote:
>> > I mean don't use ASL to comment C. It's not more readable.
>> > Describe why the code is the way it is. Use variables by preference,
>> > C does not have weird limitations like ASL so you don't need to call
>> > your variables "arg3". What does it hold?
>> >
>>
>> What it holds is function number specific.  It's similar to
>> SYSCALL_DEFINEx where the ASL code is there to marshal arguments from
>> the OS through ACPI to a BIOS routine.  See the definition of the
>> example _DSM functions here and the usages of "Arg3":
>> http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
>
> So it seems to say "3.1.1.1.1 Input (Arg3)".
> Is that right? So
>
> Aml *input = aml_arg(3); /* Input (Arg3) */
> or even
> Aml *input_arg3 =  aml_arg(3); /* Input (Arg3) */
>
> My point is we are not writing ASL. There is no reason
> to use cryptic names.
>

Ah, ok, sounds good to me.  ASL is already hard to read and we
shouldn't be using it as code commentary.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-20 15:51     ` Stefan Hajnoczi
  -1 siblings, 0 replies; 112+ messages in thread
From: Stefan Hajnoczi @ 2015-10-20 15:51 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, mst, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> +exit:
> +    /* Write our output result to dsm memory. */
> +    ((dsm_out *)dsm_ram_addr)->len = out->len;

Missing byteswap?

I thought you were going to remove this field because it wasn't needed
by the guest.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-20 15:51     ` Stefan Hajnoczi
  0 siblings, 0 replies; 112+ messages in thread
From: Stefan Hajnoczi @ 2015-10-20 15:51 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth

On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> +exit:
> +    /* Write our output result to dsm memory. */
> +    ((dsm_out *)dsm_ram_addr)->len = out->len;

Missing byteswap?

I thought you were going to remove this field because it wasn't needed
by the guest.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-20 15:51     ` [Qemu-devel] " Stefan Hajnoczi
@ 2015-10-20 16:05       ` Michael S. Tsirkin
  -1 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-20 16:05 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Xiao Guangrong, ehabkost, kvm, gleb, mtosatti, qemu-devel,
	stefanha, imammedo, pbonzini, dan.j.williams, rth

On Tue, Oct 20, 2015 at 04:51:49PM +0100, Stefan Hajnoczi wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> > +exit:
> > +    /* Write our output result to dsm memory. */
> > +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> 
> Missing byteswap?


That's why I'd prefer no structures, using build_append_int_noprefix,
unless the structure is used outside ACPI as well.

> I thought you were going to remove this field because it wasn't needed
> by the guest.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-20 16:05       ` Michael S. Tsirkin
  0 siblings, 0 replies; 112+ messages in thread
From: Michael S. Tsirkin @ 2015-10-20 16:05 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Xiao Guangrong, ehabkost, kvm, gleb, mtosatti, qemu-devel,
	stefanha, imammedo, pbonzini, dan.j.williams, rth

On Tue, Oct 20, 2015 at 04:51:49PM +0100, Stefan Hajnoczi wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> > +exit:
> > +    /* Write our output result to dsm memory. */
> > +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> 
> Missing byteswap?


That's why I'd prefer no structures, using build_append_int_noprefix,
unless the structure is used outside ACPI as well.

> I thought you were going to remove this field because it wasn't needed
> by the guest.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-20 15:51     ` [Qemu-devel] " Stefan Hajnoczi
@ 2015-10-20 16:26       ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-20 16:26 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, mst, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>> +exit:
>> +    /* Write our output result to dsm memory. */
>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>
> Missing byteswap?
>
> I thought you were going to remove this field because it wasn't needed
> by the guest.
>

The @len is the size of _DSM result buffer, for example, for the function of
DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
how much size of memory we need to return to the _DSM caller.

In _DSM code, it's handled like this:

"RLEN" is @len, “OBUF” is the left memory in DSM page.

         /* get @len*/
         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
         /* @len << 3 to get bits. */
         aml_append(method, aml_store(aml_shiftleft(aml_local(6),
                                        aml_int(3)), aml_local(6)));

         /* get @len << 3 bits from OBUF, and return it to the caller. */
         aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
                                             aml_local(6) , "OBUF"));

Since @len is our internally used, it's not return to guest, so i did not do
byteswap here.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-20 16:26       ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-20 16:26 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth



On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>> +exit:
>> +    /* Write our output result to dsm memory. */
>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>
> Missing byteswap?
>
> I thought you were going to remove this field because it wasn't needed
> by the guest.
>

The @len is the size of _DSM result buffer, for example, for the function of
DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
how much size of memory we need to return to the _DSM caller.

In _DSM code, it's handled like this:

"RLEN" is @len, “OBUF” is the left memory in DSM page.

         /* get @len*/
         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
         /* @len << 3 to get bits. */
         aml_append(method, aml_store(aml_shiftleft(aml_local(6),
                                        aml_int(3)), aml_local(6)));

         /* get @len << 3 bits from OBUF, and return it to the caller. */
         aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
                                             aml_local(6) , "OBUF"));

Since @len is our internally used, it's not return to guest, so i did not do
byteswap here.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-20 16:26       ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-20 16:29         ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-20 16:29 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth



On 10/21/2015 12:26 AM, Xiao Guangrong wrote:
>
>
> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>> +exit:
>>> +    /* Write our output result to dsm memory. */
>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>>
>> Missing byteswap?
>>
>> I thought you were going to remove this field because it wasn't needed
>> by the guest.
>>
>
> The @len is the size of _DSM result buffer, for example, for the function of
> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code

Sorry, s/DSM_DEV_FUN_NAMESPACE_LABEL_SIZE/DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA

> how much size of memory we need to return to the _DSM caller.
>
> In _DSM code, it's handled like this:
>
> "RLEN" is @len, “OBUF” is the left memory in DSM page.
>
>          /* get @len*/
>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>          /* @len << 3 to get bits. */
>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>                                         aml_int(3)), aml_local(6)));
>
>          /* get @len << 3 bits from OBUF, and return it to the caller. */
>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>                                              aml_local(6) , "OBUF"));
>
> Since @len is our internally used, it's not return to guest, so i did not do
> byteswap here.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-20 16:29         ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-20 16:29 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth



On 10/21/2015 12:26 AM, Xiao Guangrong wrote:
>
>
> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>> +exit:
>>> +    /* Write our output result to dsm memory. */
>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>>
>> Missing byteswap?
>>
>> I thought you were going to remove this field because it wasn't needed
>> by the guest.
>>
>
> The @len is the size of _DSM result buffer, for example, for the function of
> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code

Sorry, s/DSM_DEV_FUN_NAMESPACE_LABEL_SIZE/DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA

> how much size of memory we need to return to the _DSM caller.
>
> In _DSM code, it's handled like this:
>
> "RLEN" is @len, “OBUF” is the left memory in DSM page.
>
>          /* get @len*/
>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>          /* @len << 3 to get bits. */
>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>                                         aml_int(3)), aml_local(6)));
>
>          /* get @len << 3 bits from OBUF, and return it to the caller. */
>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>                                              aml_local(6) , "OBUF"));
>
> Since @len is our internally used, it's not return to guest, so i did not do
> byteswap here.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-20 16:26       ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-21 10:49         ` Stefan Hajnoczi
  -1 siblings, 0 replies; 112+ messages in thread
From: Stefan Hajnoczi @ 2015-10-21 10:49 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Stefan Hajnoczi, pbonzini, imammedo, gleb, mtosatti, mst, rth,
	ehabkost, dan.j.williams, kvm, qemu-devel

On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> >On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>+exit:
> >>+    /* Write our output result to dsm memory. */
> >>+    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >
> >Missing byteswap?
> >
> >I thought you were going to remove this field because it wasn't needed
> >by the guest.
> >
> 
> The @len is the size of _DSM result buffer, for example, for the function of
> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
> how much size of memory we need to return to the _DSM caller.
> 
> In _DSM code, it's handled like this:
> 
> "RLEN" is @len, “OBUF” is the left memory in DSM page.
> 
>         /* get @len*/
>         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>         /* @len << 3 to get bits. */
>         aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>                                        aml_int(3)), aml_local(6)));
> 
>         /* get @len << 3 bits from OBUF, and return it to the caller. */
>         aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>                                             aml_local(6) , "OBUF"));
> 
> Since @len is our internally used, it's not return to guest, so i did not do
> byteswap here.

I am not familiar with the ACPI details, but I think this emits bytecode
that will be run by the guest's ACPI interpreter?

You still need to define the endianness of fields since QEMU and the
guest could have different endianness.

In other words, will the following work if a big-endian ppc host is
running a little-endian x86 guest?

  ((dsm_out *)dsm_ram_addr)->len = out->len;

Stefan

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-21 10:49         ` Stefan Hajnoczi
  0 siblings, 0 replies; 112+ messages in thread
From: Stefan Hajnoczi @ 2015-10-21 10:49 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, mst, gleb, Stefan Hajnoczi, mtosatti, qemu-devel,
	pbonzini, imammedo, dan.j.williams, rth

On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
> 
> 
> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> >On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>+exit:
> >>+    /* Write our output result to dsm memory. */
> >>+    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >
> >Missing byteswap?
> >
> >I thought you were going to remove this field because it wasn't needed
> >by the guest.
> >
> 
> The @len is the size of _DSM result buffer, for example, for the function of
> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
> how much size of memory we need to return to the _DSM caller.
> 
> In _DSM code, it's handled like this:
> 
> "RLEN" is @len, “OBUF” is the left memory in DSM page.
> 
>         /* get @len*/
>         aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>         /* @len << 3 to get bits. */
>         aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>                                        aml_int(3)), aml_local(6)));
> 
>         /* get @len << 3 bits from OBUF, and return it to the caller. */
>         aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>                                             aml_local(6) , "OBUF"));
> 
> Since @len is our internally used, it's not return to guest, so i did not do
> byteswap here.

I am not familiar with the ACPI details, but I think this emits bytecode
that will be run by the guest's ACPI interpreter?

You still need to define the endianness of fields since QEMU and the
guest could have different endianness.

In other words, will the following work if a big-endian ppc host is
running a little-endian x86 guest?

  ((dsm_out *)dsm_ram_addr)->len = out->len;

Stefan

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-21 10:49         ` [Qemu-devel] " Stefan Hajnoczi
@ 2015-10-21 13:32           ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-21 13:32 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Stefan Hajnoczi, pbonzini, imammedo, gleb, mtosatti, mst, rth,
	ehabkost, dan.j.williams, kvm, qemu-devel



On 10/21/2015 06:49 PM, Stefan Hajnoczi wrote:
> On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
>>
>>
>> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
>>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>>> +exit:
>>>> +    /* Write our output result to dsm memory. */
>>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>>>
>>> Missing byteswap?
>>>
>>> I thought you were going to remove this field because it wasn't needed
>>> by the guest.
>>>
>>
>> The @len is the size of _DSM result buffer, for example, for the function of
>> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
>> how much size of memory we need to return to the _DSM caller.
>>
>> In _DSM code, it's handled like this:
>>
>> "RLEN" is @len, “OBUF” is the left memory in DSM page.
>>
>>          /* get @len*/
>>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>>          /* @len << 3 to get bits. */
>>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>>                                         aml_int(3)), aml_local(6)));
>>
>>          /* get @len << 3 bits from OBUF, and return it to the caller. */
>>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>>                                              aml_local(6) , "OBUF"));
>>
>> Since @len is our internally used, it's not return to guest, so i did not do
>> byteswap here.
>
> I am not familiar with the ACPI details, but I think this emits bytecode
> that will be run by the guest's ACPI interpreter?
>
> You still need to define the endianness of fields since QEMU and the
> guest could have different endianness.
>
> In other words, will the following work if a big-endian ppc host is
> running a little-endian x86 guest?
>
>    ((dsm_out *)dsm_ram_addr)->len = out->len;
>

Er... If we do byteswap in QEMU then it is also needed in ASL code, however,
ASL lacks this kind of instruction.  I guess ACPI interpreter is smart enough
to change value to Littel-Endian for all 2 bytes / 4 bytes / 8 bytes accesses

I will do the change in next version, thanks for you pointing it out, Stefan!


^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-21 13:32           ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-21 13:32 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: ehabkost, kvm, mst, gleb, Stefan Hajnoczi, mtosatti, qemu-devel,
	pbonzini, imammedo, dan.j.williams, rth



On 10/21/2015 06:49 PM, Stefan Hajnoczi wrote:
> On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
>>
>>
>> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
>>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
>>>> +exit:
>>>> +    /* Write our output result to dsm memory. */
>>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
>>>
>>> Missing byteswap?
>>>
>>> I thought you were going to remove this field because it wasn't needed
>>> by the guest.
>>>
>>
>> The @len is the size of _DSM result buffer, for example, for the function of
>> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
>> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
>> how much size of memory we need to return to the _DSM caller.
>>
>> In _DSM code, it's handled like this:
>>
>> "RLEN" is @len, “OBUF” is the left memory in DSM page.
>>
>>          /* get @len*/
>>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
>>          /* @len << 3 to get bits. */
>>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
>>                                         aml_int(3)), aml_local(6)));
>>
>>          /* get @len << 3 bits from OBUF, and return it to the caller. */
>>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
>>                                              aml_local(6) , "OBUF"));
>>
>> Since @len is our internally used, it's not return to guest, so i did not do
>> byteswap here.
>
> I am not familiar with the ACPI details, but I think this emits bytecode
> that will be run by the guest's ACPI interpreter?
>
> You still need to define the endianness of fields since QEMU and the
> guest could have different endianness.
>
> In other words, will the following work if a big-endian ppc host is
> running a little-endian x86 guest?
>
>    ((dsm_out *)dsm_ram_addr)->len = out->len;
>

Er... If we do byteswap in QEMU then it is also needed in ASL code, however,
ASL lacks this kind of instruction.  I guess ACPI interpreter is smart enough
to change value to Littel-Endian for all 2 bytes / 4 bytes / 8 bytes accesses

I will do the change in next version, thanks for you pointing it out, Stefan!

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
  2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-24  3:20     ` Bharata B Rao
  -1 siblings, 0 replies; 112+ messages in thread
From: Bharata B Rao @ 2015-10-24  3:20 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Paolo Bonzini, Igor Mammedov, gleb, mtosatti, Stefan Hajnoczi,
	mst, Richard Henderson, Eduardo Habkost, dan.j.williams, kvm,
	qemu-devel

On Mon, Oct 19, 2015 at 6:24 AM, Xiao Guangrong
<guangrong.xiao@linux.intel.com> wrote:
> A base device, dimm, is abstracted from pc-dimm, so that we can
> build nvdimm device based on dimm in the later patch
>
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  default-configs/i386-softmmu.mak   |  1 +
>  default-configs/x86_64-softmmu.mak |  1 +
>  hw/mem/Makefile.objs               |  3 ++-
>  hw/mem/dimm.c                      | 11 ++-------
>  hw/mem/pc-dimm.c                   | 46 ++++++++++++++++++++++++++++++++++++++
>  include/hw/mem/dimm.h              |  4 ++--
>  include/hw/mem/pc-dimm.h           |  7 ++++++
>  7 files changed, 61 insertions(+), 12 deletions(-)
>  create mode 100644 hw/mem/pc-dimm.c
>  create mode 100644 include/hw/mem/pc-dimm.h
>
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 43c96d1..3ece8bb 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -18,6 +18,7 @@ CONFIG_FDC=y
>  CONFIG_ACPI=y
>  CONFIG_ACPI_X86=y
>  CONFIG_ACPI_X86_ICH=y
> +CONFIG_DIMM=y
>  CONFIG_ACPI_MEMORY_HOTPLUG=y
>  CONFIG_ACPI_CPU_HOTPLUG=y
>  CONFIG_APM=y
> diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
> index dfb8095..92ea7c1 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -18,6 +18,7 @@ CONFIG_FDC=y
>  CONFIG_ACPI=y
>  CONFIG_ACPI_X86=y
>  CONFIG_ACPI_X86_ICH=y
> +CONFIG_DIMM=y

Same change needs to be done in default-configs/ppc64-softmmu.mak too.

Regards,
Bharata.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
@ 2015-10-24  3:20     ` Bharata B Rao
  0 siblings, 0 replies; 112+ messages in thread
From: Bharata B Rao @ 2015-10-24  3:20 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Eduardo Habkost, kvm, mst, gleb, mtosatti, qemu-devel,
	Stefan Hajnoczi, Igor Mammedov, Paolo Bonzini, dan.j.williams,
	Richard Henderson

On Mon, Oct 19, 2015 at 6:24 AM, Xiao Guangrong
<guangrong.xiao@linux.intel.com> wrote:
> A base device, dimm, is abstracted from pc-dimm, so that we can
> build nvdimm device based on dimm in the later patch
>
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  default-configs/i386-softmmu.mak   |  1 +
>  default-configs/x86_64-softmmu.mak |  1 +
>  hw/mem/Makefile.objs               |  3 ++-
>  hw/mem/dimm.c                      | 11 ++-------
>  hw/mem/pc-dimm.c                   | 46 ++++++++++++++++++++++++++++++++++++++
>  include/hw/mem/dimm.h              |  4 ++--
>  include/hw/mem/pc-dimm.h           |  7 ++++++
>  7 files changed, 61 insertions(+), 12 deletions(-)
>  create mode 100644 hw/mem/pc-dimm.c
>  create mode 100644 include/hw/mem/pc-dimm.h
>
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 43c96d1..3ece8bb 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -18,6 +18,7 @@ CONFIG_FDC=y
>  CONFIG_ACPI=y
>  CONFIG_ACPI_X86=y
>  CONFIG_ACPI_X86_ICH=y
> +CONFIG_DIMM=y
>  CONFIG_ACPI_MEMORY_HOTPLUG=y
>  CONFIG_ACPI_CPU_HOTPLUG=y
>  CONFIG_APM=y
> diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
> index dfb8095..92ea7c1 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -18,6 +18,7 @@ CONFIG_FDC=y
>  CONFIG_ACPI=y
>  CONFIG_ACPI_X86=y
>  CONFIG_ACPI_X86_ICH=y
> +CONFIG_DIMM=y

Same change needs to be done in default-configs/ppc64-softmmu.mak too.

Regards,
Bharata.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
  2015-10-24  3:20     ` [Qemu-devel] " Bharata B Rao
@ 2015-10-28 14:31       ` Xiao Guangrong
  -1 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-28 14:31 UTC (permalink / raw)
  To: Bharata B Rao
  Cc: Paolo Bonzini, Igor Mammedov, gleb, mtosatti, Stefan Hajnoczi,
	mst, Richard Henderson, Eduardo Habkost, dan.j.williams, kvm,
	qemu-devel



On 10/24/2015 11:20 AM, Bharata B Rao wrote:

>>   CONFIG_ACPI_X86_ICH=y
>> +CONFIG_DIMM=y
>
> Same change needs to be done in default-configs/ppc64-softmmu.mak too.

I have fixed it in v5 which cat be found at:
    http://marc.info/?l=kvm&m=144604272221080&w=2

Bharata, thank you very much for your review.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm
@ 2015-10-28 14:31       ` Xiao Guangrong
  0 siblings, 0 replies; 112+ messages in thread
From: Xiao Guangrong @ 2015-10-28 14:31 UTC (permalink / raw)
  To: Bharata B Rao
  Cc: Eduardo Habkost, kvm, mst, gleb, mtosatti, qemu-devel,
	Stefan Hajnoczi, Igor Mammedov, Paolo Bonzini, dan.j.williams,
	Richard Henderson



On 10/24/2015 11:20 AM, Bharata B Rao wrote:

>>   CONFIG_ACPI_X86_ICH=y
>> +CONFIG_DIMM=y
>
> Same change needs to be done in default-configs/ppc64-softmmu.mak too.

I have fixed it in v5 which cat be found at:
    http://marc.info/?l=kvm&m=144604272221080&w=2

Bharata, thank you very much for your review.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
  2015-10-21 13:32           ` [Qemu-devel] " Xiao Guangrong
@ 2015-10-29 14:36             ` Igor Mammedov
  -1 siblings, 0 replies; 112+ messages in thread
From: Igor Mammedov @ 2015-10-29 14:36 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Stefan Hajnoczi, Stefan Hajnoczi, pbonzini, gleb, mtosatti, mst,
	rth, ehabkost, dan.j.williams, kvm, qemu-devel

On Wed, 21 Oct 2015 21:32:38 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> 
> 
> On 10/21/2015 06:49 PM, Stefan Hajnoczi wrote:
> > On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
> >>
> >>
> >> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> >>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>>> +exit:
> >>>> +    /* Write our output result to dsm memory. */
> >>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >>>
> >>> Missing byteswap?
> >>>
> >>> I thought you were going to remove this field because it wasn't needed
> >>> by the guest.
> >>>
> >>
> >> The @len is the size of _DSM result buffer, for example, for the function of
> >> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> >> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
> >> how much size of memory we need to return to the _DSM caller.
> >>
> >> In _DSM code, it's handled like this:
> >>
> >> "RLEN" is @len, “OBUF” is the left memory in DSM page.
> >>
> >>          /* get @len*/
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >>          /* @len << 3 to get bits. */
> >>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
> >>                                         aml_int(3)), aml_local(6)));
> >>
> >>          /* get @len << 3 bits from OBUF, and return it to the caller. */
> >>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
> >>                                              aml_local(6) , "OBUF"));
> >>
> >> Since @len is our internally used, it's not return to guest, so i did not do
> >> byteswap here.
> >
> > I am not familiar with the ACPI details, but I think this emits bytecode
> > that will be run by the guest's ACPI interpreter?
> >
> > You still need to define the endianness of fields since QEMU and the
> > guest could have different endianness.
> >
> > In other words, will the following work if a big-endian ppc host is
> > running a little-endian x86 guest?
> >
> >    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >
> 
> Er... If we do byteswap in QEMU then it is also needed in ASL code, however,
> ASL lacks this kind of instruction.  I guess ACPI interpreter is smart enough
> to change value to Littel-Endian for all 2 bytes / 4 bytes / 8 bytes accesses
> 
> I will do the change in next version, thanks for you pointing it out, Stefan!
According to ACPI spec integers encoded as little endian,
so QEMU needs to convert fields accessible by OSPM to it
(i.e. do cpu_to_le())

> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [Qemu-devel] [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function
@ 2015-10-29 14:36             ` Igor Mammedov
  0 siblings, 0 replies; 112+ messages in thread
From: Igor Mammedov @ 2015-10-29 14:36 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, mst, gleb, Stefan Hajnoczi, mtosatti, qemu-devel,
	Stefan Hajnoczi, pbonzini, dan.j.williams, rth

On Wed, 21 Oct 2015 21:32:38 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> 
> 
> On 10/21/2015 06:49 PM, Stefan Hajnoczi wrote:
> > On Wed, Oct 21, 2015 at 12:26:35AM +0800, Xiao Guangrong wrote:
> >>
> >>
> >> On 10/20/2015 11:51 PM, Stefan Hajnoczi wrote:
> >>> On Mon, Oct 19, 2015 at 08:54:14AM +0800, Xiao Guangrong wrote:
> >>>> +exit:
> >>>> +    /* Write our output result to dsm memory. */
> >>>> +    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >>>
> >>> Missing byteswap?
> >>>
> >>> I thought you were going to remove this field because it wasn't needed
> >>> by the guest.
> >>>
> >>
> >> The @len is the size of _DSM result buffer, for example, for the function of
> >> DSM_FUN_IMPLEMENTED the result buffer is 8 bytes, and for
> >> DSM_DEV_FUN_NAMESPACE_LABEL_SIZE the buffer size is 4 bytes. It tells ASL code
> >> how much size of memory we need to return to the _DSM caller.
> >>
> >> In _DSM code, it's handled like this:
> >>
> >> "RLEN" is @len, “OBUF” is the left memory in DSM page.
> >>
> >>          /* get @len*/
> >>          aml_append(method, aml_store(aml_name("RLEN"), aml_local(6)));
> >>          /* @len << 3 to get bits. */
> >>          aml_append(method, aml_store(aml_shiftleft(aml_local(6),
> >>                                         aml_int(3)), aml_local(6)));
> >>
> >>          /* get @len << 3 bits from OBUF, and return it to the caller. */
> >>          aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
> >>                                              aml_local(6) , "OBUF"));
> >>
> >> Since @len is our internally used, it's not return to guest, so i did not do
> >> byteswap here.
> >
> > I am not familiar with the ACPI details, but I think this emits bytecode
> > that will be run by the guest's ACPI interpreter?
> >
> > You still need to define the endianness of fields since QEMU and the
> > guest could have different endianness.
> >
> > In other words, will the following work if a big-endian ppc host is
> > running a little-endian x86 guest?
> >
> >    ((dsm_out *)dsm_ram_addr)->len = out->len;
> >
> 
> Er... If we do byteswap in QEMU then it is also needed in ASL code, however,
> ASL lacks this kind of instruction.  I guess ACPI interpreter is smart enough
> to change value to Littel-Endian for all 2 bytes / 4 bytes / 8 bytes accesses
> 
> I will do the change in next version, thanks for you pointing it out, Stefan!
According to ACPI spec integers encoded as little endian,
so QEMU needs to convert fields accessible by OSPM to it
(i.e. do cpu_to_le())

> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 112+ messages in thread

end of thread, other threads:[~2015-10-29 14:36 UTC | newest]

Thread overview: 112+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-19  0:53 [PATCH v4 00/33] implement vNVDIMM Xiao Guangrong
2015-10-19  0:53 ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 01/33] acpi: add aml_derefof Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 02/33] acpi: add aml_sizeof Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 03/33] acpi: add aml_create_field Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 04/33] acpi: add aml_concatenate Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 05/33] acpi: add aml_object_type Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 06/33] acpi: add aml_method_serialized Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 07/33] util: introduce qemu_file_get_page_size() Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 08/33] exec: allow memory to be allocated from any kind of path Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 09/33] exec: allow file_ram_alloc to work on file Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 10/33] hostmem-file: clean up memory allocation Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 11/33] hostmem-file: use whole file size if possible Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 12/33] pc-dimm: remove DEFAULT_PC_DIMMSIZE Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:53 ` [PATCH v4 13/33] pc-dimm: make pc_existing_dimms_capacity static and rename it Xiao Guangrong
2015-10-19  0:53   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 14/33] pc-dimm: drop the prefix of pc-dimm Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 15/33] stubs: rename qmp_pc_dimm_device_list.c Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 16/33] pc-dimm: rename pc-dimm.c and pc-dimm.h Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 17/33] dimm: abstract dimm device from pc-dimm Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-24  3:20   ` Bharata B Rao
2015-10-24  3:20     ` [Qemu-devel] " Bharata B Rao
2015-10-28 14:31     ` Xiao Guangrong
2015-10-28 14:31       ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 18/33] dimm: get mapped memory region from DIMMDeviceClass->get_memory_region Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 19/33] dimm: keep the state of the whole backend memory Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 20/33] dimm: introduce realize callback Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 21/33] nvdimm: implement NVDIMM device abstract Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 22/33] docs: add NVDIMM ACPI documentation Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 23/33] nvdimm acpi: init the address region used by NVDIMM ACPI Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-18 17:15   ` Michael S. Tsirkin
2015-10-18 17:15     ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19  3:58     ` Xiao Guangrong
2015-10-19  3:58       ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 24/33] nvdimm acpi: build ACPI NFIT table Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 25/33] nvdimm acpi: init the address region used by DSM Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 26/33] nvdimm acpi: build ACPI nvdimm devices Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 27/33] nvdimm acpi: save arg3 for NVDIMM device _DSM method Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-18 17:16   ` Michael S. Tsirkin
2015-10-18 17:16     ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19  4:04     ` Xiao Guangrong
2015-10-19  4:04       ` [Qemu-devel] " Xiao Guangrong
2015-10-19  6:57       ` Michael S. Tsirkin
2015-10-19  6:57         ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19  7:09       ` Michael S. Tsirkin
2015-10-19  7:09         ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19 17:29         ` Dan Williams
2015-10-19 17:29           ` [Qemu-devel] " Dan Williams
2015-10-19 21:19           ` Michael S. Tsirkin
2015-10-19 21:19             ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19 21:29             ` Dan Williams
2015-10-19 21:29               ` [Qemu-devel] " Dan Williams
2015-10-19  0:54 ` [PATCH v4 28/33] nvdimm acpi: support DSM_FUN_IMPLEMENTED function Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-18 18:05   ` Michael S. Tsirkin
2015-10-18 18:05     ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19  4:39     ` Xiao Guangrong
2015-10-19  4:39       ` [Qemu-devel] " Xiao Guangrong
2015-10-19  7:06       ` Michael S. Tsirkin
2015-10-19  7:06         ` [Qemu-devel] " Michael S. Tsirkin
2015-10-19  7:39         ` Xiao Guangrong
2015-10-19  7:39           ` [Qemu-devel] " Xiao Guangrong
2015-10-20 15:51   ` Stefan Hajnoczi
2015-10-20 15:51     ` [Qemu-devel] " Stefan Hajnoczi
2015-10-20 16:05     ` Michael S. Tsirkin
2015-10-20 16:05       ` [Qemu-devel] " Michael S. Tsirkin
2015-10-20 16:26     ` Xiao Guangrong
2015-10-20 16:26       ` [Qemu-devel] " Xiao Guangrong
2015-10-20 16:29       ` Xiao Guangrong
2015-10-20 16:29         ` [Qemu-devel] " Xiao Guangrong
2015-10-21 10:49       ` Stefan Hajnoczi
2015-10-21 10:49         ` [Qemu-devel] " Stefan Hajnoczi
2015-10-21 13:32         ` Xiao Guangrong
2015-10-21 13:32           ` [Qemu-devel] " Xiao Guangrong
2015-10-29 14:36           ` Igor Mammedov
2015-10-29 14:36             ` [Qemu-devel] " Igor Mammedov
2015-10-19  0:54 ` [PATCH v4 29/33] nvdimm acpi: support DSM_DEV_FUN_NAMESPACE_LABEL_SIZE function Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 30/33] nvdimm acpi: support DSM_DEV_FUN_GET_NAMESPACE_LABEL_DATA Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 31/33] nvdimm acpi: support DSM_DEV_FUN_SET_NAMESPACE_LABEL_DATA Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 32/33] nvdimm: allow using whole backend memory as pmem Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong
2015-10-19  0:54 ` [PATCH v4 33/33] nvdimm: add maintain info Xiao Guangrong
2015-10-19  0:54   ` [Qemu-devel] " Xiao Guangrong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.