All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-16 10:50 ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:50 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-v8

It is based on pci branch on Michael's tree and the top commit is:
commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).

Changelog in v8:
We split the long patch series into the small parts, as you see now, this
is the first part which enables NVDIMM without label data support.

The command line has been changed because some patches simplifying the
things have not been included into this series, you should specify the
file size exactly using the parameters as follows:
   memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
   -device nvdimm,memdev=mem1,id=nv1

Changelog in v7:
- changes from Vladimir Sementsov-Ogievskiy's comments:
  1) let gethugepagesize() realize if fstat is failed instead of get
     normal page size
  2) rename  open_file_path to open_ram_file_path
  3) better log the error message by using error_setg_errno
  4) update commit in the commit log to explain hugepage detection on
     Windows

- changes from Eduardo Habkost's comments:
  1) use 'Error**' to collect error message for qemu_file_get_page_size()
  2) move gethugepagesize() replacement to the same patch to make it
     better for review
  3) introduce qemu_get_file_size to unity the code with raw_getlength()

- changes from Stefan's comments:
  1) check the memory region is large enough to contain DSM output
     buffer

- changes from Eric Blake's comments:
  1) update the shell command in the commit log to generate the patch
     which drops 'pc-dimm' prefix
  
- others:
  pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
  Eric Blake.

Changelog in v6:
- changes from Stefan's comments:
  1) fix code style of struct naming by CamelCase way
  2) fix offset + length overflow when read/write label data
  3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
     be used to replace getpagesize()

Changelog in v5:
- changes from Michael's comments:
  1) prefix nvdimm_ to everything in NVDIMM source files
  2) make parsing _DSM Arg3 more clear
  3) comment style fix
  5) drop single used definition
  6) fix dirty dsm buffer lost due to memory write happened on host
  7) check dsm buffer if it is big enough to contain input data
  8) use build_append_int_noprefix to store single value to GArray

- changes from Michael's and Igor's comments:
  1) introduce 'nvdimm-support' parameter to control nvdimm
     enablement and it is disabled for 2.4 and its earlier versions
     to make live migration compatible
  2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
     virtualization

- changes from Stefan's comments:
  1) do endian adjustment for the buffer length

- changes from Bharata B Rao's comments:
  1) fix compile on ppc

- others:
  1) the buffer length is directly got from IO read rather than got
     from dsm memory
  2) fix dirty label data lost due to memory write happened on host

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 (5):
  nvdimm: implement NVDIMM device abstract
  acpi: support specified oem table id for build_header
  nvdimm acpi: build ACPI NFIT table
  nvdimm acpi: build ACPI nvdimm devices
  nvdimm: add maintain info

 MAINTAINERS                        |   7 +
 default-configs/i386-softmmu.mak   |   2 +
 default-configs/x86_64-softmmu.mak |   2 +
 hw/acpi/Makefile.objs              |   1 +
 hw/acpi/aml-build.c                |  15 +-
 hw/acpi/ich9.c                     |  19 ++
 hw/acpi/memory_hotplug.c           |   5 +
 hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
 hw/acpi/piix4.c                    |   4 +
 hw/arm/virt-acpi-build.c           |  13 +-
 hw/i386/acpi-build.c               |  26 ++-
 hw/mem/Makefile.objs               |   1 +
 hw/mem/nvdimm.c                    |  46 ++++
 include/hw/acpi/aml-build.h        |   3 +-
 include/hw/acpi/ich9.h             |   3 +
 include/hw/i386/pc.h               |  12 +-
 include/hw/mem/nvdimm.h            |  41 ++++
 17 files changed, 645 insertions(+), 22 deletions(-)
 create mode 100644 hw/acpi/nvdimm.c
 create mode 100644 hw/mem/nvdimm.c
 create mode 100644 include/hw/mem/nvdimm.h

-- 
1.8.3.1


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

* [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-16 10:50 ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:50 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-v8

It is based on pci branch on Michael's tree and the top commit is:
commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).

Changelog in v8:
We split the long patch series into the small parts, as you see now, this
is the first part which enables NVDIMM without label data support.

The command line has been changed because some patches simplifying the
things have not been included into this series, you should specify the
file size exactly using the parameters as follows:
   memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
   -device nvdimm,memdev=mem1,id=nv1

Changelog in v7:
- changes from Vladimir Sementsov-Ogievskiy's comments:
  1) let gethugepagesize() realize if fstat is failed instead of get
     normal page size
  2) rename  open_file_path to open_ram_file_path
  3) better log the error message by using error_setg_errno
  4) update commit in the commit log to explain hugepage detection on
     Windows

- changes from Eduardo Habkost's comments:
  1) use 'Error**' to collect error message for qemu_file_get_page_size()
  2) move gethugepagesize() replacement to the same patch to make it
     better for review
  3) introduce qemu_get_file_size to unity the code with raw_getlength()

- changes from Stefan's comments:
  1) check the memory region is large enough to contain DSM output
     buffer

- changes from Eric Blake's comments:
  1) update the shell command in the commit log to generate the patch
     which drops 'pc-dimm' prefix
  
- others:
  pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
  Eric Blake.

Changelog in v6:
- changes from Stefan's comments:
  1) fix code style of struct naming by CamelCase way
  2) fix offset + length overflow when read/write label data
  3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
     be used to replace getpagesize()

Changelog in v5:
- changes from Michael's comments:
  1) prefix nvdimm_ to everything in NVDIMM source files
  2) make parsing _DSM Arg3 more clear
  3) comment style fix
  5) drop single used definition
  6) fix dirty dsm buffer lost due to memory write happened on host
  7) check dsm buffer if it is big enough to contain input data
  8) use build_append_int_noprefix to store single value to GArray

- changes from Michael's and Igor's comments:
  1) introduce 'nvdimm-support' parameter to control nvdimm
     enablement and it is disabled for 2.4 and its earlier versions
     to make live migration compatible
  2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
     virtualization

- changes from Stefan's comments:
  1) do endian adjustment for the buffer length

- changes from Bharata B Rao's comments:
  1) fix compile on ppc

- others:
  1) the buffer length is directly got from IO read rather than got
     from dsm memory
  2) fix dirty label data lost due to memory write happened on host

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 (5):
  nvdimm: implement NVDIMM device abstract
  acpi: support specified oem table id for build_header
  nvdimm acpi: build ACPI NFIT table
  nvdimm acpi: build ACPI nvdimm devices
  nvdimm: add maintain info

 MAINTAINERS                        |   7 +
 default-configs/i386-softmmu.mak   |   2 +
 default-configs/x86_64-softmmu.mak |   2 +
 hw/acpi/Makefile.objs              |   1 +
 hw/acpi/aml-build.c                |  15 +-
 hw/acpi/ich9.c                     |  19 ++
 hw/acpi/memory_hotplug.c           |   5 +
 hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
 hw/acpi/piix4.c                    |   4 +
 hw/arm/virt-acpi-build.c           |  13 +-
 hw/i386/acpi-build.c               |  26 ++-
 hw/mem/Makefile.objs               |   1 +
 hw/mem/nvdimm.c                    |  46 ++++
 include/hw/acpi/aml-build.h        |   3 +-
 include/hw/acpi/ich9.h             |   3 +
 include/hw/i386/pc.h               |  12 +-
 include/hw/mem/nvdimm.h            |  41 ++++
 17 files changed, 645 insertions(+), 22 deletions(-)
 create mode 100644 hw/acpi/nvdimm.c
 create mode 100644 hw/mem/nvdimm.c
 create mode 100644 include/hw/mem/nvdimm.h

-- 
1.8.3.1

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

* [PATCH v8 1/5] nvdimm: implement NVDIMM device abstract
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-16 10:50   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:50 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 pc-dimm device type

Currently, nothing is specific for nvdimm but hotplug is disabled

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           |  5 +++++
 hw/mem/Makefile.objs               |  1 +
 hw/mem/nvdimm.c                    | 46 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/nvdimm.h            | 29 ++++++++++++++++++++++++
 6 files changed, 83 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 43c96d1..4c79d3b 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -46,6 +46,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 dfb8095..e42d2fc 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -46,6 +46,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 ce428df..8b6662b 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -230,6 +230,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
                          DeviceState *dev, Error **errp)
 {
     MemStatus *mdev;
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+    if (!dc->hotpluggable) {
+        return;
+    }
 
     mdev = acpi_memory_slot_status(mem_st, dev, errp);
     if (!mdev) {
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index b000fb4..f12f8b9 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1,2 @@
 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..4fd397f
--- /dev/null
+++ b/hw/mem/nvdimm.c
@@ -0,0 +1,46 @@
+/*
+ * 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 "hw/mem/nvdimm.h"
+
+static void nvdimm_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    /* nvdimm hotplug has not been supported yet. */
+    dc->hotpluggable = false;
+}
+
+static TypeInfo nvdimm_info = {
+    .name          = TYPE_NVDIMM,
+    .parent        = TYPE_PC_DIMM,
+    .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..dbfa8d6
--- /dev/null
+++ b/include/hw/mem/nvdimm.h
@@ -0,0 +1,29 @@
+/*
+ * 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/pc-dimm.h"
+
+#define TYPE_NVDIMM      "nvdimm"
+#endif
-- 
1.8.3.1


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

* [Qemu-devel] [PATCH v8 1/5] nvdimm: implement NVDIMM device abstract
@ 2015-11-16 10:50   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:50 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 pc-dimm device type

Currently, nothing is specific for nvdimm but hotplug is disabled

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           |  5 +++++
 hw/mem/Makefile.objs               |  1 +
 hw/mem/nvdimm.c                    | 46 ++++++++++++++++++++++++++++++++++++++
 include/hw/mem/nvdimm.h            | 29 ++++++++++++++++++++++++
 6 files changed, 83 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 43c96d1..4c79d3b 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -46,6 +46,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 dfb8095..e42d2fc 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -46,6 +46,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 ce428df..8b6662b 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -230,6 +230,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
                          DeviceState *dev, Error **errp)
 {
     MemStatus *mdev;
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+    if (!dc->hotpluggable) {
+        return;
+    }
 
     mdev = acpi_memory_slot_status(mem_st, dev, errp);
     if (!mdev) {
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index b000fb4..f12f8b9 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1 +1,2 @@
 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..4fd397f
--- /dev/null
+++ b/hw/mem/nvdimm.c
@@ -0,0 +1,46 @@
+/*
+ * 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 "hw/mem/nvdimm.h"
+
+static void nvdimm_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    /* nvdimm hotplug has not been supported yet. */
+    dc->hotpluggable = false;
+}
+
+static TypeInfo nvdimm_info = {
+    .name          = TYPE_NVDIMM,
+    .parent        = TYPE_PC_DIMM,
+    .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..dbfa8d6
--- /dev/null
+++ b/include/hw/mem/nvdimm.h
@@ -0,0 +1,29 @@
+/*
+ * 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/pc-dimm.h"
+
+#define TYPE_NVDIMM      "nvdimm"
+#endif
-- 
1.8.3.1

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

* [PATCH v8 2/5] acpi: support specified oem table id for build_header
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-16 10:51   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel, Xiao Guangrong

Let build_header() support specified OEM table id so that we can build
multiple SSDT later

If the oem table id is not specified (aka, NULL), we use the default id
instead as the previous behavior

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 15 +++++++++++----
 hw/arm/virt-acpi-build.c    | 13 +++++++------
 hw/i386/acpi-build.c        | 20 ++++++++++----------
 include/hw/acpi/aml-build.h |  3 ++-
 4 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index a00a0ab..92873bb 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1137,14 +1137,21 @@ Aml *aml_unicode(const char *str)
 
 void
 build_header(GArray *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
+             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
+             const char *oem_table_id)
 {
     memcpy(&h->signature, sig, 4);
     h->length = cpu_to_le32(len);
     h->revision = rev;
     memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
-    memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
-    memcpy(h->oem_table_id + 4, sig, 4);
+
+    if (oem_table_id) {
+        strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
+    } else {
+        memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
+        memcpy(h->oem_table_id + 4, sig, 4);
+    }
+
     h->oem_revision = cpu_to_le32(1);
     memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
     h->asl_compiler_revision = cpu_to_le32(1);
@@ -1211,5 +1218,5 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
                                        sizeof(uint32_t));
     }
     build_header(linker, table_data,
-                 (void *)rsdt, "RSDT", rsdt_len, 1);
+                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL);
 }
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 3c2c5d6..da17779 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -381,7 +381,8 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
     spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
 
-    build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2);
+    build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2,
+                 NULL);
 }
 
 static void
@@ -400,7 +401,7 @@ build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
                                           / PCIE_MMCFG_SIZE_MIN) - 1;
 
-    build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1);
+    build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL);
 }
 
 /* GTDT */
@@ -426,7 +427,7 @@ build_gtdt(GArray *table_data, GArray *linker)
 
     build_header(linker, table_data,
                  (void *)(table_data->data + gtdt_start), "GTDT",
-                 table_data->len - gtdt_start, 2);
+                 table_data->len - gtdt_start, 2, NULL);
 }
 
 /* MADT */
@@ -488,7 +489,7 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
 
     build_header(linker, table_data,
                  (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 3);
+                 table_data->len - madt_start, 3, NULL);
 }
 
 /* FADT */
@@ -513,7 +514,7 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
                                    sizeof fadt->dsdt);
 
     build_header(linker, table_data,
-                 (void *)fadt, "FACP", sizeof(*fadt), 5);
+                 (void *)fadt, "FACP", sizeof(*fadt), 5, NULL);
 }
 
 /* DSDT */
@@ -546,7 +547,7 @@ build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
     build_header(linker, table_data,
         (void *)(table_data->data + table_data->len - dsdt->buf->len),
-        "DSDT", dsdt->buf->len, 2);
+        "DSDT", dsdt->buf->len, 2, NULL);
     free_aml_allocator();
 }
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..215b58c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -361,7 +361,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
     fadt_setup(fadt, pm);
 
     build_header(linker, table_data,
-                 (void *)fadt, "FACP", sizeof(*fadt), 1);
+                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL);
 }
 
 static void
@@ -431,7 +431,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
 
     build_header(linker, table_data,
                  (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 1);
+                 table_data->len - madt_start, 1, NULL);
 }
 
 /* Assign BSEL property to all buses.  In the future, this can be changed
@@ -1349,7 +1349,7 @@ build_ssdt(GArray *table_data, GArray *linker,
     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);
+        "SSDT", ssdt->buf->len, 1, NULL);
     free_aml_allocator();
 }
 
@@ -1365,7 +1365,7 @@ build_hpet(GArray *table_data, GArray *linker)
     hpet->timer_block_id = cpu_to_le32(0x8086a201);
     hpet->addr.address = cpu_to_le64(HPET_BASE);
     build_header(linker, table_data,
-                 (void *)hpet, "HPET", sizeof(*hpet), 1);
+                 (void *)hpet, "HPET", sizeof(*hpet), 1, NULL);
 }
 
 static void
@@ -1388,7 +1388,7 @@ build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog)
                                    sizeof(tcpa->log_area_start_address));
 
     build_header(linker, table_data,
-                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2);
+                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL);
 
     acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
 }
@@ -1405,7 +1405,7 @@ build_tpm2(GArray *table_data, GArray *linker)
     tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
 
     build_header(linker, table_data,
-                 (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4);
+                 (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL);
 }
 
 typedef enum {
@@ -1519,7 +1519,7 @@ build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
     build_header(linker, table_data,
                  (void *)(table_data->data + srat_start),
                  "SRAT",
-                 table_data->len - srat_start, 1);
+                 table_data->len - srat_start, 1, NULL);
 }
 
 static void
@@ -1548,7 +1548,7 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
     } else {
         sig = "MCFG";
     }
-    build_header(linker, table_data, (void *)mcfg, sig, len, 1);
+    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL);
 }
 
 static void
@@ -1572,7 +1572,7 @@ build_dmar_q35(GArray *table_data, GArray *linker)
     drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
 
     build_header(linker, table_data, (void *)(table_data->data + dmar_start),
-                 "DMAR", table_data->len - dmar_start, 1);
+                 "DMAR", table_data->len - dmar_start, 1, NULL);
 }
 
 static void
@@ -1587,7 +1587,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
 
     memset(dsdt, 0, sizeof *dsdt);
     build_header(linker, table_data, dsdt, "DSDT",
-                 misc->dsdt_size, 1);
+                 misc->dsdt_size, 1, NULL);
 }
 
 static GArray *
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1b632dc..e587b26 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -277,7 +277,8 @@ Aml *aml_unicode(const char *str);
 
 void
 build_header(GArray *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev);
+             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
+             const char *oem_table_id);
 void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
-- 
1.8.3.1


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

* [Qemu-devel] [PATCH v8 2/5] acpi: support specified oem table id for build_header
@ 2015-11-16 10:51   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: Xiao Guangrong, ehabkost, kvm, mst, gleb, mtosatti, qemu-devel,
	stefanha, dan.j.williams, rth

Let build_header() support specified OEM table id so that we can build
multiple SSDT later

If the oem table id is not specified (aka, NULL), we use the default id
instead as the previous behavior

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/aml-build.c         | 15 +++++++++++----
 hw/arm/virt-acpi-build.c    | 13 +++++++------
 hw/i386/acpi-build.c        | 20 ++++++++++----------
 include/hw/acpi/aml-build.h |  3 ++-
 4 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index a00a0ab..92873bb 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1137,14 +1137,21 @@ Aml *aml_unicode(const char *str)
 
 void
 build_header(GArray *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
+             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
+             const char *oem_table_id)
 {
     memcpy(&h->signature, sig, 4);
     h->length = cpu_to_le32(len);
     h->revision = rev;
     memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
-    memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
-    memcpy(h->oem_table_id + 4, sig, 4);
+
+    if (oem_table_id) {
+        strncpy((char *)h->oem_table_id, oem_table_id, sizeof(h->oem_table_id));
+    } else {
+        memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
+        memcpy(h->oem_table_id + 4, sig, 4);
+    }
+
     h->oem_revision = cpu_to_le32(1);
     memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
     h->asl_compiler_revision = cpu_to_le32(1);
@@ -1211,5 +1218,5 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
                                        sizeof(uint32_t));
     }
     build_header(linker, table_data,
-                 (void *)rsdt, "RSDT", rsdt_len, 1);
+                 (void *)rsdt, "RSDT", rsdt_len, 1, NULL);
 }
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 3c2c5d6..da17779 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -381,7 +381,8 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
     spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
 
-    build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2);
+    build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2,
+                 NULL);
 }
 
 static void
@@ -400,7 +401,7 @@ build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
                                           / PCIE_MMCFG_SIZE_MIN) - 1;
 
-    build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1);
+    build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL);
 }
 
 /* GTDT */
@@ -426,7 +427,7 @@ build_gtdt(GArray *table_data, GArray *linker)
 
     build_header(linker, table_data,
                  (void *)(table_data->data + gtdt_start), "GTDT",
-                 table_data->len - gtdt_start, 2);
+                 table_data->len - gtdt_start, 2, NULL);
 }
 
 /* MADT */
@@ -488,7 +489,7 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
 
     build_header(linker, table_data,
                  (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 3);
+                 table_data->len - madt_start, 3, NULL);
 }
 
 /* FADT */
@@ -513,7 +514,7 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
                                    sizeof fadt->dsdt);
 
     build_header(linker, table_data,
-                 (void *)fadt, "FACP", sizeof(*fadt), 5);
+                 (void *)fadt, "FACP", sizeof(*fadt), 5, NULL);
 }
 
 /* DSDT */
@@ -546,7 +547,7 @@ build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
     build_header(linker, table_data,
         (void *)(table_data->data + table_data->len - dsdt->buf->len),
-        "DSDT", dsdt->buf->len, 2);
+        "DSDT", dsdt->buf->len, 2, NULL);
     free_aml_allocator();
 }
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..215b58c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -361,7 +361,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
     fadt_setup(fadt, pm);
 
     build_header(linker, table_data,
-                 (void *)fadt, "FACP", sizeof(*fadt), 1);
+                 (void *)fadt, "FACP", sizeof(*fadt), 1, NULL);
 }
 
 static void
@@ -431,7 +431,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
 
     build_header(linker, table_data,
                  (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 1);
+                 table_data->len - madt_start, 1, NULL);
 }
 
 /* Assign BSEL property to all buses.  In the future, this can be changed
@@ -1349,7 +1349,7 @@ build_ssdt(GArray *table_data, GArray *linker,
     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);
+        "SSDT", ssdt->buf->len, 1, NULL);
     free_aml_allocator();
 }
 
@@ -1365,7 +1365,7 @@ build_hpet(GArray *table_data, GArray *linker)
     hpet->timer_block_id = cpu_to_le32(0x8086a201);
     hpet->addr.address = cpu_to_le64(HPET_BASE);
     build_header(linker, table_data,
-                 (void *)hpet, "HPET", sizeof(*hpet), 1);
+                 (void *)hpet, "HPET", sizeof(*hpet), 1, NULL);
 }
 
 static void
@@ -1388,7 +1388,7 @@ build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog)
                                    sizeof(tcpa->log_area_start_address));
 
     build_header(linker, table_data,
-                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2);
+                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL);
 
     acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
 }
@@ -1405,7 +1405,7 @@ build_tpm2(GArray *table_data, GArray *linker)
     tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
 
     build_header(linker, table_data,
-                 (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4);
+                 (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL);
 }
 
 typedef enum {
@@ -1519,7 +1519,7 @@ build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
     build_header(linker, table_data,
                  (void *)(table_data->data + srat_start),
                  "SRAT",
-                 table_data->len - srat_start, 1);
+                 table_data->len - srat_start, 1, NULL);
 }
 
 static void
@@ -1548,7 +1548,7 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
     } else {
         sig = "MCFG";
     }
-    build_header(linker, table_data, (void *)mcfg, sig, len, 1);
+    build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL);
 }
 
 static void
@@ -1572,7 +1572,7 @@ build_dmar_q35(GArray *table_data, GArray *linker)
     drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
 
     build_header(linker, table_data, (void *)(table_data->data + dmar_start),
-                 "DMAR", table_data->len - dmar_start, 1);
+                 "DMAR", table_data->len - dmar_start, 1, NULL);
 }
 
 static void
@@ -1587,7 +1587,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
 
     memset(dsdt, 0, sizeof *dsdt);
     build_header(linker, table_data, dsdt, "DSDT",
-                 misc->dsdt_size, 1);
+                 misc->dsdt_size, 1, NULL);
 }
 
 static GArray *
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1b632dc..e587b26 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -277,7 +277,8 @@ Aml *aml_unicode(const char *str);
 
 void
 build_header(GArray *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev);
+             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
+             const char *oem_table_id);
 void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
-- 
1.8.3.1

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

* [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-16 10:51   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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

The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
false on 2.4 and its earlier version to keep compatibility

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/Makefile.objs              |   1 +
 hw/acpi/ich9.c                     |  19 ++
 hw/acpi/nvdimm.c                   | 382 +++++++++++++++++++++++++++++++++++++
 hw/acpi/piix4.c                    |   4 +
 hw/i386/acpi-build.c               |   6 +
 include/hw/acpi/ich9.h             |   3 +
 include/hw/i386/pc.h               |  12 +-
 include/hw/mem/nvdimm.h            |  12 ++
 10 files changed, 440 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi/nvdimm.c

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4c79d3b..53fb517 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
 CONFIG_NVDIMM=y
+CONFIG_ACPI_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 e42d2fc..766c27c 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
 CONFIG_NVDIMM=y
+CONFIG_ACPI_NVDIMM=y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 7d3230c..095597f 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_ACPI_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/ich9.c b/hw/acpi/ich9.c
index 1c7fcfa..275796f 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -307,6 +307,20 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
     s->pm.acpi_memory_hotplug.is_enabled = value;
 }
 
+static bool ich9_pm_get_nvdimm_support(Object *obj, Error **errp)
+{
+    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+    return s->pm.nvdimm_acpi_state.is_enabled;
+}
+
+static void ich9_pm_set_nvdimm_support(Object *obj, bool value, Error **errp)
+{
+    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+    s->pm.nvdimm_acpi_state.is_enabled = value;
+}
+
 static void ich9_pm_get_disable_s3(Object *obj, Visitor *v,
                                    void *opaque, const char *name,
                                    Error **errp)
@@ -404,6 +418,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
 {
     static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
     pm->acpi_memory_hotplug.is_enabled = true;
+    pm->nvdimm_acpi_state.is_enabled = true;
     pm->disable_s3 = 0;
     pm->disable_s4 = 0;
     pm->s4_val = 2;
@@ -419,6 +434,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
                              ich9_pm_get_memory_hotplug_support,
                              ich9_pm_set_memory_hotplug_support,
                              NULL);
+    object_property_add_bool(obj, "nvdimm-support",
+                             ich9_pm_get_nvdimm_support,
+                             ich9_pm_set_nvdimm_support,
+                             NULL);
     object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
                         ich9_pm_get_disable_s3,
                         ich9_pm_set_disable_s3,
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
new file mode 100644
index 0000000..98c004d
--- /dev/null
+++ b/hw/acpi/nvdimm.c
@@ -0,0 +1,382 @@
+/*
+ * 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 "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.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)) {
+        DeviceState *dev = DEVICE(obj);
+
+        if (dev->realized) { /* only realized NVDIMMs matter */
+            *list = g_slist_append(*list, DEVICE(obj));
+        }
+    }
+
+    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
+    return 0;
+}
+
+/*
+ * 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.
+ */
+static GSList *nvdimm_get_plugged_device_list(void)
+{
+    GSList *list = NULL;
+
+    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list,
+                         &list);
+    return list;
+}
+
+#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) }
+
+/*
+ * define Byte Addressable Persistent Memory (PM) Region according to
+ * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
+ */
+static const uint8_t nvdimm_nfit_spa_uuid[] =
+      NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
+                     0x18, 0xb7, 0x8c, 0xdb);
+
+/*
+ * 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.
+ *
+ * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
+ */
+struct NvdimmNfitHeader {
+    ACPI_TABLE_HEADER_DEF
+    uint32_t reserved;
+} QEMU_PACKED;
+typedef struct NvdimmNfitHeader NvdimmNfitHeader;
+
+/*
+ * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
+ * Interface Table (NFIT).
+ */
+
+/*
+ * System Physical Address Range Structure
+ *
+ * It describes the system physical address ranges occupied by NVDIMMs and
+ * the types of the regions.
+ */
+struct NvdimmNfitSpa {
+    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 NvdimmNfitSpa NvdimmNfitSpa;
+
+/*
+ * Memory Device to System Physical Address Range Mapping Structure
+ *
+ * It enables identifying each NVDIMM region and the corresponding SPA
+ * describing the memory interleave
+ */
+struct NvdimmNfitMemDev {
+    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 NvdimmNfitMemDev NvdimmNfitMemDev;
+
+/*
+ * NVDIMM Control Region Structure
+ *
+ * It describes the NVDIMM and if applicable, Block Control Window.
+ */
+struct NvdimmNfitControlRegion {
+    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 NvdimmNfitControlRegion NvdimmNfitControlRegion;
+
+/*
+ * 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 comments of nvdimm_slot_to_spa_index(). */
+static uint32_t nvdimm_slot_to_dcr_index(int slot)
+{
+    return nvdimm_slot_to_spa_index(slot) + 1;
+}
+
+/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
+static void
+nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitSpa *nfit_spa;
+    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
+                                            NULL);
+    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                            NULL);
+
+    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
+
+    nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range
+                                      Structure */);
+    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
+    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+
+    /*
+     * Control region is strict as all the device info, such as SN, index,
+     * is associated with slot id.
+     */
+    nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for
+                                       management during hot add/online
+                                       operation */ |
+                                  2 /* Data in Proximity Domain field is
+                                       valid*/);
+
+    /* NUMA node. */
+    nfit_spa->proximity_domain = cpu_to_le32(node);
+    /* the region reported as PMEM. */
+    memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
+           sizeof(nvdimm_nfit_spa_uuid));
+
+    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(0x8ULL /* EFI_MEMORY_WB */ |
+                                     0x8000ULL /* EFI_MEMORY_NV */);
+}
+
+/*
+ * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping
+ * Structure
+ */
+static void
+nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitMemDev *nfit_memdev;
+    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                            NULL);
+    uint32_t handle = nvdimm_slot_to_handle(slot);
+
+    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
+
+    nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address
+                                         Range Map Structure*/);
+    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);
+}
+
+/*
+ * ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure.
+ */
+static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitControlRegion *nfit_dcr;
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                       NULL);
+    uint32_t sn = nvdimm_slot_to_sn(slot);
+
+    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
+
+    nfit_dcr->type = cpu_to_le16(4 /* NVDIMM Control Region Structure */);
+    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(1 /* Current Revision supported
+                                             in ACPI 6.0 is 1. */);
+    nfit_dcr->serial_number = cpu_to_le32(sn);
+    nfit_dcr->fic = cpu_to_le16(0x201 /* Format Interface Code. See Chapter
+                                         2: NVDIMM Device Specific Method
+                                         (DSM) in DSM Spec Rev1.*/);
+}
+
+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) {
+        DeviceState *dev = device_list->data;
+
+        /* build System Physical Address Range Structure. */
+        nvdimm_build_structure_spa(structures, dev);
+
+        /*
+         * build Memory Device to System Physical Address Range Mapping
+         * Structure.
+         */
+        nvdimm_build_structure_memdev(structures, dev);
+
+        /* build NVDIMM Control Region Structure. */
+        nvdimm_build_structure_dcr(structures, dev);
+    }
+
+    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(NvdimmNfitHeader));
+    /* NVDIMM device structures. */
+    g_array_append_vals(table_data, structures->data, structures->len);
+
+    build_header(linker, table_data, header, "NFIT",
+                 sizeof(NvdimmNfitHeader) + structures->len, 1, NULL);
+    g_array_free(structures, true);
+}
+
+void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
+                       GArray *linker)
+{
+    GSList *device_list;
+
+    /* no NVDIMM device is plugged. */
+    device_list = nvdimm_get_plugged_device_list();
+    if (!device_list) {
+        return;
+    }
+    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    g_slist_free(device_list);
+}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2cd2fee..33e24cf 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -34,6 +34,7 @@
 #include "hw/acpi/cpu_hotplug.h"
 #include "hw/hotplug.h"
 #include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/xen/xen.h"
@@ -86,6 +87,7 @@ typedef struct PIIX4PMState {
     AcpiCpuHotplug gpe_cpu;
 
     MemHotplugState acpi_memory_hotplug;
+    NVDIMMAcpiState nvdimm_acpi_state;
 } PIIX4PMState;
 
 #define TYPE_PIIX4_PM "PIIX4_PM"
@@ -592,6 +594,8 @@ static Property piix4_pm_properties[] = {
                      use_acpi_pci_hotplug, true),
     DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
                      acpi_memory_hotplug.is_enabled, true),
+    DEFINE_PROP_BOOL("nvdimm-support", PIIX4PMState,
+                     nvdimm_acpi_state.is_enabled, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 215b58c..30ba594 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -90,6 +90,7 @@ typedef struct AcpiPmInfo {
     bool s3_disabled;
     bool s4_disabled;
     bool pcihp_bridge_en;
+    bool nvdimm_support;
     uint8_t s4_val;
     uint16_t sci_int;
     uint8_t acpi_enable_cmd;
@@ -231,6 +232,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
     pm->pcihp_bridge_en =
         object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
                                  NULL);
+    pm->nvdimm_support = object_property_get_bool(obj, "nvdimm-support", NULL);
 }
 
 static void acpi_get_misc_info(AcpiMiscInfo *info)
@@ -1742,6 +1744,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
         build_dmar_q35(tables_blob, tables->linker);
     }
 
+    if (pm.nvdimm_support) {
+        nvdimm_build_acpi(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/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 345fd8d..2c6f350 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -26,6 +26,7 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/acpi/tco.h"
+#include "hw/mem/nvdimm.h"
 
 typedef struct ICH9LPCPMRegs {
     /*
@@ -52,6 +53,8 @@ typedef struct ICH9LPCPMRegs {
 
     MemHotplugState acpi_memory_hotplug;
 
+    NVDIMMAcpiState nvdimm_acpi_state;
+
     uint8_t disable_s3;
     uint8_t disable_s4;
     uint8_t s4_val;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 4bbc0ff..9c9576b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -347,7 +347,17 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .driver   = "qemu32" "-" TYPE_X86_CPU,\
             .property = "popcnt",\
             .value    = "on",\
-        },
+        },\
+        {\
+            .driver   = "PIIX4_PM",\
+            .property = "nvdimm-support",\
+            .value    = "off",\
+        },\
+        {\
+            .driver   = "ICH9-LPC",\
+            .property = "nvdimm-support",\
+            .value    = "off",\
+       },
 
 #define PC_COMPAT_2_3 \
         PC_COMPAT_2_4 \
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index dbfa8d6..6c29fff 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -26,4 +26,16 @@
 #include "hw/mem/pc-dimm.h"
 
 #define TYPE_NVDIMM      "nvdimm"
+
+/*
+ * AcpiNVDIMMState:
+ * @is_enabled: detect if NVDIMM support is enabled.
+ */
+struct NVDIMMAcpiState {
+    bool is_enabled;
+};
+typedef struct NVDIMMAcpiState NVDIMMAcpiState;
+
+void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
+                       GArray *linker);
 #endif
-- 
1.8.3.1


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

* [Qemu-devel] [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
@ 2015-11-16 10:51   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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

The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
false on 2.4 and its earlier version to keep compatibility

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/Makefile.objs              |   1 +
 hw/acpi/ich9.c                     |  19 ++
 hw/acpi/nvdimm.c                   | 382 +++++++++++++++++++++++++++++++++++++
 hw/acpi/piix4.c                    |   4 +
 hw/i386/acpi-build.c               |   6 +
 include/hw/acpi/ich9.h             |   3 +
 include/hw/i386/pc.h               |  12 +-
 include/hw/mem/nvdimm.h            |  12 ++
 10 files changed, 440 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi/nvdimm.c

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4c79d3b..53fb517 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
 CONFIG_NVDIMM=y
+CONFIG_ACPI_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 e42d2fc..766c27c 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
 CONFIG_NVDIMM=y
+CONFIG_ACPI_NVDIMM=y
 CONFIG_XIO3130=y
 CONFIG_IOH3420=y
 CONFIG_I82801B11=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 7d3230c..095597f 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_ACPI_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/ich9.c b/hw/acpi/ich9.c
index 1c7fcfa..275796f 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -307,6 +307,20 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
     s->pm.acpi_memory_hotplug.is_enabled = value;
 }
 
+static bool ich9_pm_get_nvdimm_support(Object *obj, Error **errp)
+{
+    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+    return s->pm.nvdimm_acpi_state.is_enabled;
+}
+
+static void ich9_pm_set_nvdimm_support(Object *obj, bool value, Error **errp)
+{
+    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+    s->pm.nvdimm_acpi_state.is_enabled = value;
+}
+
 static void ich9_pm_get_disable_s3(Object *obj, Visitor *v,
                                    void *opaque, const char *name,
                                    Error **errp)
@@ -404,6 +418,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
 {
     static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
     pm->acpi_memory_hotplug.is_enabled = true;
+    pm->nvdimm_acpi_state.is_enabled = true;
     pm->disable_s3 = 0;
     pm->disable_s4 = 0;
     pm->s4_val = 2;
@@ -419,6 +434,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
                              ich9_pm_get_memory_hotplug_support,
                              ich9_pm_set_memory_hotplug_support,
                              NULL);
+    object_property_add_bool(obj, "nvdimm-support",
+                             ich9_pm_get_nvdimm_support,
+                             ich9_pm_set_nvdimm_support,
+                             NULL);
     object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
                         ich9_pm_get_disable_s3,
                         ich9_pm_set_disable_s3,
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
new file mode 100644
index 0000000..98c004d
--- /dev/null
+++ b/hw/acpi/nvdimm.c
@@ -0,0 +1,382 @@
+/*
+ * 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 "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.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)) {
+        DeviceState *dev = DEVICE(obj);
+
+        if (dev->realized) { /* only realized NVDIMMs matter */
+            *list = g_slist_append(*list, DEVICE(obj));
+        }
+    }
+
+    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
+    return 0;
+}
+
+/*
+ * 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.
+ */
+static GSList *nvdimm_get_plugged_device_list(void)
+{
+    GSList *list = NULL;
+
+    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list,
+                         &list);
+    return list;
+}
+
+#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) }
+
+/*
+ * define Byte Addressable Persistent Memory (PM) Region according to
+ * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
+ */
+static const uint8_t nvdimm_nfit_spa_uuid[] =
+      NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
+                     0x18, 0xb7, 0x8c, 0xdb);
+
+/*
+ * 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.
+ *
+ * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
+ */
+struct NvdimmNfitHeader {
+    ACPI_TABLE_HEADER_DEF
+    uint32_t reserved;
+} QEMU_PACKED;
+typedef struct NvdimmNfitHeader NvdimmNfitHeader;
+
+/*
+ * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
+ * Interface Table (NFIT).
+ */
+
+/*
+ * System Physical Address Range Structure
+ *
+ * It describes the system physical address ranges occupied by NVDIMMs and
+ * the types of the regions.
+ */
+struct NvdimmNfitSpa {
+    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 NvdimmNfitSpa NvdimmNfitSpa;
+
+/*
+ * Memory Device to System Physical Address Range Mapping Structure
+ *
+ * It enables identifying each NVDIMM region and the corresponding SPA
+ * describing the memory interleave
+ */
+struct NvdimmNfitMemDev {
+    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 NvdimmNfitMemDev NvdimmNfitMemDev;
+
+/*
+ * NVDIMM Control Region Structure
+ *
+ * It describes the NVDIMM and if applicable, Block Control Window.
+ */
+struct NvdimmNfitControlRegion {
+    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 NvdimmNfitControlRegion NvdimmNfitControlRegion;
+
+/*
+ * 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 comments of nvdimm_slot_to_spa_index(). */
+static uint32_t nvdimm_slot_to_dcr_index(int slot)
+{
+    return nvdimm_slot_to_spa_index(slot) + 1;
+}
+
+/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
+static void
+nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitSpa *nfit_spa;
+    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
+                                            NULL);
+    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                            NULL);
+
+    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
+
+    nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range
+                                      Structure */);
+    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
+    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
+
+    /*
+     * Control region is strict as all the device info, such as SN, index,
+     * is associated with slot id.
+     */
+    nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for
+                                       management during hot add/online
+                                       operation */ |
+                                  2 /* Data in Proximity Domain field is
+                                       valid*/);
+
+    /* NUMA node. */
+    nfit_spa->proximity_domain = cpu_to_le32(node);
+    /* the region reported as PMEM. */
+    memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
+           sizeof(nvdimm_nfit_spa_uuid));
+
+    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(0x8ULL /* EFI_MEMORY_WB */ |
+                                     0x8000ULL /* EFI_MEMORY_NV */);
+}
+
+/*
+ * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping
+ * Structure
+ */
+static void
+nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitMemDev *nfit_memdev;
+    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
+                                            NULL);
+    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
+                                            NULL);
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                            NULL);
+    uint32_t handle = nvdimm_slot_to_handle(slot);
+
+    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
+
+    nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address
+                                         Range Map Structure*/);
+    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);
+}
+
+/*
+ * ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure.
+ */
+static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
+{
+    NvdimmNfitControlRegion *nfit_dcr;
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                       NULL);
+    uint32_t sn = nvdimm_slot_to_sn(slot);
+
+    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
+
+    nfit_dcr->type = cpu_to_le16(4 /* NVDIMM Control Region Structure */);
+    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(1 /* Current Revision supported
+                                             in ACPI 6.0 is 1. */);
+    nfit_dcr->serial_number = cpu_to_le32(sn);
+    nfit_dcr->fic = cpu_to_le16(0x201 /* Format Interface Code. See Chapter
+                                         2: NVDIMM Device Specific Method
+                                         (DSM) in DSM Spec Rev1.*/);
+}
+
+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) {
+        DeviceState *dev = device_list->data;
+
+        /* build System Physical Address Range Structure. */
+        nvdimm_build_structure_spa(structures, dev);
+
+        /*
+         * build Memory Device to System Physical Address Range Mapping
+         * Structure.
+         */
+        nvdimm_build_structure_memdev(structures, dev);
+
+        /* build NVDIMM Control Region Structure. */
+        nvdimm_build_structure_dcr(structures, dev);
+    }
+
+    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(NvdimmNfitHeader));
+    /* NVDIMM device structures. */
+    g_array_append_vals(table_data, structures->data, structures->len);
+
+    build_header(linker, table_data, header, "NFIT",
+                 sizeof(NvdimmNfitHeader) + structures->len, 1, NULL);
+    g_array_free(structures, true);
+}
+
+void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
+                       GArray *linker)
+{
+    GSList *device_list;
+
+    /* no NVDIMM device is plugged. */
+    device_list = nvdimm_get_plugged_device_list();
+    if (!device_list) {
+        return;
+    }
+    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    g_slist_free(device_list);
+}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2cd2fee..33e24cf 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -34,6 +34,7 @@
 #include "hw/acpi/cpu_hotplug.h"
 #include "hw/hotplug.h"
 #include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/xen/xen.h"
@@ -86,6 +87,7 @@ typedef struct PIIX4PMState {
     AcpiCpuHotplug gpe_cpu;
 
     MemHotplugState acpi_memory_hotplug;
+    NVDIMMAcpiState nvdimm_acpi_state;
 } PIIX4PMState;
 
 #define TYPE_PIIX4_PM "PIIX4_PM"
@@ -592,6 +594,8 @@ static Property piix4_pm_properties[] = {
                      use_acpi_pci_hotplug, true),
     DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
                      acpi_memory_hotplug.is_enabled, true),
+    DEFINE_PROP_BOOL("nvdimm-support", PIIX4PMState,
+                     nvdimm_acpi_state.is_enabled, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 215b58c..30ba594 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -90,6 +90,7 @@ typedef struct AcpiPmInfo {
     bool s3_disabled;
     bool s4_disabled;
     bool pcihp_bridge_en;
+    bool nvdimm_support;
     uint8_t s4_val;
     uint16_t sci_int;
     uint8_t acpi_enable_cmd;
@@ -231,6 +232,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
     pm->pcihp_bridge_en =
         object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
                                  NULL);
+    pm->nvdimm_support = object_property_get_bool(obj, "nvdimm-support", NULL);
 }
 
 static void acpi_get_misc_info(AcpiMiscInfo *info)
@@ -1742,6 +1744,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
         build_dmar_q35(tables_blob, tables->linker);
     }
 
+    if (pm.nvdimm_support) {
+        nvdimm_build_acpi(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/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 345fd8d..2c6f350 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -26,6 +26,7 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/acpi_dev_interface.h"
 #include "hw/acpi/tco.h"
+#include "hw/mem/nvdimm.h"
 
 typedef struct ICH9LPCPMRegs {
     /*
@@ -52,6 +53,8 @@ typedef struct ICH9LPCPMRegs {
 
     MemHotplugState acpi_memory_hotplug;
 
+    NVDIMMAcpiState nvdimm_acpi_state;
+
     uint8_t disable_s3;
     uint8_t disable_s4;
     uint8_t s4_val;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 4bbc0ff..9c9576b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -347,7 +347,17 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .driver   = "qemu32" "-" TYPE_X86_CPU,\
             .property = "popcnt",\
             .value    = "on",\
-        },
+        },\
+        {\
+            .driver   = "PIIX4_PM",\
+            .property = "nvdimm-support",\
+            .value    = "off",\
+        },\
+        {\
+            .driver   = "ICH9-LPC",\
+            .property = "nvdimm-support",\
+            .value    = "off",\
+       },
 
 #define PC_COMPAT_2_3 \
         PC_COMPAT_2_4 \
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index dbfa8d6..6c29fff 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -26,4 +26,16 @@
 #include "hw/mem/pc-dimm.h"
 
 #define TYPE_NVDIMM      "nvdimm"
+
+/*
+ * AcpiNVDIMMState:
+ * @is_enabled: detect if NVDIMM support is enabled.
+ */
+struct NVDIMMAcpiState {
+    bool is_enabled;
+};
+typedef struct NVDIMMAcpiState NVDIMMAcpiState;
+
+void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
+                       GArray *linker);
 #endif
-- 
1.8.3.1

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

* [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-16 10:51   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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

Currently, we do not support any function on _DSM, that means, NVDIMM
label data has not been supported yet

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

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 98c004d..abe0daa 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
     g_array_free(structures, true);
 }
 
+static void nvdimm_build_common_dsm(Aml *root_dev)
+{
+    Aml *method, *ifctx, *function;
+    uint8_t byte_list[1];
+
+    method = aml_method("NCAL", 4);
+    {
+        function = aml_arg(2);
+
+        /*
+         * function 0 is called to inquire what functions are supported by
+         * OSPM
+         */
+        ifctx = aml_if(aml_equal(function, aml_int(0)));
+        byte_list[0] = 0 /* No function Supported */;
+        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
+        aml_append(method, ifctx);
+
+        /* No function is supported yet. */
+        byte_list[0] = 1 /* Not Supported */;
+        aml_append(method, aml_return(aml_buffer(1, byte_list)));
+    }
+    aml_append(root_dev, method);
+}
+
+static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
+{
+    for (; device_list; device_list = device_list->next) {
+        DeviceState *dev = device_list->data;
+        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                           NULL);
+        uint32_t handle = nvdimm_slot_to_handle(slot);
+        Aml *nvdimm_dev, *method;
+
+        nvdimm_dev = aml_device("NV%02X", slot);
+        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
+
+        method = aml_method("_DSM", 4);
+        {
+            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
+                       aml_arg(1), aml_arg(2), aml_arg(3))));
+        }
+        aml_append(nvdimm_dev, method);
+
+        aml_append(root_dev, nvdimm_dev);
+    }
+}
+
+static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
+                              GArray *table_data, GArray *linker)
+{
+    Aml *ssdt, *sb_scope, *dev, *method;
+
+    acpi_add_table(table_offsets, table_data);
+
+    ssdt = init_aml_allocator();
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    sb_scope = aml_scope("\\_SB");
+
+    dev = aml_device("NVDR");
+    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
+
+    nvdimm_build_common_dsm(dev);
+    method = aml_method("_DSM", 4);
+    {
+        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
+                   aml_arg(1), aml_arg(2), aml_arg(3))));
+    }
+    aml_append(dev, method);
+
+    nvdimm_build_nvdimm_devices(device_list, dev);
+
+    aml_append(sb_scope, dev);
+
+    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, "NVDIMM");
+    free_aml_allocator();
+}
+
 void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
                        GArray *linker)
 {
@@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
         return;
     }
     nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
     g_slist_free(device_list);
 }
-- 
1.8.3.1


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

* [Qemu-devel] [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
@ 2015-11-16 10:51   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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

Currently, we do not support any function on _DSM, that means, NVDIMM
label data has not been supported yet

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

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 98c004d..abe0daa 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
     g_array_free(structures, true);
 }
 
+static void nvdimm_build_common_dsm(Aml *root_dev)
+{
+    Aml *method, *ifctx, *function;
+    uint8_t byte_list[1];
+
+    method = aml_method("NCAL", 4);
+    {
+        function = aml_arg(2);
+
+        /*
+         * function 0 is called to inquire what functions are supported by
+         * OSPM
+         */
+        ifctx = aml_if(aml_equal(function, aml_int(0)));
+        byte_list[0] = 0 /* No function Supported */;
+        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
+        aml_append(method, ifctx);
+
+        /* No function is supported yet. */
+        byte_list[0] = 1 /* Not Supported */;
+        aml_append(method, aml_return(aml_buffer(1, byte_list)));
+    }
+    aml_append(root_dev, method);
+}
+
+static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
+{
+    for (; device_list; device_list = device_list->next) {
+        DeviceState *dev = device_list->data;
+        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                           NULL);
+        uint32_t handle = nvdimm_slot_to_handle(slot);
+        Aml *nvdimm_dev, *method;
+
+        nvdimm_dev = aml_device("NV%02X", slot);
+        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
+
+        method = aml_method("_DSM", 4);
+        {
+            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
+                       aml_arg(1), aml_arg(2), aml_arg(3))));
+        }
+        aml_append(nvdimm_dev, method);
+
+        aml_append(root_dev, nvdimm_dev);
+    }
+}
+
+static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
+                              GArray *table_data, GArray *linker)
+{
+    Aml *ssdt, *sb_scope, *dev, *method;
+
+    acpi_add_table(table_offsets, table_data);
+
+    ssdt = init_aml_allocator();
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    sb_scope = aml_scope("\\_SB");
+
+    dev = aml_device("NVDR");
+    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
+
+    nvdimm_build_common_dsm(dev);
+    method = aml_method("_DSM", 4);
+    {
+        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
+                   aml_arg(1), aml_arg(2), aml_arg(3))));
+    }
+    aml_append(dev, method);
+
+    nvdimm_build_nvdimm_devices(device_list, dev);
+
+    aml_append(sb_scope, dev);
+
+    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, "NVDIMM");
+    free_aml_allocator();
+}
+
 void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
                        GArray *linker)
 {
@@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
         return;
     }
     nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
     g_slist_free(device_list);
 }
-- 
1.8.3.1

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

* [PATCH v8 5/5] nvdimm: add maintain info
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-16 10:51   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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 9e1fa72..da58bf4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -932,6 +932,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] 48+ messages in thread

* [Qemu-devel] [PATCH v8 5/5] nvdimm: add maintain info
@ 2015-11-16 10:51   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-16 10:51 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 9e1fa72..da58bf4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -932,6 +932,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] 48+ messages in thread

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-18  1:59   ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-18  1:59 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: gleb, mtosatti, stefanha, mst, rth, ehabkost, dan.j.williams,
	kvm, qemu-devel


Ping...

Do you have any comment on this patchset? Could it be applied to somewhere
if it is okay for you?

Thanks!

On 11/16/2015 06:50 PM, Xiao Guangrong wrote:
> This patchset can be found at:
>        https://github.com/xiaogr/qemu.git nvdimm-v8
>
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
>
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.
>
> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>     memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>     -device nvdimm,memdev=mem1,id=nv1
>
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>    1) let gethugepagesize() realize if fstat is failed instead of get
>       normal page size
>    2) rename  open_file_path to open_ram_file_path
>    3) better log the error message by using error_setg_errno
>    4) update commit in the commit log to explain hugepage detection on
>       Windows
>
> - changes from Eduardo Habkost's comments:
>    1) use 'Error**' to collect error message for qemu_file_get_page_size()
>    2) move gethugepagesize() replacement to the same patch to make it
>       better for review
>    3) introduce qemu_get_file_size to unity the code with raw_getlength()
>
> - changes from Stefan's comments:
>    1) check the memory region is large enough to contain DSM output
>       buffer
>
> - changes from Eric Blake's comments:
>    1) update the shell command in the commit log to generate the patch
>       which drops 'pc-dimm' prefix
>
> - others:
>    pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>    Eric Blake.
>
> Changelog in v6:
> - changes from Stefan's comments:
>    1) fix code style of struct naming by CamelCase way
>    2) fix offset + length overflow when read/write label data
>    3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>       be used to replace getpagesize()
>
> Changelog in v5:
> - changes from Michael's comments:
>    1) prefix nvdimm_ to everything in NVDIMM source files
>    2) make parsing _DSM Arg3 more clear
>    3) comment style fix
>    5) drop single used definition
>    6) fix dirty dsm buffer lost due to memory write happened on host
>    7) check dsm buffer if it is big enough to contain input data
>    8) use build_append_int_noprefix to store single value to GArray
>
> - changes from Michael's and Igor's comments:
>    1) introduce 'nvdimm-support' parameter to control nvdimm
>       enablement and it is disabled for 2.4 and its earlier versions
>       to make live migration compatible
>    2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>       virtualization
>
> - changes from Stefan's comments:
>    1) do endian adjustment for the buffer length
>
> - changes from Bharata B Rao's comments:
>    1) fix compile on ppc
>
> - others:
>    1) the buffer length is directly got from IO read rather than got
>       from dsm memory
>    2) fix dirty label data lost due to memory write happened on host
>
> 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 (5):
>    nvdimm: implement NVDIMM device abstract
>    acpi: support specified oem table id for build_header
>    nvdimm acpi: build ACPI NFIT table
>    nvdimm acpi: build ACPI nvdimm devices
>    nvdimm: add maintain info
>
>   MAINTAINERS                        |   7 +
>   default-configs/i386-softmmu.mak   |   2 +
>   default-configs/x86_64-softmmu.mak |   2 +
>   hw/acpi/Makefile.objs              |   1 +
>   hw/acpi/aml-build.c                |  15 +-
>   hw/acpi/ich9.c                     |  19 ++
>   hw/acpi/memory_hotplug.c           |   5 +
>   hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>   hw/acpi/piix4.c                    |   4 +
>   hw/arm/virt-acpi-build.c           |  13 +-
>   hw/i386/acpi-build.c               |  26 ++-
>   hw/mem/Makefile.objs               |   1 +
>   hw/mem/nvdimm.c                    |  46 ++++
>   include/hw/acpi/aml-build.h        |   3 +-
>   include/hw/acpi/ich9.h             |   3 +
>   include/hw/i386/pc.h               |  12 +-
>   include/hw/mem/nvdimm.h            |  41 ++++
>   17 files changed, 645 insertions(+), 22 deletions(-)
>   create mode 100644 hw/acpi/nvdimm.c
>   create mode 100644 hw/mem/nvdimm.c
>   create mode 100644 include/hw/mem/nvdimm.h
>

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-18  1:59   ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-18  1:59 UTC (permalink / raw)
  To: pbonzini, imammedo
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	dan.j.williams, rth


Ping...

Do you have any comment on this patchset? Could it be applied to somewhere
if it is okay for you?

Thanks!

On 11/16/2015 06:50 PM, Xiao Guangrong wrote:
> This patchset can be found at:
>        https://github.com/xiaogr/qemu.git nvdimm-v8
>
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
>
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.
>
> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>     memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>     -device nvdimm,memdev=mem1,id=nv1
>
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>    1) let gethugepagesize() realize if fstat is failed instead of get
>       normal page size
>    2) rename  open_file_path to open_ram_file_path
>    3) better log the error message by using error_setg_errno
>    4) update commit in the commit log to explain hugepage detection on
>       Windows
>
> - changes from Eduardo Habkost's comments:
>    1) use 'Error**' to collect error message for qemu_file_get_page_size()
>    2) move gethugepagesize() replacement to the same patch to make it
>       better for review
>    3) introduce qemu_get_file_size to unity the code with raw_getlength()
>
> - changes from Stefan's comments:
>    1) check the memory region is large enough to contain DSM output
>       buffer
>
> - changes from Eric Blake's comments:
>    1) update the shell command in the commit log to generate the patch
>       which drops 'pc-dimm' prefix
>
> - others:
>    pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>    Eric Blake.
>
> Changelog in v6:
> - changes from Stefan's comments:
>    1) fix code style of struct naming by CamelCase way
>    2) fix offset + length overflow when read/write label data
>    3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>       be used to replace getpagesize()
>
> Changelog in v5:
> - changes from Michael's comments:
>    1) prefix nvdimm_ to everything in NVDIMM source files
>    2) make parsing _DSM Arg3 more clear
>    3) comment style fix
>    5) drop single used definition
>    6) fix dirty dsm buffer lost due to memory write happened on host
>    7) check dsm buffer if it is big enough to contain input data
>    8) use build_append_int_noprefix to store single value to GArray
>
> - changes from Michael's and Igor's comments:
>    1) introduce 'nvdimm-support' parameter to control nvdimm
>       enablement and it is disabled for 2.4 and its earlier versions
>       to make live migration compatible
>    2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>       virtualization
>
> - changes from Stefan's comments:
>    1) do endian adjustment for the buffer length
>
> - changes from Bharata B Rao's comments:
>    1) fix compile on ppc
>
> - others:
>    1) the buffer length is directly got from IO read rather than got
>       from dsm memory
>    2) fix dirty label data lost due to memory write happened on host
>
> 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 (5):
>    nvdimm: implement NVDIMM device abstract
>    acpi: support specified oem table id for build_header
>    nvdimm acpi: build ACPI NFIT table
>    nvdimm acpi: build ACPI nvdimm devices
>    nvdimm: add maintain info
>
>   MAINTAINERS                        |   7 +
>   default-configs/i386-softmmu.mak   |   2 +
>   default-configs/x86_64-softmmu.mak |   2 +
>   hw/acpi/Makefile.objs              |   1 +
>   hw/acpi/aml-build.c                |  15 +-
>   hw/acpi/ich9.c                     |  19 ++
>   hw/acpi/memory_hotplug.c           |   5 +
>   hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>   hw/acpi/piix4.c                    |   4 +
>   hw/arm/virt-acpi-build.c           |  13 +-
>   hw/i386/acpi-build.c               |  26 ++-
>   hw/mem/Makefile.objs               |   1 +
>   hw/mem/nvdimm.c                    |  46 ++++
>   include/hw/acpi/aml-build.h        |   3 +-
>   include/hw/acpi/ich9.h             |   3 +
>   include/hw/i386/pc.h               |  12 +-
>   include/hw/mem/nvdimm.h            |  41 ++++
>   17 files changed, 645 insertions(+), 22 deletions(-)
>   create mode 100644 hw/acpi/nvdimm.c
>   create mode 100644 hw/mem/nvdimm.c
>   create mode 100644 include/hw/mem/nvdimm.h
>

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-18  1:59   ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-18 19:18     ` Eduardo Habkost
  -1 siblings, 0 replies; 48+ messages in thread
From: Eduardo Habkost @ 2015-11-18 19:18 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, mst, rth,
	dan.j.williams, kvm, qemu-devel

On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> 
> Ping...
> 
> Do you have any comment on this patchset? Could it be applied to somewhere
> if it is okay for you?

I have no additional comments, as the memory-backend patches I
was reviewing are not included in this version. I didn't take the
time to review the TYPE_NVDIMM and ACPI changes.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-18 19:18     ` Eduardo Habkost
  0 siblings, 0 replies; 48+ messages in thread
From: Eduardo Habkost @ 2015-11-18 19:18 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: kvm, mst, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> 
> Ping...
> 
> Do you have any comment on this patchset? Could it be applied to somewhere
> if it is okay for you?

I have no additional comments, as the memory-backend patches I
was reviewing are not included in this version. I didn't take the
time to review the TYPE_NVDIMM and ACPI changes.

-- 
Eduardo

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-18 19:18     ` [Qemu-devel] " Eduardo Habkost
@ 2015-11-18 20:44       ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-18 20:44 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Xiao Guangrong, pbonzini, imammedo, gleb, mtosatti, stefanha,
	rth, dan.j.williams, kvm, qemu-devel

On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> > 
> > Ping...
> > 
> > Do you have any comment on this patchset? Could it be applied to somewhere
> > if it is okay for you?
> 
> I have no additional comments, as the memory-backend patches I
> was reviewing are not included in this version. I didn't take the
> time to review the TYPE_NVDIMM and ACPI changes.

No, I don't think the way guest memory is allocated here is ok.  I'm
sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
Once that's out, I'll post some suggestions.

Thanks!

> -- 
> Eduardo

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-18 20:44       ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-18 20:44 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Xiao Guangrong, kvm, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth

On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> > 
> > Ping...
> > 
> > Do you have any comment on this patchset? Could it be applied to somewhere
> > if it is okay for you?
> 
> I have no additional comments, as the memory-backend patches I
> was reviewing are not included in this version. I didn't take the
> time to review the TYPE_NVDIMM and ACPI changes.

No, I don't think the way guest memory is allocated here is ok.  I'm
sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
Once that's out, I'll post some suggestions.

Thanks!

> -- 
> Eduardo

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-18 20:44       ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-11-19  2:39         ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-19  2:39 UTC (permalink / raw)
  To: Michael S. Tsirkin, Eduardo Habkost
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth,
	dan.j.williams, kvm, qemu-devel



On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
>> On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
>>>
>>> Ping...
>>>
>>> Do you have any comment on this patchset? Could it be applied to somewhere
>>> if it is okay for you?
>>
>> I have no additional comments, as the memory-backend patches I
>> was reviewing are not included in this version. I didn't take the
>> time to review the TYPE_NVDIMM and ACPI changes.
>
> No, I don't think the way guest memory is allocated here is ok.  I'm

Since the DSM memory/ACPI memory was not included in this patchset, i really
do not understand what is "guest memory is allocated" exactly stands for...

> sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.

I still see some pull requests were send our for 2.5 merge window today and
yesterday ...

This patchset is the simplest version we can figure out to implement basic
functionality for vNVDIMM and only minor change is needed for other code.
It would be nice and really appreciate if it can go to 2.5.

> Once that's out, I'll post some suggestions.

Look forward to you suggestions.

Thanks for your time, Michael and Eduardo!

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-19  2:39         ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-19  2:39 UTC (permalink / raw)
  To: Michael S. Tsirkin, Eduardo Habkost
  Cc: kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo, pbonzini,
	dan.j.williams, rth



On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
>> On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
>>>
>>> Ping...
>>>
>>> Do you have any comment on this patchset? Could it be applied to somewhere
>>> if it is okay for you?
>>
>> I have no additional comments, as the memory-backend patches I
>> was reviewing are not included in this version. I didn't take the
>> time to review the TYPE_NVDIMM and ACPI changes.
>
> No, I don't think the way guest memory is allocated here is ok.  I'm

Since the DSM memory/ACPI memory was not included in this patchset, i really
do not understand what is "guest memory is allocated" exactly stands for...

> sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.

I still see some pull requests were send our for 2.5 merge window today and
yesterday ...

This patchset is the simplest version we can figure out to implement basic
functionality for vNVDIMM and only minor change is needed for other code.
It would be nice and really appreciate if it can go to 2.5.

> Once that's out, I'll post some suggestions.

Look forward to you suggestions.

Thanks for your time, Michael and Eduardo!

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-19  2:39         ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-19  8:21           ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-19  8:21 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Eduardo Habkost, pbonzini, imammedo, gleb, mtosatti, stefanha,
	rth, dan.j.williams, kvm, qemu-devel

On Thu, Nov 19, 2015 at 10:39:05AM +0800, Xiao Guangrong wrote:
> 
> 
> On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> >On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> >>On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> >>>
> >>>Ping...
> >>>
> >>>Do you have any comment on this patchset? Could it be applied to somewhere
> >>>if it is okay for you?
> >>
> >>I have no additional comments, as the memory-backend patches I
> >>was reviewing are not included in this version. I didn't take the
> >>time to review the TYPE_NVDIMM and ACPI changes.
> >
> >No, I don't think the way guest memory is allocated here is ok.  I'm
> 
> Since the DSM memory/ACPI memory was not included in this patchset, i really
> do not understand what is "guest memory is allocated" exactly stands for...

I might even be confusing this with another patchset.
Let's have this discussion when I have the time to review
and respond properly.

> >sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
> 
> I still see some pull requests were send our for 2.5 merge window today and
> yesterday ...
> 
> This patchset is the simplest version we can figure out to implement basic
> functionality for vNVDIMM and only minor change is needed for other code.
> It would be nice and really appreciate if it can go to 2.5.

Sorry, no way, we are in a bugfix only mode for 2.5.

> >Once that's out, I'll post some suggestions.
> 
> Look forward to you suggestions.
> 
> Thanks for your time, Michael and Eduardo!

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-19  8:21           ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-19  8:21 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Eduardo Habkost, kvm, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth

On Thu, Nov 19, 2015 at 10:39:05AM +0800, Xiao Guangrong wrote:
> 
> 
> On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> >On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> >>On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> >>>
> >>>Ping...
> >>>
> >>>Do you have any comment on this patchset? Could it be applied to somewhere
> >>>if it is okay for you?
> >>
> >>I have no additional comments, as the memory-backend patches I
> >>was reviewing are not included in this version. I didn't take the
> >>time to review the TYPE_NVDIMM and ACPI changes.
> >
> >No, I don't think the way guest memory is allocated here is ok.  I'm
> 
> Since the DSM memory/ACPI memory was not included in this patchset, i really
> do not understand what is "guest memory is allocated" exactly stands for...

I might even be confusing this with another patchset.
Let's have this discussion when I have the time to review
and respond properly.

> >sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
> 
> I still see some pull requests were send our for 2.5 merge window today and
> yesterday ...
> 
> This patchset is the simplest version we can figure out to implement basic
> functionality for vNVDIMM and only minor change is needed for other code.
> It would be nice and really appreciate if it can go to 2.5.

Sorry, no way, we are in a bugfix only mode for 2.5.

> >Once that's out, I'll post some suggestions.
> 
> Look forward to you suggestions.
> 
> Thanks for your time, Michael and Eduardo!

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-19  2:39         ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-23  8:53           ` Stefan Hajnoczi
  -1 siblings, 0 replies; 48+ messages in thread
From: Stefan Hajnoczi @ 2015-11-23  8:53 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Eduardo Habkost, kvm, Michael S. Tsirkin, gleb, mtosatti,
	qemu-devel, stefanha, pbonzini, imammedo, dan.j.williams, rth

[-- Attachment #1: Type: text/plain, Size: 901 bytes --]

On Thu, Nov 19, 2015 at 10:39:05AM +0800, Xiao Guangrong wrote:
> On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> >On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> >>On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> >sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
> 
> I still see some pull requests were send our for 2.5 merge window today and
> yesterday ...
> 
> This patchset is the simplest version we can figure out to implement basic
> functionality for vNVDIMM and only minor change is needed for other code.
> It would be nice and really appreciate if it can go to 2.5.

Here is the release schedule:
http://qemu-project.org/Planning/2.5

QEMU is in hard freeze right now.  That means only critical bug fixes
are being merged.  No new features will be merged until the QEMU 2.6
development cycle begins.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-23  8:53           ` Stefan Hajnoczi
  0 siblings, 0 replies; 48+ messages in thread
From: Stefan Hajnoczi @ 2015-11-23  8:53 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: Eduardo Habkost, kvm, Michael S. Tsirkin, gleb, mtosatti,
	qemu-devel, stefanha, pbonzini, imammedo, dan.j.williams, rth

[-- Attachment #1: Type: text/plain, Size: 901 bytes --]

On Thu, Nov 19, 2015 at 10:39:05AM +0800, Xiao Guangrong wrote:
> On 11/19/2015 04:44 AM, Michael S. Tsirkin wrote:
> >On Wed, Nov 18, 2015 at 05:18:17PM -0200, Eduardo Habkost wrote:
> >>On Wed, Nov 18, 2015 at 09:59:34AM +0800, Xiao Guangrong wrote:
> >sorry, I'm busy with 2.5 now, and this is clearly not 2.5 material.
> 
> I still see some pull requests were send our for 2.5 merge window today and
> yesterday ...
> 
> This patchset is the simplest version we can figure out to implement basic
> functionality for vNVDIMM and only minor change is needed for other code.
> It would be nice and really appreciate if it can go to 2.5.

Here is the release schedule:
http://qemu-project.org/Planning/2.5

QEMU is in hard freeze right now.  That means only critical bug fixes
are being merged.  No new features will be merged until the QEMU 2.6
development cycle begins.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-30  8:51   ` Stefan Hajnoczi
  -1 siblings, 0 replies; 48+ messages in thread
From: Stefan Hajnoczi @ 2015-11-30  8:51 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth

[-- Attachment #1: Type: text/plain, Size: 13984 bytes --]

On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
> This patchset can be found at:
>       https://github.com/xiaogr/qemu.git nvdimm-v8
> 
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
> 
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.
> 
> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>    memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>    -device nvdimm,memdev=mem1,id=nv1
> 
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>   1) let gethugepagesize() realize if fstat is failed instead of get
>      normal page size
>   2) rename  open_file_path to open_ram_file_path
>   3) better log the error message by using error_setg_errno
>   4) update commit in the commit log to explain hugepage detection on
>      Windows
> 
> - changes from Eduardo Habkost's comments:
>   1) use 'Error**' to collect error message for qemu_file_get_page_size()
>   2) move gethugepagesize() replacement to the same patch to make it
>      better for review
>   3) introduce qemu_get_file_size to unity the code with raw_getlength()
> 
> - changes from Stefan's comments:
>   1) check the memory region is large enough to contain DSM output
>      buffer
> 
> - changes from Eric Blake's comments:
>   1) update the shell command in the commit log to generate the patch
>      which drops 'pc-dimm' prefix
>   
> - others:
>   pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>   Eric Blake.
> 
> Changelog in v6:
> - changes from Stefan's comments:
>   1) fix code style of struct naming by CamelCase way
>   2) fix offset + length overflow when read/write label data
>   3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>      be used to replace getpagesize()
> 
> Changelog in v5:
> - changes from Michael's comments:
>   1) prefix nvdimm_ to everything in NVDIMM source files
>   2) make parsing _DSM Arg3 more clear
>   3) comment style fix
>   5) drop single used definition
>   6) fix dirty dsm buffer lost due to memory write happened on host
>   7) check dsm buffer if it is big enough to contain input data
>   8) use build_append_int_noprefix to store single value to GArray
> 
> - changes from Michael's and Igor's comments:
>   1) introduce 'nvdimm-support' parameter to control nvdimm
>      enablement and it is disabled for 2.4 and its earlier versions
>      to make live migration compatible
>   2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>      virtualization
> 
> - changes from Stefan's comments:
>   1) do endian adjustment for the buffer length
> 
> - changes from Bharata B Rao's comments:
>   1) fix compile on ppc
> 
> - others:
>   1) the buffer length is directly got from IO read rather than got
>      from dsm memory
>   2) fix dirty label data lost due to memory write happened on host
> 
> 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 (5):
>   nvdimm: implement NVDIMM device abstract
>   acpi: support specified oem table id for build_header
>   nvdimm acpi: build ACPI NFIT table
>   nvdimm acpi: build ACPI nvdimm devices
>   nvdimm: add maintain info
> 
>  MAINTAINERS                        |   7 +
>  default-configs/i386-softmmu.mak   |   2 +
>  default-configs/x86_64-softmmu.mak |   2 +
>  hw/acpi/Makefile.objs              |   1 +
>  hw/acpi/aml-build.c                |  15 +-
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/memory_hotplug.c           |   5 +
>  hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/arm/virt-acpi-build.c           |  13 +-
>  hw/i386/acpi-build.c               |  26 ++-
>  hw/mem/Makefile.objs               |   1 +
>  hw/mem/nvdimm.c                    |  46 ++++
>  include/hw/acpi/aml-build.h        |   3 +-
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  41 ++++
>  17 files changed, 645 insertions(+), 22 deletions(-)
>  create mode 100644 hw/acpi/nvdimm.c
>  create mode 100644 hw/mem/nvdimm.c
>  create mode 100644 include/hw/mem/nvdimm.h

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-30  8:51   ` Stefan Hajnoczi
  0 siblings, 0 replies; 48+ messages in thread
From: Stefan Hajnoczi @ 2015-11-30  8:51 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth

[-- Attachment #1: Type: text/plain, Size: 13984 bytes --]

On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
> This patchset can be found at:
>       https://github.com/xiaogr/qemu.git nvdimm-v8
> 
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
> 
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.
> 
> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>    memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>    -device nvdimm,memdev=mem1,id=nv1
> 
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>   1) let gethugepagesize() realize if fstat is failed instead of get
>      normal page size
>   2) rename  open_file_path to open_ram_file_path
>   3) better log the error message by using error_setg_errno
>   4) update commit in the commit log to explain hugepage detection on
>      Windows
> 
> - changes from Eduardo Habkost's comments:
>   1) use 'Error**' to collect error message for qemu_file_get_page_size()
>   2) move gethugepagesize() replacement to the same patch to make it
>      better for review
>   3) introduce qemu_get_file_size to unity the code with raw_getlength()
> 
> - changes from Stefan's comments:
>   1) check the memory region is large enough to contain DSM output
>      buffer
> 
> - changes from Eric Blake's comments:
>   1) update the shell command in the commit log to generate the patch
>      which drops 'pc-dimm' prefix
>   
> - others:
>   pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>   Eric Blake.
> 
> Changelog in v6:
> - changes from Stefan's comments:
>   1) fix code style of struct naming by CamelCase way
>   2) fix offset + length overflow when read/write label data
>   3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>      be used to replace getpagesize()
> 
> Changelog in v5:
> - changes from Michael's comments:
>   1) prefix nvdimm_ to everything in NVDIMM source files
>   2) make parsing _DSM Arg3 more clear
>   3) comment style fix
>   5) drop single used definition
>   6) fix dirty dsm buffer lost due to memory write happened on host
>   7) check dsm buffer if it is big enough to contain input data
>   8) use build_append_int_noprefix to store single value to GArray
> 
> - changes from Michael's and Igor's comments:
>   1) introduce 'nvdimm-support' parameter to control nvdimm
>      enablement and it is disabled for 2.4 and its earlier versions
>      to make live migration compatible
>   2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>      virtualization
> 
> - changes from Stefan's comments:
>   1) do endian adjustment for the buffer length
> 
> - changes from Bharata B Rao's comments:
>   1) fix compile on ppc
> 
> - others:
>   1) the buffer length is directly got from IO read rather than got
>      from dsm memory
>   2) fix dirty label data lost due to memory write happened on host
> 
> 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 (5):
>   nvdimm: implement NVDIMM device abstract
>   acpi: support specified oem table id for build_header
>   nvdimm acpi: build ACPI NFIT table
>   nvdimm acpi: build ACPI nvdimm devices
>   nvdimm: add maintain info
> 
>  MAINTAINERS                        |   7 +
>  default-configs/i386-softmmu.mak   |   2 +
>  default-configs/x86_64-softmmu.mak |   2 +
>  hw/acpi/Makefile.objs              |   1 +
>  hw/acpi/aml-build.c                |  15 +-
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/memory_hotplug.c           |   5 +
>  hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/arm/virt-acpi-build.c           |  13 +-
>  hw/i386/acpi-build.c               |  26 ++-
>  hw/mem/Makefile.objs               |   1 +
>  hw/mem/nvdimm.c                    |  46 ++++
>  include/hw/acpi/aml-build.h        |   3 +-
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  41 ++++
>  17 files changed, 645 insertions(+), 22 deletions(-)
>  create mode 100644 hw/acpi/nvdimm.c
>  create mode 100644 hw/mem/nvdimm.c
>  create mode 100644 include/hw/mem/nvdimm.h

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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

* Re: [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
  2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-30 10:30     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:30 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
> 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
> 
> Currently, we do not support any function on _DSM, that means, NVDIMM
> label data has not been supported yet
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 98c004d..abe0daa 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>      g_array_free(structures, true);
>  }
>  
> +static void nvdimm_build_common_dsm(Aml *root_dev)
> +{
> +    Aml *method, *ifctx, *function;
> +    uint8_t byte_list[1];
> +
> +    method = aml_method("NCAL", 4);

This "NCAL" needs a define as it's used
in multiple places. It's really just a DSM
implementation, right? Reflect this in the macro
name.

> +    {

What's this doing?

> +        function = aml_arg(2);
> +
> +        /*
> +         * function 0 is called to inquire what functions are supported by
> +         * OSPM
> +         */
> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
> +        byte_list[0] = 0 /* No function Supported */;
> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
> +        aml_append(method, ifctx);
> +
> +        /* No function is supported yet. */
> +        byte_list[0] = 1 /* Not Supported */;
> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
> +    }
> +    aml_append(root_dev, method);
> +}
> +
> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
> +{
> +    for (; device_list; device_list = device_list->next) {
> +        DeviceState *dev = device_list->data;
> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                           NULL);
> +        uint32_t handle = nvdimm_slot_to_handle(slot);
> +        Aml *nvdimm_dev, *method;
> +
> +        nvdimm_dev = aml_device("NV%02X", slot);
> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
> +
> +        method = aml_method("_DSM", 4);
> +        {
> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
> +        }
> +        aml_append(nvdimm_dev, method);
> +
> +        aml_append(root_dev, nvdimm_dev);
> +    }
> +}
> +
> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
> +                              GArray *table_data, GArray *linker)
> +{
> +    Aml *ssdt, *sb_scope, *dev, *method;
> +
> +    acpi_add_table(table_offsets, table_data);
> +
> +    ssdt = init_aml_allocator();
> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
> +
> +    sb_scope = aml_scope("\\_SB");
> +
> +    dev = aml_device("NVDR");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));

Pls add a comment explaining that ACPI0012 is NVDIMM root device.

Also - this will now appear for all users, e.g.
windows guests will prompt users for a driver.
Not nice if user didn't actually ask for nvdimm.

A simple solution is to default this functionality
to off by default.

> +
> +    nvdimm_build_common_dsm(dev);
> +    method = aml_method("_DSM", 4);
> +    {
> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
> +    }

Some duplication here, move above to a sub-function please.

> +    aml_append(dev, method);
> +
> +    nvdimm_build_nvdimm_devices(device_list, dev);
> +
> +    aml_append(sb_scope, dev);
> +
> +    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, "NVDIMM");
> +    free_aml_allocator();
> +}
> +
>  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>                         GArray *linker)
>  {
> @@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>          return;
>      }
>      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
>      g_slist_free(device_list);
>  }
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
@ 2015-11-30 10:30     ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:30 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
> 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
> 
> Currently, we do not support any function on _DSM, that means, NVDIMM
> label data has not been supported yet
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 98c004d..abe0daa 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>      g_array_free(structures, true);
>  }
>  
> +static void nvdimm_build_common_dsm(Aml *root_dev)
> +{
> +    Aml *method, *ifctx, *function;
> +    uint8_t byte_list[1];
> +
> +    method = aml_method("NCAL", 4);

This "NCAL" needs a define as it's used
in multiple places. It's really just a DSM
implementation, right? Reflect this in the macro
name.

> +    {

What's this doing?

> +        function = aml_arg(2);
> +
> +        /*
> +         * function 0 is called to inquire what functions are supported by
> +         * OSPM
> +         */
> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
> +        byte_list[0] = 0 /* No function Supported */;
> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
> +        aml_append(method, ifctx);
> +
> +        /* No function is supported yet. */
> +        byte_list[0] = 1 /* Not Supported */;
> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
> +    }
> +    aml_append(root_dev, method);
> +}
> +
> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
> +{
> +    for (; device_list; device_list = device_list->next) {
> +        DeviceState *dev = device_list->data;
> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                           NULL);
> +        uint32_t handle = nvdimm_slot_to_handle(slot);
> +        Aml *nvdimm_dev, *method;
> +
> +        nvdimm_dev = aml_device("NV%02X", slot);
> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
> +
> +        method = aml_method("_DSM", 4);
> +        {
> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
> +        }
> +        aml_append(nvdimm_dev, method);
> +
> +        aml_append(root_dev, nvdimm_dev);
> +    }
> +}
> +
> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
> +                              GArray *table_data, GArray *linker)
> +{
> +    Aml *ssdt, *sb_scope, *dev, *method;
> +
> +    acpi_add_table(table_offsets, table_data);
> +
> +    ssdt = init_aml_allocator();
> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
> +
> +    sb_scope = aml_scope("\\_SB");
> +
> +    dev = aml_device("NVDR");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));

Pls add a comment explaining that ACPI0012 is NVDIMM root device.

Also - this will now appear for all users, e.g.
windows guests will prompt users for a driver.
Not nice if user didn't actually ask for nvdimm.

A simple solution is to default this functionality
to off by default.

> +
> +    nvdimm_build_common_dsm(dev);
> +    method = aml_method("_DSM", 4);
> +    {
> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
> +    }

Some duplication here, move above to a sub-function please.

> +    aml_append(dev, method);
> +
> +    nvdimm_build_nvdimm_devices(device_list, dev);
> +
> +    aml_append(sb_scope, dev);
> +
> +    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, "NVDIMM");
> +    free_aml_allocator();
> +}
> +
>  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>                         GArray *linker)
>  {
> @@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>          return;
>      }
>      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
>      g_slist_free(device_list);
>  }
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
  2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-30 10:30     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:30 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Nov 16, 2015 at 06:51:01PM +0800, Xiao Guangrong wrote:
> 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
> 
> The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
> is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
> false on 2.4 and its earlier version to keep compatibility

Will need to make it false on 2.5 too.

Isn't there a device that needs to be created for this
to work?  It would be cleaned to just key off
the device presence, then we don't need compat gunk,
and further, people not using it don't get a
bunch of unused AML.


> 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/Makefile.objs              |   1 +
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/nvdimm.c                   | 382 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/i386/acpi-build.c               |   6 +
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  12 ++
>  10 files changed, 440 insertions(+), 1 deletion(-)
>  create mode 100644 hw/acpi/nvdimm.c
> 
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 4c79d3b..53fb517 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
>  CONFIG_PVPANIC=y
>  CONFIG_MEM_HOTPLUG=y
>  CONFIG_NVDIMM=y
> +CONFIG_ACPI_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 e42d2fc..766c27c 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
>  CONFIG_PVPANIC=y
>  CONFIG_MEM_HOTPLUG=y
>  CONFIG_NVDIMM=y
> +CONFIG_ACPI_NVDIMM=y
>  CONFIG_XIO3130=y
>  CONFIG_IOH3420=y
>  CONFIG_I82801B11=y
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 7d3230c..095597f 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_ACPI_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/ich9.c b/hw/acpi/ich9.c
> index 1c7fcfa..275796f 100644
> --- a/hw/acpi/ich9.c
> +++ b/hw/acpi/ich9.c
> @@ -307,6 +307,20 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
>      s->pm.acpi_memory_hotplug.is_enabled = value;
>  }
>  
> +static bool ich9_pm_get_nvdimm_support(Object *obj, Error **errp)
> +{
> +    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
> +
> +    return s->pm.nvdimm_acpi_state.is_enabled;
> +}
> +
> +static void ich9_pm_set_nvdimm_support(Object *obj, bool value, Error **errp)
> +{
> +    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
> +
> +    s->pm.nvdimm_acpi_state.is_enabled = value;
> +}
> +
>  static void ich9_pm_get_disable_s3(Object *obj, Visitor *v,
>                                     void *opaque, const char *name,
>                                     Error **errp)
> @@ -404,6 +418,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>  {
>      static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
>      pm->acpi_memory_hotplug.is_enabled = true;
> +    pm->nvdimm_acpi_state.is_enabled = true;
>      pm->disable_s3 = 0;
>      pm->disable_s4 = 0;
>      pm->s4_val = 2;
> @@ -419,6 +434,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>                               ich9_pm_get_memory_hotplug_support,
>                               ich9_pm_set_memory_hotplug_support,
>                               NULL);
> +    object_property_add_bool(obj, "nvdimm-support",
> +                             ich9_pm_get_nvdimm_support,
> +                             ich9_pm_set_nvdimm_support,
> +                             NULL);
>      object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
>                          ich9_pm_get_disable_s3,
>                          ich9_pm_set_disable_s3,
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> new file mode 100644
> index 0000000..98c004d
> --- /dev/null
> +++ b/hw/acpi/nvdimm.c
> @@ -0,0 +1,382 @@
> +/*
> + * 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 "hw/acpi/acpi.h"
> +#include "hw/acpi/aml-build.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)) {
> +        DeviceState *dev = DEVICE(obj);
> +
> +        if (dev->realized) { /* only realized NVDIMMs matter */
> +            *list = g_slist_append(*list, DEVICE(obj));
> +        }
> +    }
> +
> +    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
> +    return 0;
> +}
> +
> +/*
> + * 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.
> + */
> +static GSList *nvdimm_get_plugged_device_list(void)
> +{
> +    GSList *list = NULL;
> +
> +    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list,
> +                         &list);
> +    return list;
> +}
> +
> +#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) }
> +
> +/*
> + * define Byte Addressable Persistent Memory (PM) Region according to
> + * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
> + */
> +static const uint8_t nvdimm_nfit_spa_uuid[] =
> +      NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
> +                     0x18, 0xb7, 0x8c, 0xdb);
> +
> +/*
> + * 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.
> + *
> + * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
> + */
> +struct NvdimmNfitHeader {
> +    ACPI_TABLE_HEADER_DEF
> +    uint32_t reserved;
> +} QEMU_PACKED;
> +typedef struct NvdimmNfitHeader NvdimmNfitHeader;
> +
> +/*
> + * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
> + * Interface Table (NFIT).
> + */
> +
> +/*
> + * System Physical Address Range Structure
> + *
> + * It describes the system physical address ranges occupied by NVDIMMs and
> + * the types of the regions.
> + */
> +struct NvdimmNfitSpa {
> +    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 NvdimmNfitSpa NvdimmNfitSpa;
> +
> +/*
> + * Memory Device to System Physical Address Range Mapping Structure
> + *
> + * It enables identifying each NVDIMM region and the corresponding SPA
> + * describing the memory interleave
> + */
> +struct NvdimmNfitMemDev {
> +    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 NvdimmNfitMemDev NvdimmNfitMemDev;
> +
> +/*
> + * NVDIMM Control Region Structure
> + *
> + * It describes the NVDIMM and if applicable, Block Control Window.
> + */
> +struct NvdimmNfitControlRegion {
> +    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 NvdimmNfitControlRegion NvdimmNfitControlRegion;
> +
> +/*
> + * 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 comments of nvdimm_slot_to_spa_index(). */
> +static uint32_t nvdimm_slot_to_dcr_index(int slot)
> +{
> +    return nvdimm_slot_to_spa_index(slot) + 1;
> +}
> +
> +/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
> +static void
> +nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitSpa *nfit_spa;
> +    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
> +                                            NULL);
> +    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
> +                                            NULL);
> +    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
> +                                            NULL);
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                            NULL);
> +
> +    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
> +
> +    nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range
> +                                      Structure */);
> +    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
> +    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
> +
> +    /*
> +     * Control region is strict as all the device info, such as SN, index,
> +     * is associated with slot id.
> +     */
> +    nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for
> +                                       management during hot add/online
> +                                       operation */ |
> +                                  2 /* Data in Proximity Domain field is
> +                                       valid*/);
> +
> +    /* NUMA node. */
> +    nfit_spa->proximity_domain = cpu_to_le32(node);
> +    /* the region reported as PMEM. */
> +    memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
> +           sizeof(nvdimm_nfit_spa_uuid));
> +
> +    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(0x8ULL /* EFI_MEMORY_WB */ |
> +                                     0x8000ULL /* EFI_MEMORY_NV */);
> +}
> +
> +/*
> + * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping
> + * Structure
> + */
> +static void
> +nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitMemDev *nfit_memdev;
> +    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
> +                                            NULL);
> +    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
> +                                            NULL);
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                            NULL);
> +    uint32_t handle = nvdimm_slot_to_handle(slot);
> +
> +    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
> +
> +    nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address
> +                                         Range Map Structure*/);
> +    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);
> +}
> +
> +/*
> + * ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure.
> + */
> +static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitControlRegion *nfit_dcr;
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                       NULL);
> +    uint32_t sn = nvdimm_slot_to_sn(slot);
> +
> +    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
> +
> +    nfit_dcr->type = cpu_to_le16(4 /* NVDIMM Control Region Structure */);
> +    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(1 /* Current Revision supported
> +                                             in ACPI 6.0 is 1. */);
> +    nfit_dcr->serial_number = cpu_to_le32(sn);
> +    nfit_dcr->fic = cpu_to_le16(0x201 /* Format Interface Code. See Chapter
> +                                         2: NVDIMM Device Specific Method
> +                                         (DSM) in DSM Spec Rev1.*/);
> +}
> +
> +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) {
> +        DeviceState *dev = device_list->data;
> +
> +        /* build System Physical Address Range Structure. */
> +        nvdimm_build_structure_spa(structures, dev);
> +
> +        /*
> +         * build Memory Device to System Physical Address Range Mapping
> +         * Structure.
> +         */
> +        nvdimm_build_structure_memdev(structures, dev);
> +
> +        /* build NVDIMM Control Region Structure. */
> +        nvdimm_build_structure_dcr(structures, dev);
> +    }
> +
> +    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(NvdimmNfitHeader));
> +    /* NVDIMM device structures. */
> +    g_array_append_vals(table_data, structures->data, structures->len);
> +
> +    build_header(linker, table_data, header, "NFIT",
> +                 sizeof(NvdimmNfitHeader) + structures->len, 1, NULL);
> +    g_array_free(structures, true);
> +}
> +
> +void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
> +                       GArray *linker)
> +{
> +    GSList *device_list;
> +
> +    /* no NVDIMM device is plugged. */
> +    device_list = nvdimm_get_plugged_device_list();
> +    if (!device_list) {
> +        return;
> +    }
> +    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    g_slist_free(device_list);
> +}
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index 2cd2fee..33e24cf 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -34,6 +34,7 @@
>  #include "hw/acpi/cpu_hotplug.h"
>  #include "hw/hotplug.h"
>  #include "hw/mem/pc-dimm.h"
> +#include "hw/mem/nvdimm.h"
>  #include "hw/acpi/memory_hotplug.h"
>  #include "hw/acpi/acpi_dev_interface.h"
>  #include "hw/xen/xen.h"
> @@ -86,6 +87,7 @@ typedef struct PIIX4PMState {
>      AcpiCpuHotplug gpe_cpu;
>  
>      MemHotplugState acpi_memory_hotplug;
> +    NVDIMMAcpiState nvdimm_acpi_state;
>  } PIIX4PMState;
>  
>  #define TYPE_PIIX4_PM "PIIX4_PM"
> @@ -592,6 +594,8 @@ static Property piix4_pm_properties[] = {
>                       use_acpi_pci_hotplug, true),
>      DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
>                       acpi_memory_hotplug.is_enabled, true),
> +    DEFINE_PROP_BOOL("nvdimm-support", PIIX4PMState,
> +                     nvdimm_acpi_state.is_enabled, true),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 215b58c..30ba594 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -90,6 +90,7 @@ typedef struct AcpiPmInfo {
>      bool s3_disabled;
>      bool s4_disabled;
>      bool pcihp_bridge_en;
> +    bool nvdimm_support;
>      uint8_t s4_val;
>      uint16_t sci_int;
>      uint8_t acpi_enable_cmd;
> @@ -231,6 +232,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
>      pm->pcihp_bridge_en =
>          object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
>                                   NULL);
> +    pm->nvdimm_support = object_property_get_bool(obj, "nvdimm-support", NULL);
>  }
>  
>  static void acpi_get_misc_info(AcpiMiscInfo *info)
> @@ -1742,6 +1744,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
>          build_dmar_q35(tables_blob, tables->linker);
>      }
>  
> +    if (pm.nvdimm_support) {
> +        nvdimm_build_acpi(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/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
> index 345fd8d..2c6f350 100644
> --- a/include/hw/acpi/ich9.h
> +++ b/include/hw/acpi/ich9.h
> @@ -26,6 +26,7 @@
>  #include "hw/acpi/memory_hotplug.h"
>  #include "hw/acpi/acpi_dev_interface.h"
>  #include "hw/acpi/tco.h"
> +#include "hw/mem/nvdimm.h"
>  
>  typedef struct ICH9LPCPMRegs {
>      /*
> @@ -52,6 +53,8 @@ typedef struct ICH9LPCPMRegs {
>  
>      MemHotplugState acpi_memory_hotplug;
>  
> +    NVDIMMAcpiState nvdimm_acpi_state;
> +
>      uint8_t disable_s3;
>      uint8_t disable_s4;
>      uint8_t s4_val;
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 4bbc0ff..9c9576b 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -347,7 +347,17 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
>              .driver   = "qemu32" "-" TYPE_X86_CPU,\
>              .property = "popcnt",\
>              .value    = "on",\
> -        },
> +        },\
> +        {\
> +            .driver   = "PIIX4_PM",\
> +            .property = "nvdimm-support",\
> +            .value    = "off",\
> +        },\
> +        {\
> +            .driver   = "ICH9-LPC",\
> +            .property = "nvdimm-support",\
> +            .value    = "off",\
> +       },
>  
>  #define PC_COMPAT_2_3 \
>          PC_COMPAT_2_4 \
> diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
> index dbfa8d6..6c29fff 100644
> --- a/include/hw/mem/nvdimm.h
> +++ b/include/hw/mem/nvdimm.h
> @@ -26,4 +26,16 @@
>  #include "hw/mem/pc-dimm.h"
>  
>  #define TYPE_NVDIMM      "nvdimm"
> +
> +/*
> + * AcpiNVDIMMState:
> + * @is_enabled: detect if NVDIMM support is enabled.
> + */
> +struct NVDIMMAcpiState {
> +    bool is_enabled;
> +};
> +typedef struct NVDIMMAcpiState NVDIMMAcpiState;
> +
> +void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
> +                       GArray *linker);
>  #endif
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [Qemu-devel] [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
@ 2015-11-30 10:30     ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:30 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Nov 16, 2015 at 06:51:01PM +0800, Xiao Guangrong wrote:
> 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
> 
> The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
> is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
> false on 2.4 and its earlier version to keep compatibility

Will need to make it false on 2.5 too.

Isn't there a device that needs to be created for this
to work?  It would be cleaned to just key off
the device presence, then we don't need compat gunk,
and further, people not using it don't get a
bunch of unused AML.


> 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/Makefile.objs              |   1 +
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/nvdimm.c                   | 382 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/i386/acpi-build.c               |   6 +
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  12 ++
>  10 files changed, 440 insertions(+), 1 deletion(-)
>  create mode 100644 hw/acpi/nvdimm.c
> 
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 4c79d3b..53fb517 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
>  CONFIG_PVPANIC=y
>  CONFIG_MEM_HOTPLUG=y
>  CONFIG_NVDIMM=y
> +CONFIG_ACPI_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 e42d2fc..766c27c 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -47,6 +47,7 @@ CONFIG_IOAPIC=y
>  CONFIG_PVPANIC=y
>  CONFIG_MEM_HOTPLUG=y
>  CONFIG_NVDIMM=y
> +CONFIG_ACPI_NVDIMM=y
>  CONFIG_XIO3130=y
>  CONFIG_IOH3420=y
>  CONFIG_I82801B11=y
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 7d3230c..095597f 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_ACPI_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/ich9.c b/hw/acpi/ich9.c
> index 1c7fcfa..275796f 100644
> --- a/hw/acpi/ich9.c
> +++ b/hw/acpi/ich9.c
> @@ -307,6 +307,20 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
>      s->pm.acpi_memory_hotplug.is_enabled = value;
>  }
>  
> +static bool ich9_pm_get_nvdimm_support(Object *obj, Error **errp)
> +{
> +    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
> +
> +    return s->pm.nvdimm_acpi_state.is_enabled;
> +}
> +
> +static void ich9_pm_set_nvdimm_support(Object *obj, bool value, Error **errp)
> +{
> +    ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
> +
> +    s->pm.nvdimm_acpi_state.is_enabled = value;
> +}
> +
>  static void ich9_pm_get_disable_s3(Object *obj, Visitor *v,
>                                     void *opaque, const char *name,
>                                     Error **errp)
> @@ -404,6 +418,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>  {
>      static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
>      pm->acpi_memory_hotplug.is_enabled = true;
> +    pm->nvdimm_acpi_state.is_enabled = true;
>      pm->disable_s3 = 0;
>      pm->disable_s4 = 0;
>      pm->s4_val = 2;
> @@ -419,6 +434,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
>                               ich9_pm_get_memory_hotplug_support,
>                               ich9_pm_set_memory_hotplug_support,
>                               NULL);
> +    object_property_add_bool(obj, "nvdimm-support",
> +                             ich9_pm_get_nvdimm_support,
> +                             ich9_pm_set_nvdimm_support,
> +                             NULL);
>      object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
>                          ich9_pm_get_disable_s3,
>                          ich9_pm_set_disable_s3,
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> new file mode 100644
> index 0000000..98c004d
> --- /dev/null
> +++ b/hw/acpi/nvdimm.c
> @@ -0,0 +1,382 @@
> +/*
> + * 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 "hw/acpi/acpi.h"
> +#include "hw/acpi/aml-build.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)) {
> +        DeviceState *dev = DEVICE(obj);
> +
> +        if (dev->realized) { /* only realized NVDIMMs matter */
> +            *list = g_slist_append(*list, DEVICE(obj));
> +        }
> +    }
> +
> +    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);
> +    return 0;
> +}
> +
> +/*
> + * 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.
> + */
> +static GSList *nvdimm_get_plugged_device_list(void)
> +{
> +    GSList *list = NULL;
> +
> +    object_child_foreach(qdev_get_machine(), nvdimm_plugged_device_list,
> +                         &list);
> +    return list;
> +}
> +
> +#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) }
> +
> +/*
> + * define Byte Addressable Persistent Memory (PM) Region according to
> + * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
> + */
> +static const uint8_t nvdimm_nfit_spa_uuid[] =
> +      NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
> +                     0x18, 0xb7, 0x8c, 0xdb);
> +
> +/*
> + * 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.
> + *
> + * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
> + */
> +struct NvdimmNfitHeader {
> +    ACPI_TABLE_HEADER_DEF
> +    uint32_t reserved;
> +} QEMU_PACKED;
> +typedef struct NvdimmNfitHeader NvdimmNfitHeader;
> +
> +/*
> + * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
> + * Interface Table (NFIT).
> + */
> +
> +/*
> + * System Physical Address Range Structure
> + *
> + * It describes the system physical address ranges occupied by NVDIMMs and
> + * the types of the regions.
> + */
> +struct NvdimmNfitSpa {
> +    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 NvdimmNfitSpa NvdimmNfitSpa;
> +
> +/*
> + * Memory Device to System Physical Address Range Mapping Structure
> + *
> + * It enables identifying each NVDIMM region and the corresponding SPA
> + * describing the memory interleave
> + */
> +struct NvdimmNfitMemDev {
> +    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 NvdimmNfitMemDev NvdimmNfitMemDev;
> +
> +/*
> + * NVDIMM Control Region Structure
> + *
> + * It describes the NVDIMM and if applicable, Block Control Window.
> + */
> +struct NvdimmNfitControlRegion {
> +    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 NvdimmNfitControlRegion NvdimmNfitControlRegion;
> +
> +/*
> + * 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 comments of nvdimm_slot_to_spa_index(). */
> +static uint32_t nvdimm_slot_to_dcr_index(int slot)
> +{
> +    return nvdimm_slot_to_spa_index(slot) + 1;
> +}
> +
> +/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
> +static void
> +nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitSpa *nfit_spa;
> +    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
> +                                            NULL);
> +    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
> +                                            NULL);
> +    uint32_t node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP,
> +                                            NULL);
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                            NULL);
> +
> +    nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
> +
> +    nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range
> +                                      Structure */);
> +    nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
> +    nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
> +
> +    /*
> +     * Control region is strict as all the device info, such as SN, index,
> +     * is associated with slot id.
> +     */
> +    nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for
> +                                       management during hot add/online
> +                                       operation */ |
> +                                  2 /* Data in Proximity Domain field is
> +                                       valid*/);
> +
> +    /* NUMA node. */
> +    nfit_spa->proximity_domain = cpu_to_le32(node);
> +    /* the region reported as PMEM. */
> +    memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
> +           sizeof(nvdimm_nfit_spa_uuid));
> +
> +    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(0x8ULL /* EFI_MEMORY_WB */ |
> +                                     0x8000ULL /* EFI_MEMORY_NV */);
> +}
> +
> +/*
> + * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping
> + * Structure
> + */
> +static void
> +nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitMemDev *nfit_memdev;
> +    uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
> +                                            NULL);
> +    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
> +                                            NULL);
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                            NULL);
> +    uint32_t handle = nvdimm_slot_to_handle(slot);
> +
> +    nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
> +
> +    nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address
> +                                         Range Map Structure*/);
> +    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);
> +}
> +
> +/*
> + * ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure.
> + */
> +static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
> +{
> +    NvdimmNfitControlRegion *nfit_dcr;
> +    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                       NULL);
> +    uint32_t sn = nvdimm_slot_to_sn(slot);
> +
> +    nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
> +
> +    nfit_dcr->type = cpu_to_le16(4 /* NVDIMM Control Region Structure */);
> +    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(1 /* Current Revision supported
> +                                             in ACPI 6.0 is 1. */);
> +    nfit_dcr->serial_number = cpu_to_le32(sn);
> +    nfit_dcr->fic = cpu_to_le16(0x201 /* Format Interface Code. See Chapter
> +                                         2: NVDIMM Device Specific Method
> +                                         (DSM) in DSM Spec Rev1.*/);
> +}
> +
> +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) {
> +        DeviceState *dev = device_list->data;
> +
> +        /* build System Physical Address Range Structure. */
> +        nvdimm_build_structure_spa(structures, dev);
> +
> +        /*
> +         * build Memory Device to System Physical Address Range Mapping
> +         * Structure.
> +         */
> +        nvdimm_build_structure_memdev(structures, dev);
> +
> +        /* build NVDIMM Control Region Structure. */
> +        nvdimm_build_structure_dcr(structures, dev);
> +    }
> +
> +    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(NvdimmNfitHeader));
> +    /* NVDIMM device structures. */
> +    g_array_append_vals(table_data, structures->data, structures->len);
> +
> +    build_header(linker, table_data, header, "NFIT",
> +                 sizeof(NvdimmNfitHeader) + structures->len, 1, NULL);
> +    g_array_free(structures, true);
> +}
> +
> +void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
> +                       GArray *linker)
> +{
> +    GSList *device_list;
> +
> +    /* no NVDIMM device is plugged. */
> +    device_list = nvdimm_get_plugged_device_list();
> +    if (!device_list) {
> +        return;
> +    }
> +    nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    g_slist_free(device_list);
> +}
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index 2cd2fee..33e24cf 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -34,6 +34,7 @@
>  #include "hw/acpi/cpu_hotplug.h"
>  #include "hw/hotplug.h"
>  #include "hw/mem/pc-dimm.h"
> +#include "hw/mem/nvdimm.h"
>  #include "hw/acpi/memory_hotplug.h"
>  #include "hw/acpi/acpi_dev_interface.h"
>  #include "hw/xen/xen.h"
> @@ -86,6 +87,7 @@ typedef struct PIIX4PMState {
>      AcpiCpuHotplug gpe_cpu;
>  
>      MemHotplugState acpi_memory_hotplug;
> +    NVDIMMAcpiState nvdimm_acpi_state;
>  } PIIX4PMState;
>  
>  #define TYPE_PIIX4_PM "PIIX4_PM"
> @@ -592,6 +594,8 @@ static Property piix4_pm_properties[] = {
>                       use_acpi_pci_hotplug, true),
>      DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
>                       acpi_memory_hotplug.is_enabled, true),
> +    DEFINE_PROP_BOOL("nvdimm-support", PIIX4PMState,
> +                     nvdimm_acpi_state.is_enabled, true),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 215b58c..30ba594 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -90,6 +90,7 @@ typedef struct AcpiPmInfo {
>      bool s3_disabled;
>      bool s4_disabled;
>      bool pcihp_bridge_en;
> +    bool nvdimm_support;
>      uint8_t s4_val;
>      uint16_t sci_int;
>      uint8_t acpi_enable_cmd;
> @@ -231,6 +232,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
>      pm->pcihp_bridge_en =
>          object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support",
>                                   NULL);
> +    pm->nvdimm_support = object_property_get_bool(obj, "nvdimm-support", NULL);
>  }
>  
>  static void acpi_get_misc_info(AcpiMiscInfo *info)
> @@ -1742,6 +1744,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
>          build_dmar_q35(tables_blob, tables->linker);
>      }
>  
> +    if (pm.nvdimm_support) {
> +        nvdimm_build_acpi(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/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
> index 345fd8d..2c6f350 100644
> --- a/include/hw/acpi/ich9.h
> +++ b/include/hw/acpi/ich9.h
> @@ -26,6 +26,7 @@
>  #include "hw/acpi/memory_hotplug.h"
>  #include "hw/acpi/acpi_dev_interface.h"
>  #include "hw/acpi/tco.h"
> +#include "hw/mem/nvdimm.h"
>  
>  typedef struct ICH9LPCPMRegs {
>      /*
> @@ -52,6 +53,8 @@ typedef struct ICH9LPCPMRegs {
>  
>      MemHotplugState acpi_memory_hotplug;
>  
> +    NVDIMMAcpiState nvdimm_acpi_state;
> +
>      uint8_t disable_s3;
>      uint8_t disable_s4;
>      uint8_t s4_val;
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 4bbc0ff..9c9576b 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -347,7 +347,17 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
>              .driver   = "qemu32" "-" TYPE_X86_CPU,\
>              .property = "popcnt",\
>              .value    = "on",\
> -        },
> +        },\
> +        {\
> +            .driver   = "PIIX4_PM",\
> +            .property = "nvdimm-support",\
> +            .value    = "off",\
> +        },\
> +        {\
> +            .driver   = "ICH9-LPC",\
> +            .property = "nvdimm-support",\
> +            .value    = "off",\
> +       },
>  
>  #define PC_COMPAT_2_3 \
>          PC_COMPAT_2_4 \
> diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
> index dbfa8d6..6c29fff 100644
> --- a/include/hw/mem/nvdimm.h
> +++ b/include/hw/mem/nvdimm.h
> @@ -26,4 +26,16 @@
>  #include "hw/mem/pc-dimm.h"
>  
>  #define TYPE_NVDIMM      "nvdimm"
> +
> +/*
> + * AcpiNVDIMMState:
> + * @is_enabled: detect if NVDIMM support is enabled.
> + */
> +struct NVDIMMAcpiState {
> +    bool is_enabled;
> +};
> +typedef struct NVDIMMAcpiState NVDIMMAcpiState;
> +
> +void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
> +                       GArray *linker);
>  #endif
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
  2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-30 10:32     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:32 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
> NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices

Forgot to mention:

Pls put spec info in code comments near
relevant functions, not just the log.

> 
> 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
> 
> Currently, we do not support any function on _DSM, that means, NVDIMM
> label data has not been supported yet
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 98c004d..abe0daa 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>      g_array_free(structures, true);
>  }
>  
> +static void nvdimm_build_common_dsm(Aml *root_dev)
> +{
> +    Aml *method, *ifctx, *function;
> +    uint8_t byte_list[1];
> +
> +    method = aml_method("NCAL", 4);
> +    {
> +        function = aml_arg(2);
> +
> +        /*
> +         * function 0 is called to inquire what functions are supported by
> +         * OSPM
> +         */
> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
> +        byte_list[0] = 0 /* No function Supported */;
> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
> +        aml_append(method, ifctx);
> +
> +        /* No function is supported yet. */
> +        byte_list[0] = 1 /* Not Supported */;
> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
> +    }
> +    aml_append(root_dev, method);
> +}
> +
> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
> +{
> +    for (; device_list; device_list = device_list->next) {
> +        DeviceState *dev = device_list->data;
> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                           NULL);
> +        uint32_t handle = nvdimm_slot_to_handle(slot);
> +        Aml *nvdimm_dev, *method;
> +
> +        nvdimm_dev = aml_device("NV%02X", slot);
> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
> +
> +        method = aml_method("_DSM", 4);
> +        {
> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
> +        }
> +        aml_append(nvdimm_dev, method);
> +
> +        aml_append(root_dev, nvdimm_dev);
> +    }
> +}
> +
> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
> +                              GArray *table_data, GArray *linker)
> +{
> +    Aml *ssdt, *sb_scope, *dev, *method;

So why don't we skip this completely if device list is empty?

> +
> +    acpi_add_table(table_offsets, table_data);
> +
> +    ssdt = init_aml_allocator();
> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
> +
> +    sb_scope = aml_scope("\\_SB");
> +
> +    dev = aml_device("NVDR");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
> +
> +    nvdimm_build_common_dsm(dev);
> +    method = aml_method("_DSM", 4);
> +    {
> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
> +    }
> +    aml_append(dev, method);
> +
> +    nvdimm_build_nvdimm_devices(device_list, dev);
> +
> +    aml_append(sb_scope, dev);
> +
> +    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, "NVDIMM");
> +    free_aml_allocator();
> +}
> +
>  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>                         GArray *linker)
>  {
> @@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>          return;
>      }
>      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
>      g_slist_free(device_list);
>  }
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
@ 2015-11-30 10:32     ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:32 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
> NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices

Forgot to mention:

Pls put spec info in code comments near
relevant functions, not just the log.

> 
> 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
> 
> Currently, we do not support any function on _DSM, that means, NVDIMM
> label data has not been supported yet
> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 98c004d..abe0daa 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>      g_array_free(structures, true);
>  }
>  
> +static void nvdimm_build_common_dsm(Aml *root_dev)
> +{
> +    Aml *method, *ifctx, *function;
> +    uint8_t byte_list[1];
> +
> +    method = aml_method("NCAL", 4);
> +    {
> +        function = aml_arg(2);
> +
> +        /*
> +         * function 0 is called to inquire what functions are supported by
> +         * OSPM
> +         */
> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
> +        byte_list[0] = 0 /* No function Supported */;
> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
> +        aml_append(method, ifctx);
> +
> +        /* No function is supported yet. */
> +        byte_list[0] = 1 /* Not Supported */;
> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
> +    }
> +    aml_append(root_dev, method);
> +}
> +
> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
> +{
> +    for (; device_list; device_list = device_list->next) {
> +        DeviceState *dev = device_list->data;
> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
> +                                           NULL);
> +        uint32_t handle = nvdimm_slot_to_handle(slot);
> +        Aml *nvdimm_dev, *method;
> +
> +        nvdimm_dev = aml_device("NV%02X", slot);
> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
> +
> +        method = aml_method("_DSM", 4);
> +        {
> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
> +        }
> +        aml_append(nvdimm_dev, method);
> +
> +        aml_append(root_dev, nvdimm_dev);
> +    }
> +}
> +
> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
> +                              GArray *table_data, GArray *linker)
> +{
> +    Aml *ssdt, *sb_scope, *dev, *method;

So why don't we skip this completely if device list is empty?

> +
> +    acpi_add_table(table_offsets, table_data);
> +
> +    ssdt = init_aml_allocator();
> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
> +
> +    sb_scope = aml_scope("\\_SB");
> +
> +    dev = aml_device("NVDR");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
> +
> +    nvdimm_build_common_dsm(dev);
> +    method = aml_method("_DSM", 4);
> +    {
> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
> +    }
> +    aml_append(dev, method);
> +
> +    nvdimm_build_nvdimm_devices(device_list, dev);
> +
> +    aml_append(sb_scope, dev);
> +
> +    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, "NVDIMM");
> +    free_aml_allocator();
> +}
> +
>  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>                         GArray *linker)
>  {
> @@ -378,5 +462,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
>          return;
>      }
>      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
> +    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
>      g_slist_free(device_list);
>  }
> -- 
> 1.8.3.1
> 
> --
> 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] 48+ messages in thread

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-11-30 10:38   ` Michael S. Tsirkin
  -1 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:38 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel

On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
> This patchset can be found at:
>       https://github.com/xiaogr/qemu.git nvdimm-v8
> 
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
> 
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.

Finally found some time to review this.  Very nice, this is making good
progress, and I think to split it like this is a great idea.  I sent
some comments, most of them minor.

Thanks!

> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>    memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>    -device nvdimm,memdev=mem1,id=nv1
> 
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>   1) let gethugepagesize() realize if fstat is failed instead of get
>      normal page size
>   2) rename  open_file_path to open_ram_file_path
>   3) better log the error message by using error_setg_errno
>   4) update commit in the commit log to explain hugepage detection on
>      Windows
> 
> - changes from Eduardo Habkost's comments:
>   1) use 'Error**' to collect error message for qemu_file_get_page_size()
>   2) move gethugepagesize() replacement to the same patch to make it
>      better for review
>   3) introduce qemu_get_file_size to unity the code with raw_getlength()
> 
> - changes from Stefan's comments:
>   1) check the memory region is large enough to contain DSM output
>      buffer
> 
> - changes from Eric Blake's comments:
>   1) update the shell command in the commit log to generate the patch
>      which drops 'pc-dimm' prefix
>   
> - others:
>   pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>   Eric Blake.
> 
> Changelog in v6:
> - changes from Stefan's comments:
>   1) fix code style of struct naming by CamelCase way
>   2) fix offset + length overflow when read/write label data
>   3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>      be used to replace getpagesize()
> 
> Changelog in v5:
> - changes from Michael's comments:
>   1) prefix nvdimm_ to everything in NVDIMM source files
>   2) make parsing _DSM Arg3 more clear
>   3) comment style fix
>   5) drop single used definition
>   6) fix dirty dsm buffer lost due to memory write happened on host
>   7) check dsm buffer if it is big enough to contain input data
>   8) use build_append_int_noprefix to store single value to GArray
> 
> - changes from Michael's and Igor's comments:
>   1) introduce 'nvdimm-support' parameter to control nvdimm
>      enablement and it is disabled for 2.4 and its earlier versions
>      to make live migration compatible
>   2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>      virtualization
> 
> - changes from Stefan's comments:
>   1) do endian adjustment for the buffer length
> 
> - changes from Bharata B Rao's comments:
>   1) fix compile on ppc
> 
> - others:
>   1) the buffer length is directly got from IO read rather than got
>      from dsm memory
>   2) fix dirty label data lost due to memory write happened on host
> 
> 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 (5):
>   nvdimm: implement NVDIMM device abstract
>   acpi: support specified oem table id for build_header
>   nvdimm acpi: build ACPI NFIT table
>   nvdimm acpi: build ACPI nvdimm devices
>   nvdimm: add maintain info
> 
>  MAINTAINERS                        |   7 +
>  default-configs/i386-softmmu.mak   |   2 +
>  default-configs/x86_64-softmmu.mak |   2 +
>  hw/acpi/Makefile.objs              |   1 +
>  hw/acpi/aml-build.c                |  15 +-
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/memory_hotplug.c           |   5 +
>  hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/arm/virt-acpi-build.c           |  13 +-
>  hw/i386/acpi-build.c               |  26 ++-
>  hw/mem/Makefile.objs               |   1 +
>  hw/mem/nvdimm.c                    |  46 ++++
>  include/hw/acpi/aml-build.h        |   3 +-
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  41 ++++
>  17 files changed, 645 insertions(+), 22 deletions(-)
>  create mode 100644 hw/acpi/nvdimm.c
>  create mode 100644 hw/mem/nvdimm.c
>  create mode 100644 include/hw/mem/nvdimm.h
> 
> -- 
> 1.8.3.1

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-30 10:38   ` Michael S. Tsirkin
  0 siblings, 0 replies; 48+ messages in thread
From: Michael S. Tsirkin @ 2015-11-30 10:38 UTC (permalink / raw)
  To: Xiao Guangrong
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth

On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
> This patchset can be found at:
>       https://github.com/xiaogr/qemu.git nvdimm-v8
> 
> It is based on pci branch on Michael's tree and the top commit is:
> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
> 
> Changelog in v8:
> We split the long patch series into the small parts, as you see now, this
> is the first part which enables NVDIMM without label data support.

Finally found some time to review this.  Very nice, this is making good
progress, and I think to split it like this is a great idea.  I sent
some comments, most of them minor.

Thanks!

> The command line has been changed because some patches simplifying the
> things have not been included into this series, you should specify the
> file size exactly using the parameters as follows:
>    memory-backend-file,id=mem1,share,mem-path=/tmp/nvdimm1,size=10G \
>    -device nvdimm,memdev=mem1,id=nv1
> 
> Changelog in v7:
> - changes from Vladimir Sementsov-Ogievskiy's comments:
>   1) let gethugepagesize() realize if fstat is failed instead of get
>      normal page size
>   2) rename  open_file_path to open_ram_file_path
>   3) better log the error message by using error_setg_errno
>   4) update commit in the commit log to explain hugepage detection on
>      Windows
> 
> - changes from Eduardo Habkost's comments:
>   1) use 'Error**' to collect error message for qemu_file_get_page_size()
>   2) move gethugepagesize() replacement to the same patch to make it
>      better for review
>   3) introduce qemu_get_file_size to unity the code with raw_getlength()
> 
> - changes from Stefan's comments:
>   1) check the memory region is large enough to contain DSM output
>      buffer
> 
> - changes from Eric Blake's comments:
>   1) update the shell command in the commit log to generate the patch
>      which drops 'pc-dimm' prefix
>   
> - others:
>   pick up Reviewed-by from Stefan, Vladimir Sementsov-Ogievskiy, and
>   Eric Blake.
> 
> Changelog in v6:
> - changes from Stefan's comments:
>   1) fix code style of struct naming by CamelCase way
>   2) fix offset + length overflow when read/write label data
>   3) compile hw/acpi/nvdimm.c for per target so that TARGET_PAGE_SIZE can
>      be used to replace getpagesize()
> 
> Changelog in v5:
> - changes from Michael's comments:
>   1) prefix nvdimm_ to everything in NVDIMM source files
>   2) make parsing _DSM Arg3 more clear
>   3) comment style fix
>   5) drop single used definition
>   6) fix dirty dsm buffer lost due to memory write happened on host
>   7) check dsm buffer if it is big enough to contain input data
>   8) use build_append_int_noprefix to store single value to GArray
> 
> - changes from Michael's and Igor's comments:
>   1) introduce 'nvdimm-support' parameter to control nvdimm
>      enablement and it is disabled for 2.4 and its earlier versions
>      to make live migration compatible
>   2) only reserve 1 RAM page and 4 bytes IO Port for NVDIMM ACPI
>      virtualization
> 
> - changes from Stefan's comments:
>   1) do endian adjustment for the buffer length
> 
> - changes from Bharata B Rao's comments:
>   1) fix compile on ppc
> 
> - others:
>   1) the buffer length is directly got from IO read rather than got
>      from dsm memory
>   2) fix dirty label data lost due to memory write happened on host
> 
> 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 (5):
>   nvdimm: implement NVDIMM device abstract
>   acpi: support specified oem table id for build_header
>   nvdimm acpi: build ACPI NFIT table
>   nvdimm acpi: build ACPI nvdimm devices
>   nvdimm: add maintain info
> 
>  MAINTAINERS                        |   7 +
>  default-configs/i386-softmmu.mak   |   2 +
>  default-configs/x86_64-softmmu.mak |   2 +
>  hw/acpi/Makefile.objs              |   1 +
>  hw/acpi/aml-build.c                |  15 +-
>  hw/acpi/ich9.c                     |  19 ++
>  hw/acpi/memory_hotplug.c           |   5 +
>  hw/acpi/nvdimm.c                   | 467 +++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c                    |   4 +
>  hw/arm/virt-acpi-build.c           |  13 +-
>  hw/i386/acpi-build.c               |  26 ++-
>  hw/mem/Makefile.objs               |   1 +
>  hw/mem/nvdimm.c                    |  46 ++++
>  include/hw/acpi/aml-build.h        |   3 +-
>  include/hw/acpi/ich9.h             |   3 +
>  include/hw/i386/pc.h               |  12 +-
>  include/hw/mem/nvdimm.h            |  41 ++++
>  17 files changed, 645 insertions(+), 22 deletions(-)
>  create mode 100644 hw/acpi/nvdimm.c
>  create mode 100644 hw/mem/nvdimm.c
>  create mode 100644 include/hw/mem/nvdimm.h
> 
> -- 
> 1.8.3.1

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

* Re: [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
  2015-11-30 10:30     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-11-30 12:21       ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:21 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 11/30/2015 06:30 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
>> 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
>>
>> Currently, we do not support any function on _DSM, that means, NVDIMM
>> label data has not been supported yet
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 85 insertions(+)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index 98c004d..abe0daa 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>>       g_array_free(structures, true);
>>   }
>>
>> +static void nvdimm_build_common_dsm(Aml *root_dev)
>> +{
>> +    Aml *method, *ifctx, *function;
>> +    uint8_t byte_list[1];
>> +
>> +    method = aml_method("NCAL", 4);
>
> This "NCAL" needs a define as it's used
> in multiple places. It's really just a DSM
> implementation, right? Reflect this in the macro
> name.
>

Yes, it is a common DSM method used by both root device and nvdimm devices.
I will do it like this:

#define NVDIMM_COMMON_DSM	"NCAL"

>> +    {
>
> What's this doing?
>

It just a reminder that the code containing in this braces is a DSM body like
a C function. However, i do not have strong opinion on it, will drop this style
if you dislike it.

>> +        function = aml_arg(2);
>> +
>> +        /*
>> +         * function 0 is called to inquire what functions are supported by
>> +         * OSPM
>> +         */
>> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
>> +        byte_list[0] = 0 /* No function Supported */;
>> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
>> +        aml_append(method, ifctx);
>> +
>> +        /* No function is supported yet. */
>> +        byte_list[0] = 1 /* Not Supported */;
>> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
>> +    }
>> +    aml_append(root_dev, method);
>> +}
>> +
>> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
>> +{
>> +    for (; device_list; device_list = device_list->next) {
>> +        DeviceState *dev = device_list->data;
>> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
>> +                                           NULL);
>> +        uint32_t handle = nvdimm_slot_to_handle(slot);
>> +        Aml *nvdimm_dev, *method;
>> +
>> +        nvdimm_dev = aml_device("NV%02X", slot);
>> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
>> +
>> +        method = aml_method("_DSM", 4);
>> +        {
>> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
>> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
>> +        }
>> +        aml_append(nvdimm_dev, method);
>> +
>> +        aml_append(root_dev, nvdimm_dev);
>> +    }
>> +}
>> +
>> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
>> +                              GArray *table_data, GArray *linker)
>> +{
>> +    Aml *ssdt, *sb_scope, *dev, *method;
>> +
>> +    acpi_add_table(table_offsets, table_data);
>> +
>> +    ssdt = init_aml_allocator();
>> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
>> +
>> +    sb_scope = aml_scope("\\_SB");
>> +
>> +    dev = aml_device("NVDR");
>> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
>
> Pls add a comment explaining that ACPI0012 is NVDIMM root device.

Okay, will add these comment:

/*
  * NVDIMM is introduced in ACPI 6.0 9.20 NVDIMM Devices 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.
  */

>
> Also - this will now appear for all users, e.g.
> windows guests will prompt users for a driver.
> Not nice if user didn't actually ask for nvdimm.
>
> A simple solution is to default this functionality
> to off by default.
>

Okay, will disable nvdimm on default in the next version.

>> +
>> +    nvdimm_build_common_dsm(dev);
>> +    method = aml_method("_DSM", 4);
>> +    {
>> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
>> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
>> +    }
>
> Some duplication here, move above to a sub-function please.

Okay, will add a function named nvdimm_build_device_dsm() to do these
things.

Thanks!

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

* Re: [Qemu-devel] [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
@ 2015-11-30 12:21       ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:21 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 11/30/2015 06:30 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
>> 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
>>
>> Currently, we do not support any function on _DSM, that means, NVDIMM
>> label data has not been supported yet
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>   hw/acpi/nvdimm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 85 insertions(+)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index 98c004d..abe0daa 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -367,6 +367,90 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
>>       g_array_free(structures, true);
>>   }
>>
>> +static void nvdimm_build_common_dsm(Aml *root_dev)
>> +{
>> +    Aml *method, *ifctx, *function;
>> +    uint8_t byte_list[1];
>> +
>> +    method = aml_method("NCAL", 4);
>
> This "NCAL" needs a define as it's used
> in multiple places. It's really just a DSM
> implementation, right? Reflect this in the macro
> name.
>

Yes, it is a common DSM method used by both root device and nvdimm devices.
I will do it like this:

#define NVDIMM_COMMON_DSM	"NCAL"

>> +    {
>
> What's this doing?
>

It just a reminder that the code containing in this braces is a DSM body like
a C function. However, i do not have strong opinion on it, will drop this style
if you dislike it.

>> +        function = aml_arg(2);
>> +
>> +        /*
>> +         * function 0 is called to inquire what functions are supported by
>> +         * OSPM
>> +         */
>> +        ifctx = aml_if(aml_equal(function, aml_int(0)));
>> +        byte_list[0] = 0 /* No function Supported */;
>> +        aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
>> +        aml_append(method, ifctx);
>> +
>> +        /* No function is supported yet. */
>> +        byte_list[0] = 1 /* Not Supported */;
>> +        aml_append(method, aml_return(aml_buffer(1, byte_list)));
>> +    }
>> +    aml_append(root_dev, method);
>> +}
>> +
>> +static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
>> +{
>> +    for (; device_list; device_list = device_list->next) {
>> +        DeviceState *dev = device_list->data;
>> +        int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
>> +                                           NULL);
>> +        uint32_t handle = nvdimm_slot_to_handle(slot);
>> +        Aml *nvdimm_dev, *method;
>> +
>> +        nvdimm_dev = aml_device("NV%02X", slot);
>> +        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
>> +
>> +        method = aml_method("_DSM", 4);
>> +        {
>> +            aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
>> +                       aml_arg(1), aml_arg(2), aml_arg(3))));
>> +        }
>> +        aml_append(nvdimm_dev, method);
>> +
>> +        aml_append(root_dev, nvdimm_dev);
>> +    }
>> +}
>> +
>> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
>> +                              GArray *table_data, GArray *linker)
>> +{
>> +    Aml *ssdt, *sb_scope, *dev, *method;
>> +
>> +    acpi_add_table(table_offsets, table_data);
>> +
>> +    ssdt = init_aml_allocator();
>> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
>> +
>> +    sb_scope = aml_scope("\\_SB");
>> +
>> +    dev = aml_device("NVDR");
>> +    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
>
> Pls add a comment explaining that ACPI0012 is NVDIMM root device.

Okay, will add these comment:

/*
  * NVDIMM is introduced in ACPI 6.0 9.20 NVDIMM Devices 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.
  */

>
> Also - this will now appear for all users, e.g.
> windows guests will prompt users for a driver.
> Not nice if user didn't actually ask for nvdimm.
>
> A simple solution is to default this functionality
> to off by default.
>

Okay, will disable nvdimm on default in the next version.

>> +
>> +    nvdimm_build_common_dsm(dev);
>> +    method = aml_method("_DSM", 4);
>> +    {
>> +        aml_append(method, aml_return(aml_call4("NCAL", aml_arg(0),
>> +                   aml_arg(1), aml_arg(2), aml_arg(3))));
>> +    }
>
> Some duplication here, move above to a sub-function please.

Okay, will add a function named nvdimm_build_device_dsm() to do these
things.

Thanks!

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

* Re: [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
  2015-11-30 10:30     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-11-30 12:29       ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 11/30/2015 06:30 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:01PM +0800, Xiao Guangrong wrote:
>> 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
>>
>> The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
>> is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
>> false on 2.4 and its earlier version to keep compatibility
>
> Will need to make it false on 2.5 too.
>

Yes, 2.5 have been released now, it need to be updated. :)

> Isn't there a device that needs to be created for this
> to work?  It would be cleaned to just key off

Yes. But no nvdimm device/NFIT exists if no nvdimm device is
specified by QEMU command line.

> the device presence, then we don't need compat gunk,
> and further, people not using it don't get a
> bunch of unused AML.

I am okay to make it off on default.


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

* Re: [Qemu-devel] [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table
@ 2015-11-30 12:29       ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 11/30/2015 06:30 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:01PM +0800, Xiao Guangrong wrote:
>> 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
>>
>> The NVDIMM functionality is controlled by the parameter, 'nvdimm-support',
>> is introduced for PIIX4_PM and ICH9-LPC, it is true on default and it is
>> false on 2.4 and its earlier version to keep compatibility
>
> Will need to make it false on 2.5 too.
>

Yes, 2.5 have been released now, it need to be updated. :)

> Isn't there a device that needs to be created for this
> to work?  It would be cleaned to just key off

Yes. But no nvdimm device/NFIT exists if no nvdimm device is
specified by QEMU command line.

> the device presence, then we don't need compat gunk,
> and further, people not using it don't get a
> bunch of unused AML.

I am okay to make it off on default.

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

* Re: [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
  2015-11-30 10:32     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-11-30 12:31       ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:31 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 11/30/2015 06:32 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
>> NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices
>
> Forgot to mention:
>
> Pls put spec info in code comments near
> relevant functions, not just the log.
>

Sure, good to me.

>> +
>> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
>> +                              GArray *table_data, GArray *linker)
>> +{
>> +    Aml *ssdt, *sb_scope, *dev, *method;
>
> So why don't we skip this completely if device list is empty?

Yes, it is exactly what we did:

  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
                         GArray *linker)
  {
      GSList *device_list;

      /* no NVDIMM device is plugged. */
      device_list = nvdimm_get_plugged_device_list();
      if (!device_list) {
          return;
      }
      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
      g_slist_free(device_list);
  }

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

* Re: [Qemu-devel] [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices
@ 2015-11-30 12:31       ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:31 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 11/30/2015 06:32 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:51:02PM +0800, Xiao Guangrong wrote:
>> NVDIMM devices is defined in ACPI 6.0 9.20 NVDIMM Devices
>
> Forgot to mention:
>
> Pls put spec info in code comments near
> relevant functions, not just the log.
>

Sure, good to me.

>> +
>> +static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
>> +                              GArray *table_data, GArray *linker)
>> +{
>> +    Aml *ssdt, *sb_scope, *dev, *method;
>
> So why don't we skip this completely if device list is empty?

Yes, it is exactly what we did:

  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
                         GArray *linker)
  {
      GSList *device_list;

      /* no NVDIMM device is plugged. */
      device_list = nvdimm_get_plugged_device_list();
      if (!device_list) {
          return;
      }
      nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
+    nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
      g_slist_free(device_list);
  }

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-30 10:38   ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-11-30 12:33     ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 11/30/2015 06:38 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
>> This patchset can be found at:
>>        https://github.com/xiaogr/qemu.git nvdimm-v8
>>
>> It is based on pci branch on Michael's tree and the top commit is:
>> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
>>
>> Changelog in v8:
>> We split the long patch series into the small parts, as you see now, this
>> is the first part which enables NVDIMM without label data support.
>
> Finally found some time to review this.  Very nice, this is making good
> progress, and I think to split it like this is a great idea.  I sent
> some comments, most of them minor.
>

Thanks for your time and really happy to see you like it. :)

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-30 12:33     ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: ehabkost, kvm, gleb, mtosatti, qemu-devel, stefanha, imammedo,
	pbonzini, dan.j.williams, rth



On 11/30/2015 06:38 PM, Michael S. Tsirkin wrote:
> On Mon, Nov 16, 2015 at 06:50:58PM +0800, Xiao Guangrong wrote:
>> This patchset can be found at:
>>        https://github.com/xiaogr/qemu.git nvdimm-v8
>>
>> It is based on pci branch on Michael's tree and the top commit is:
>> commit e3a4e177d9 (migration/ram: fix build on 32 bit hosts).
>>
>> Changelog in v8:
>> We split the long patch series into the small parts, as you see now, this
>> is the first part which enables NVDIMM without label data support.
>
> Finally found some time to review this.  Very nice, this is making good
> progress, and I think to split it like this is a great idea.  I sent
> some comments, most of them minor.
>

Thanks for your time and really happy to see you like it. :)

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-11-30  8:51   ` [Qemu-devel] " Stefan Hajnoczi
@ 2015-11-30 12:34     ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:34 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: pbonzini, imammedo, gleb, mtosatti, stefanha, mst, rth, ehabkost,
	dan.j.williams, kvm, qemu-devel



On 11/30/2015 04:51 PM, Stefan Hajnoczi wrote:

>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
>

Thanks for your review Stefan. Will pick up your Reviewed-by in
the next version. :)

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-11-30 12:34     ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-11-30 12:34 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	imammedo, pbonzini, dan.j.williams, rth



On 11/30/2015 04:51 PM, Stefan Hajnoczi wrote:

>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
>

Thanks for your review Stefan. Will pick up your Reviewed-by in
the next version. :)

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
  2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
@ 2015-12-04 16:38   ` Vladimir Sementsov-Ogievskiy
  -1 siblings, 0 replies; 48+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2015-12-04 16:38 UTC (permalink / raw)
  To: Xiao Guangrong, pbonzini, imammedo
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	dan.j.williams, rth

On 16.11.2015 13:50, Xiao Guangrong wrote:
> NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
> on Intel's platform.

Hi.

One question: do this mean, that your qemu emulated nvidimm - pmem 
solution will work only on Intel host?


-- 
Best regards,
Vladimir
* now, @virtuozzo.com instead of @parallels.com. Sorry for this inconvenience.


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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-12-04 16:38   ` Vladimir Sementsov-Ogievskiy
  0 siblings, 0 replies; 48+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2015-12-04 16:38 UTC (permalink / raw)
  To: Xiao Guangrong, pbonzini, imammedo
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	dan.j.williams, rth

On 16.11.2015 13:50, Xiao Guangrong wrote:
> NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
> on Intel's platform.

Hi.

One question: do this mean, that your qemu emulated nvidimm - pmem 
solution will work only on Intel host?


-- 
Best regards,
Vladimir
* now, @virtuozzo.com instead of @parallels.com. Sorry for this inconvenience.

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

* Re: [PATCH v8 0/5] implement vNVDIMM
  2015-12-04 16:38   ` Vladimir Sementsov-Ogievskiy
@ 2015-12-05  4:29     ` Xiao Guangrong
  -1 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-12-05  4:29 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, pbonzini, imammedo
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	dan.j.williams, rth



On 12/05/2015 12:38 AM, Vladimir Sementsov-Ogievskiy wrote:
> On 16.11.2015 13:50, Xiao Guangrong wrote:
>> NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
>> on Intel's platform.
>
> Hi.
>
> One question: do this mean, that your qemu emulated nvidimm - pmem solution will work only on Intel
> host?

Currently, it is only enabled in x86 emulator, however, it can be easily enabled on
other platform which supports acpi.

BTW, you also need to check the linux kernel driver, nfit.ko, which is currently only
working on x86 IIUC:
config ACPI_NFIT
         tristate "ACPI NVDIMM Firmware Interface Table (NFIT)"
         depends on PHYS_ADDR_T_64BIT
         depends on BLK_DEV
         depends on ARCH_HAS_MMIO_FLUSH
         select LIBNVDIMM
         help
           Infrastructure to probe ACPI 6 compliant platforms for
           NVDIMMs (NFIT) and register a libnvdimm device tree.  In
           addition to storage devices this also enables libnvdimm to pass
           ACPI._DSM messages for platform/dimm configuration.

           To compile this driver as a module, choose M here:
           the module will be called nfit.

$ git grep ARCH_HAS_MMIO_FLUSH
arch/x86/Kconfig:       select ARCH_HAS_MMIO_FLUSH
drivers/acpi/Kconfig:   depends on ARCH_HAS_MMIO_FLUSH
lib/Kconfig:config ARCH_HAS_MMIO_FLUSH

You should check  ARCH_HAS_MMIO_FLUSH on your platform.

Thanks!

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

* Re: [Qemu-devel] [PATCH v8 0/5] implement vNVDIMM
@ 2015-12-05  4:29     ` Xiao Guangrong
  0 siblings, 0 replies; 48+ messages in thread
From: Xiao Guangrong @ 2015-12-05  4:29 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, pbonzini, imammedo
  Cc: ehabkost, kvm, mst, gleb, mtosatti, qemu-devel, stefanha,
	dan.j.williams, rth



On 12/05/2015 12:38 AM, Vladimir Sementsov-Ogievskiy wrote:
> On 16.11.2015 13:50, Xiao Guangrong wrote:
>> NVDIMM (A Non-Volatile Dual In-line Memory Module) is going to be supported
>> on Intel's platform.
>
> Hi.
>
> One question: do this mean, that your qemu emulated nvidimm - pmem solution will work only on Intel
> host?

Currently, it is only enabled in x86 emulator, however, it can be easily enabled on
other platform which supports acpi.

BTW, you also need to check the linux kernel driver, nfit.ko, which is currently only
working on x86 IIUC:
config ACPI_NFIT
         tristate "ACPI NVDIMM Firmware Interface Table (NFIT)"
         depends on PHYS_ADDR_T_64BIT
         depends on BLK_DEV
         depends on ARCH_HAS_MMIO_FLUSH
         select LIBNVDIMM
         help
           Infrastructure to probe ACPI 6 compliant platforms for
           NVDIMMs (NFIT) and register a libnvdimm device tree.  In
           addition to storage devices this also enables libnvdimm to pass
           ACPI._DSM messages for platform/dimm configuration.

           To compile this driver as a module, choose M here:
           the module will be called nfit.

$ git grep ARCH_HAS_MMIO_FLUSH
arch/x86/Kconfig:       select ARCH_HAS_MMIO_FLUSH
drivers/acpi/Kconfig:   depends on ARCH_HAS_MMIO_FLUSH
lib/Kconfig:config ARCH_HAS_MMIO_FLUSH

You should check  ARCH_HAS_MMIO_FLUSH on your platform.

Thanks!

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

end of thread, other threads:[~2015-12-05  4:36 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-16 10:50 [PATCH v8 0/5] implement vNVDIMM Xiao Guangrong
2015-11-16 10:50 ` [Qemu-devel] " Xiao Guangrong
2015-11-16 10:50 ` [PATCH v8 1/5] nvdimm: implement NVDIMM device abstract Xiao Guangrong
2015-11-16 10:50   ` [Qemu-devel] " Xiao Guangrong
2015-11-16 10:51 ` [PATCH v8 2/5] acpi: support specified oem table id for build_header Xiao Guangrong
2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
2015-11-16 10:51 ` [PATCH v8 3/5] nvdimm acpi: build ACPI NFIT table Xiao Guangrong
2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
2015-11-30 10:30   ` Michael S. Tsirkin
2015-11-30 10:30     ` [Qemu-devel] " Michael S. Tsirkin
2015-11-30 12:29     ` Xiao Guangrong
2015-11-30 12:29       ` [Qemu-devel] " Xiao Guangrong
2015-11-16 10:51 ` [PATCH v8 4/5] nvdimm acpi: build ACPI nvdimm devices Xiao Guangrong
2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
2015-11-30 10:30   ` Michael S. Tsirkin
2015-11-30 10:30     ` [Qemu-devel] " Michael S. Tsirkin
2015-11-30 12:21     ` Xiao Guangrong
2015-11-30 12:21       ` [Qemu-devel] " Xiao Guangrong
2015-11-30 10:32   ` Michael S. Tsirkin
2015-11-30 10:32     ` [Qemu-devel] " Michael S. Tsirkin
2015-11-30 12:31     ` Xiao Guangrong
2015-11-30 12:31       ` [Qemu-devel] " Xiao Guangrong
2015-11-16 10:51 ` [PATCH v8 5/5] nvdimm: add maintain info Xiao Guangrong
2015-11-16 10:51   ` [Qemu-devel] " Xiao Guangrong
2015-11-18  1:59 ` [PATCH v8 0/5] implement vNVDIMM Xiao Guangrong
2015-11-18  1:59   ` [Qemu-devel] " Xiao Guangrong
2015-11-18 19:18   ` Eduardo Habkost
2015-11-18 19:18     ` [Qemu-devel] " Eduardo Habkost
2015-11-18 20:44     ` Michael S. Tsirkin
2015-11-18 20:44       ` [Qemu-devel] " Michael S. Tsirkin
2015-11-19  2:39       ` Xiao Guangrong
2015-11-19  2:39         ` [Qemu-devel] " Xiao Guangrong
2015-11-19  8:21         ` Michael S. Tsirkin
2015-11-19  8:21           ` [Qemu-devel] " Michael S. Tsirkin
2015-11-23  8:53         ` Stefan Hajnoczi
2015-11-23  8:53           ` [Qemu-devel] " Stefan Hajnoczi
2015-11-30  8:51 ` Stefan Hajnoczi
2015-11-30  8:51   ` [Qemu-devel] " Stefan Hajnoczi
2015-11-30 12:34   ` Xiao Guangrong
2015-11-30 12:34     ` [Qemu-devel] " Xiao Guangrong
2015-11-30 10:38 ` Michael S. Tsirkin
2015-11-30 10:38   ` [Qemu-devel] " Michael S. Tsirkin
2015-11-30 12:33   ` Xiao Guangrong
2015-11-30 12:33     ` [Qemu-devel] " Xiao Guangrong
2015-12-04 16:38 ` Vladimir Sementsov-Ogievskiy
2015-12-04 16:38   ` Vladimir Sementsov-Ogievskiy
2015-12-05  4:29   ` Xiao Guangrong
2015-12-05  4:29     ` [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.