[v3,02/21] libnd, nfit: initial libnd infrastructure and NFIT support
diff mbox

Message ID 20150520205621.32249.39424.stgit@dwillia2-desk3.amr.corp.intel.com
State Superseded
Headers show

Commit Message

Dan Williams May 20, 2015, 8:56 p.m. UTC
A libnd bus is the anchor device for registering nvdimm resources and
interfaces, for example, a character control device, nvdimm devices,
and I/O region devices.  The ACPI NFIT (NVDIMM Firmware Interface Table)
is one possible platform description for such non-volatile memory
resources in a system.  The nfit.ko driver attaches to the "ACPI0012"
device that indicates the presence of the NFIT and parses the table to
register a libnd bus instance.

Cc: <linux-acpi@vger.kernel.org>
Cc: Lv Zheng <lv.zheng@intel.com>
Cc: Robert Moore <robert.moore@intel.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/acpi/Kconfig          |   15 +
 drivers/acpi/Makefile         |    1 
 drivers/acpi/nfit.c           |  444 +++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/nfit.h           |   89 ++++++++
 drivers/block/Kconfig         |    2 
 drivers/block/Makefile        |    1 
 drivers/block/nd/Kconfig      |   20 ++
 drivers/block/nd/Makefile     |    3 
 drivers/block/nd/core.c       |   67 ++++++
 drivers/block/nd/nd-private.h |   23 ++
 include/acpi/actbl1.h         |  154 ++++++++++++++
 include/acpi/acuuid.h         |   89 ++++++++
 include/linux/libnd.h         |   34 +++
 13 files changed, 942 insertions(+)
 create mode 100644 drivers/acpi/nfit.c
 create mode 100644 drivers/acpi/nfit.h
 create mode 100644 drivers/block/nd/Kconfig
 create mode 100644 drivers/block/nd/Makefile
 create mode 100644 drivers/block/nd/core.c
 create mode 100644 drivers/block/nd/nd-private.h
 create mode 100644 include/acpi/acuuid.h
 create mode 100644 include/linux/libnd.h

Comments

Toshi Kani May 21, 2015, 1:55 p.m. UTC | #1
On Wed, 2015-05-20 at 16:56 -0400, Dan Williams wrote:
 :
> +/* NVDIMM - NFIT table */
> +
> +#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-3f22d252e5d0"
> +#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
> +#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-0a2db9408249"
> +#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-f7b281d1f96e"
> +#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-d2ade523c4bb"
> +#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-4496fbe096f9"
> +#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-5387d53ded3d"

acpi_str_to_uuid() performs little-endian byte-swapping, so the UUID
strings here need to be actual values.

For instance, UUID_PERSISTENT_MEMORY should be:
#define UUID_PERSISTENT_MEMORY   "66f0d379-b4f3-4074-ac43-0d3318b78cdb"

Thanks,
-Toshi
Dan Williams May 21, 2015, 3:56 p.m. UTC | #2
On Thu, May 21, 2015 at 6:55 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> On Wed, 2015-05-20 at 16:56 -0400, Dan Williams wrote:
>  :
>> +/* NVDIMM - NFIT table */
>> +
>> +#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-3f22d252e5d0"
>> +#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
>> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
>> +#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-0a2db9408249"
>> +#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-f7b281d1f96e"
>> +#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-d2ade523c4bb"
>> +#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-4496fbe096f9"
>> +#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-5387d53ded3d"
>
> acpi_str_to_uuid() performs little-endian byte-swapping, so the UUID
> strings here need to be actual values.
>
> For instance, UUID_PERSISTENT_MEMORY should be:
> #define UUID_PERSISTENT_MEMORY   "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
>

No, the spec defines the GUID for persistent memory as:

{ 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C, 0xDB }

The byte encoding for that GUID is the following (all fields stored
big endian: https://en.wikipedia.org/wiki/Globally_unique_identifier#Binary_encoding)

{ 0x66, 0xF0, 0xD3, 0x79, 0xB4, 0xF3, 0x40,0x74, 0xAC, 0x43, 0x0D,
0x33, 0x18, 0xB7, 0x8C, 0xDB }

The reverse ACPI string translation of a UUID buffer according to
"ACPI 6 - 19.6.136 ToUUID (Convert String to UUID Macro)"

{ dd, cc, bb, aa, ff, ee, hh, gg, ii, jj, kk, ll, mm, nn, oo, pp }

"aabbccdd-eeff-gghh-iijj-kkllmmnnoopp"

"79d3f066-f3b4-7440-ac43-0d3318b78cdb"

Indeed, v2 of this patchset got this wrong.  Thanks to the sharp eyes
of Bob Moore on the ACPICA team, he caught this discrepancy.  It seems
the ACPI spec uses the terms "GUID" and "UUID" interchangeably.
Toshi Kani May 21, 2015, 5:25 p.m. UTC | #3
On Thu, 2015-05-21 at 08:56 -0700, Dan Williams wrote:
> On Thu, May 21, 2015 at 6:55 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > On Wed, 2015-05-20 at 16:56 -0400, Dan Williams wrote:
> >  :
> >> +/* NVDIMM - NFIT table */
> >> +
> >> +#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-3f22d252e5d0"
> >> +#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
> >> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
> >> +#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-0a2db9408249"
> >> +#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-f7b281d1f96e"
> >> +#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-d2ade523c4bb"
> >> +#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-4496fbe096f9"
> >> +#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-5387d53ded3d"
> >
> > acpi_str_to_uuid() performs little-endian byte-swapping, so the UUID
> > strings here need to be actual values.
> >
> > For instance, UUID_PERSISTENT_MEMORY should be:
> > #define UUID_PERSISTENT_MEMORY   "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
> >
> 
> No, the spec defines the GUID for persistent memory as:
> 
> { 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C, 0xDB }
> 
> The byte encoding for that GUID is the following (all fields stored
> big endian: https://en.wikipedia.org/wiki/Globally_unique_identifier#Binary_encoding)
> 
> { 0x66, 0xF0, 0xD3, 0x79, 0xB4, 0xF3, 0x40,0x74, 0xAC, 0x43, 0x0D,
> 0x33, 0x18, 0xB7, 0x8C, 0xDB }
> 
> The reverse ACPI string translation of a UUID buffer according to
> "ACPI 6 - 19.6.136 ToUUID (Convert String to UUID Macro)"
> 
> { dd, cc, bb, aa, ff, ee, hh, gg, ii, jj, kk, ll, mm, nn, oo, pp }
> 
> "aabbccdd-eeff-gghh-iijj-kkllmmnnoopp"
> 
> "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
> 
> Indeed, v2 of this patchset got this wrong.  Thanks to the sharp eyes
> of Bob Moore on the ACPICA team, he caught this discrepancy.  It seems
> the ACPI spec uses the terms "GUID" and "UUID" interchangeably.

I agree that this thing is confusing...

The Wiki page you pointed states that:
===
Byte encoding
 :
This endianness applies only to the way in which a GUID is stored, and
not to the way in which it is represented in text. GUIDs and RFC 4122
UUIDs should be identical when displayed textually.

Text encoding
 :
For the first three fields, the most significant digit is on the left. 
===

Wiki page of UUID below also states that:
http://en.wikipedia.org/wiki/Universally_unique_identifier
===
Definition
 :
The first 3 sequences are interpreted as complete hexadecimal numbers,
while the final 2 as a plain sequence of bytes. The byte order is "most
significant byte first (known as network byte order)
===

So, the text encoding of GUID represents actual value; no endianness
applies here.  So, the following GUID definition:

{ 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C,
0xDB }

Should be text encoded as:

"66f0d379-b4f3-4074-ac43-0d3318b78cdb"

Now, byte-encoding is confusing.  While the Wiki page you pointed states
that GUID has big endian per Microsoft definition, EFI spec defines
differently.  Please look at EFI 2.5 "Appendix A GUID and Time Formats".

The EFI spec states that:
===
All EFI GUIDs (Globally Unique Identifiers) have the format described in
RFC 4122 and comply with the referenced algorithms for generating GUIDs.
It should be noted that TimeLow, TimeMid, TimeHighAndVersion fields in
the EFI are encoded as little endian.
===

Table 212 defines how text representation of the GUID is stored in
Buffer, which is little endian format.  This table also states that the
most significant byte is the first in text encoding, which is consistent
with the Wiki pages.

The ACPI spec, ToUUID, is consistent with EFI spec Table 212 as well.

Thanks,
-Toshi
Moore, Robert May 21, 2015, 5:49 p.m. UTC | #4
What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:


Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):

   Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
     Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp




> -----Original Message-----
> From: Toshi Kani [mailto:toshi.kani@hp.com]
> Sent: Thursday, May 21, 2015 10:25 AM
> To: Williams, Dan J
> Cc: Jens Axboe; linux-nvdimm@lists.01.org; Neil Brown; Greg KH; Wysocki,
> Rafael J; linux-kernel@vger.kernel.org; Moore, Robert; Linux ACPI; Zheng,
> Lv; Christoph Hellwig; Ingo Molnar
> Subject: Re: [PATCH v3 02/21] libnd, nfit: initial libnd infrastructure
> and NFIT support
> 
> On Thu, 2015-05-21 at 08:56 -0700, Dan Williams wrote:
> > On Thu, May 21, 2015 at 6:55 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > > On Wed, 2015-05-20 at 16:56 -0400, Dan Williams wrote:
> > >  :
> > >> +/* NVDIMM - NFIT table */
> > >> +
> > >> +#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-
> 3f22d252e5d0"
> > >> +#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-
> 0d3318b78cdb"
> > >> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-
> 299367e8234c"
> > >> +#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-
> 0a2db9408249"
> > >> +#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-
> f7b281d1f96e"
> > >> +#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-
> d2ade523c4bb"
> > >> +#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-
> 4496fbe096f9"
> > >> +#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-
> 5387d53ded3d"
> > >
> > > acpi_str_to_uuid() performs little-endian byte-swapping, so the UUID
> > > strings here need to be actual values.
> > >
> > > For instance, UUID_PERSISTENT_MEMORY should be:
> > > #define UUID_PERSISTENT_MEMORY   "66f0d379-b4f3-4074-ac43-
> 0d3318b78cdb"
> > >
> >
> > No, the spec defines the GUID for persistent memory as:
> >
> > { 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7,
> > 0x8C, 0xDB }
> >
> > The byte encoding for that GUID is the following (all fields stored
> > big endian:
> > https://en.wikipedia.org/wiki/Globally_unique_identifier#Binary_encodi
> > ng)
> >
> > { 0x66, 0xF0, 0xD3, 0x79, 0xB4, 0xF3, 0x40,0x74, 0xAC, 0x43, 0x0D,
> > 0x33, 0x18, 0xB7, 0x8C, 0xDB }
> >
> > The reverse ACPI string translation of a UUID buffer according to
> > "ACPI 6 - 19.6.136 ToUUID (Convert String to UUID Macro)"
> >
> > { dd, cc, bb, aa, ff, ee, hh, gg, ii, jj, kk, ll, mm, nn, oo, pp }
> >
> > "aabbccdd-eeff-gghh-iijj-kkllmmnnoopp"
> >
> > "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
> >
> > Indeed, v2 of this patchset got this wrong.  Thanks to the sharp eyes
> > of Bob Moore on the ACPICA team, he caught this discrepancy.  It seems
> > the ACPI spec uses the terms "GUID" and "UUID" interchangeably.
> 
> I agree that this thing is confusing...
> 
> The Wiki page you pointed states that:
> ===
> Byte encoding
>  :
> This endianness applies only to the way in which a GUID is stored, and not
> to the way in which it is represented in text. GUIDs and RFC 4122 UUIDs
> should be identical when displayed textually.
> 
> Text encoding
>  :
> For the first three fields, the most significant digit is on the left.
> ===
> 
> Wiki page of UUID below also states that:
> http://en.wikipedia.org/wiki/Universally_unique_identifier
> ===
> Definition
>  :
> The first 3 sequences are interpreted as complete hexadecimal numbers,
> while the final 2 as a plain sequence of bytes. The byte order is "most
> significant byte first (known as network byte order) ===
> 
> So, the text encoding of GUID represents actual value; no endianness
> applies here.  So, the following GUID definition:
> 
> { 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C,
> 0xDB }
> 
> Should be text encoded as:
> 
> "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
> 
> Now, byte-encoding is confusing.  While the Wiki page you pointed states
> that GUID has big endian per Microsoft definition, EFI spec defines
> differently.  Please look at EFI 2.5 "Appendix A GUID and Time Formats".
> 
> The EFI spec states that:
> ===
> All EFI GUIDs (Globally Unique Identifiers) have the format described in
> RFC 4122 and comply with the referenced algorithms for generating GUIDs.
> It should be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the
> EFI are encoded as little endian.
> ===
> 
> Table 212 defines how text representation of the GUID is stored in Buffer,
> which is little endian format.  This table also states that the most
> significant byte is the first in text encoding, which is consistent with
> the Wiki pages.
> 
> The ACPI spec, ToUUID, is consistent with EFI spec Table 212 as well.
> 
> Thanks,
> -Toshi
Toshi Kani May 21, 2015, 6:01 p.m. UTC | #5
On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
> 
> 
> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
> 
>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
> 

I do not see any issue in this conversion, which is consistent with
ToUUID defined in ACPI spec.

My point is that the string format of GUID is endian-neutral.  Wiki
pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
Table 212, which is v2.4), is also clear about how String and Buffer are
related with actual values of GUID.

Thanks,
-Toshi


> 
> 
> > -----Original Message-----
> > From: Toshi Kani [mailto:toshi.kani@hp.com]
> > Sent: Thursday, May 21, 2015 10:25 AM
> > To: Williams, Dan J
> > Cc: Jens Axboe; linux-nvdimm@lists.01.org; Neil Brown; Greg KH; Wysocki,
> > Rafael J; linux-kernel@vger.kernel.org; Moore, Robert; Linux ACPI; Zheng,
> > Lv; Christoph Hellwig; Ingo Molnar
> > Subject: Re: [PATCH v3 02/21] libnd, nfit: initial libnd infrastructure
> > and NFIT support
> > 
> > On Thu, 2015-05-21 at 08:56 -0700, Dan Williams wrote:
> > > On Thu, May 21, 2015 at 6:55 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > > > On Wed, 2015-05-20 at 16:56 -0400, Dan Williams wrote:
> > > >  :
> > > >> +/* NVDIMM - NFIT table */
> > > >> +
> > > >> +#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-
> > 3f22d252e5d0"
> > > >> +#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-
> > 0d3318b78cdb"
> > > >> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-
> > 299367e8234c"
> > > >> +#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-
> > 0a2db9408249"
> > > >> +#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-
> > f7b281d1f96e"
> > > >> +#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-
> > d2ade523c4bb"
> > > >> +#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-
> > 4496fbe096f9"
> > > >> +#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-
> > 5387d53ded3d"
> > > >
> > > > acpi_str_to_uuid() performs little-endian byte-swapping, so the UUID
> > > > strings here need to be actual values.
> > > >
> > > > For instance, UUID_PERSISTENT_MEMORY should be:
> > > > #define UUID_PERSISTENT_MEMORY   "66f0d379-b4f3-4074-ac43-
> > 0d3318b78cdb"
> > > >
> > >
> > > No, the spec defines the GUID for persistent memory as:
> > >
> > > { 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7,
> > > 0x8C, 0xDB }
> > >
> > > The byte encoding for that GUID is the following (all fields stored
> > > big endian:
> > > https://en.wikipedia.org/wiki/Globally_unique_identifier#Binary_encodi
> > > ng)
> > >
> > > { 0x66, 0xF0, 0xD3, 0x79, 0xB4, 0xF3, 0x40,0x74, 0xAC, 0x43, 0x0D,
> > > 0x33, 0x18, 0xB7, 0x8C, 0xDB }
> > >
> > > The reverse ACPI string translation of a UUID buffer according to
> > > "ACPI 6 - 19.6.136 ToUUID (Convert String to UUID Macro)"
> > >
> > > { dd, cc, bb, aa, ff, ee, hh, gg, ii, jj, kk, ll, mm, nn, oo, pp }
> > >
> > > "aabbccdd-eeff-gghh-iijj-kkllmmnnoopp"
> > >
> > > "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
> > >
> > > Indeed, v2 of this patchset got this wrong.  Thanks to the sharp eyes
> > > of Bob Moore on the ACPICA team, he caught this discrepancy.  It seems
> > > the ACPI spec uses the terms "GUID" and "UUID" interchangeably.
> > 
> > I agree that this thing is confusing...
> > 
> > The Wiki page you pointed states that:
> > ===
> > Byte encoding
> >  :
> > This endianness applies only to the way in which a GUID is stored, and not
> > to the way in which it is represented in text. GUIDs and RFC 4122 UUIDs
> > should be identical when displayed textually.
> > 
> > Text encoding
> >  :
> > For the first three fields, the most significant digit is on the left.
> > ===
> > 
> > Wiki page of UUID below also states that:
> > http://en.wikipedia.org/wiki/Universally_unique_identifier
> > ===
> > Definition
> >  :
> > The first 3 sequences are interpreted as complete hexadecimal numbers,
> > while the final 2 as a plain sequence of bytes. The byte order is "most
> > significant byte first (known as network byte order) ===
> > 
> > So, the text encoding of GUID represents actual value; no endianness
> > applies here.  So, the following GUID definition:
> > 
> > { 0x66F0D379, 0xB4F3, 0x4074, 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C,
> > 0xDB }
> > 
> > Should be text encoded as:
> > 
> > "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
> > 
> > Now, byte-encoding is confusing.  While the Wiki page you pointed states
> > that GUID has big endian per Microsoft definition, EFI spec defines
> > differently.  Please look at EFI 2.5 "Appendix A GUID and Time Formats".
> > 
> > The EFI spec states that:
> > ===
> > All EFI GUIDs (Globally Unique Identifiers) have the format described in
> > RFC 4122 and comply with the referenced algorithms for generating GUIDs.
> > It should be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the
> > EFI are encoded as little endian.
> > ===
> > 
> > Table 212 defines how text representation of the GUID is stored in Buffer,
> > which is little endian format.  This table also states that the most
> > significant byte is the first in text encoding, which is consistent with
> > the Wiki pages.
> > 
> > The ACPI spec, ToUUID, is consistent with EFI spec Table 212 as well.
> > 
> > Thanks,
> > -Toshi
>
Dan Williams May 21, 2015, 7:06 p.m. UTC | #6
On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
>> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
>>
>>
>> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
>>
>>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
>>
>
> I do not see any issue in this conversion, which is consistent with
> ToUUID defined in ACPI spec.
>
> My point is that the string format of GUID is endian-neutral.  Wiki
> pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
> Table 212, which is v2.4), is also clear about how String and Buffer are
> related with actual values of GUID.

I think the critical point from the UEFI spec is the "It should also
be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the EFI
are encoded as little endian".  That would imply the byte encoding
of...

{ 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }

...should be:

{ f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }

Which implies the text conversion should be:

"92f701f6-13b4-405d-910b-299367e8234c"

...not

> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"

I think ACPICA has the right order for a standard RFC 4122 id, but it
seems EFI is explicitly clarifying that the encoding is little endian
for the initial fields.  I think the EFI definition applies due to
this note in the NFIT section of the ACPI spec: "The Address Range
Type GUID values used in the ACPI NFIT must match the corresponding
values in the Disk Type GUID of the RAM Disk device path that describe
the same RAM Disk Type. Refer to the UEFI specification for details."

In hindsight it would have been nice if the NFIT spec had used an
unambiguous text encoding to define these values.
Toshi Kani May 21, 2015, 7:44 p.m. UTC | #7
On Thu, 2015-05-21 at 12:06 -0700, Dan Williams wrote:
> On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
> >> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
> >>
> >>
> >> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
> >>
> >>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
> >>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
> >>
> >
> > I do not see any issue in this conversion, which is consistent with
> > ToUUID defined in ACPI spec.
> >
> > My point is that the string format of GUID is endian-neutral.  Wiki
> > pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
> > Table 212, which is v2.4), is also clear about how String and Buffer are
> > related with actual values of GUID.
> 
> I think the critical point from the UEFI spec is the "It should also
> be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the EFI
> are encoded as little endian".  That would imply the byte encoding
> of...
> 
> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }
> 
> ...should be:
> 
> { f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }

The above NFIT GUID as data values means:

EFI_GUID(0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,
0x23, 0x4C)

> Which implies the text conversion should be:
> 
> "92f701f6-13b4-405d-910b-299367e8234c"

Nope.

EFI 2.5 spec, Appendix A "GUID and Time Formats" defines that:
(NOTE, I simplified the table 225 to fit in this email)
==
This specification also defines a standard text representation of the
GUID. This format is also sometimes called the “registry format”. It
consists of 36 characters, as follows:

aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
 :

Table 225. Text representation relationships
String	Offset In Buffer   EFI_GUID
aa	3                  Data1[24:31]
bb      2                  Data1[16:23]
cc      1                  Data1[8:15]
dd      0                  Data1[0:7]
 :
===

Therefore:

aa = Data1[21:31] = 92
bb = Data1[16:23] = F7
cc = Data1[8:15]  = 01
dd = Data1[0:7]   = F6

> ...not
> 
> > +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"

Hence, the above string is correct.

ToUUD then stores the given string to Buffer according to "Offset In
Buffer" in the above table.

Another example, EFI 2.5 spec defines GPT partition GUID:

===
Table 19. Defined GPT Partition Entry - Partition Type GUIDs
EFI System Partition C12A7328-F81F-11D2-BA4B-00A0C93EC93B
===

The kernel defines it as:
#define PARTITION_SYSTEM_GUID \
    EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
              0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B)

Thanks,
-Toshi
Toshi Kani May 21, 2015, 7:59 p.m. UTC | #8
On Thu, 2015-05-21 at 13:44 -0600, Toshi Kani wrote:
> On Thu, 2015-05-21 at 12:06 -0700, Dan Williams wrote:
> > On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > > On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
> > >> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
> > >>
> > >>
> > >> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
> > >>
> > >>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
> > >>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
> > >>
> > >
> > > I do not see any issue in this conversion, which is consistent with
> > > ToUUID defined in ACPI spec.
> > >
> > > My point is that the string format of GUID is endian-neutral.  Wiki
> > > pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
> > > Table 212, which is v2.4), is also clear about how String and Buffer are
> > > related with actual values of GUID.
> > 
> > I think the critical point from the UEFI spec is the "It should also
> > be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the EFI
> > are encoded as little endian".  That would imply the byte encoding
> > of...
> > 
> > { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }
> > 
> > ...should be:
> > 
> > { f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }
> 
> The above NFIT GUID as data values means:
> 
> EFI_GUID(0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,
> 0x23, 0x4C)
> 
> > Which implies the text conversion should be:
> > 
> > "92f701f6-13b4-405d-910b-299367e8234c"
> 
> Nope.

Oops! Sorry, I misread your email... The above string is correct,
although I do not think you need such conversion. 

> EFI 2.5 spec, Appendix A "GUID and Time Formats" defines that:
> (NOTE, I simplified the table 225 to fit in this email)
> ==
> This specification also defines a standard text representation of the
> GUID. This format is also sometimes called the “registry format”. It
> consists of 36 characters, as follows:
> 
> aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>  :
> 
> Table 225. Text representation relationships
> String	Offset In Buffer   EFI_GUID
> aa	3                  Data1[24:31]
> bb      2                  Data1[16:23]
> cc      1                  Data1[8:15]
> dd      0                  Data1[0:7]
>  :
> ===
> 
> Therefore:
> 
> aa = Data1[21:31] = 92
> bb = Data1[16:23] = F7
> cc = Data1[8:15]  = 01
> dd = Data1[0:7]   = F6
> 
> > ...not
> > 
> > > +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
> 
> Hence, the above string is correct.

Misread again... Right, the above string is NOT correct.

I think we are on the same page that the GUID strings in this patch need
to be changed.

{ 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23,
0x4C }

should be defined as:

"92f701f6-13b4-405d-910b-299367e8234c"

Thanks,
-Toshi


> ToUUD then stores the given string to Buffer according to "Offset In
> Buffer" in the above table.
> 
> Another example, EFI 2.5 spec defines GPT partition GUID:
> 
> ===
> Table 19. Defined GPT Partition Entry - Partition Type GUIDs
> EFI System Partition C12A7328-F81F-11D2-BA4B-00A0C93EC93B
> ===
> 
> The kernel defines it as:
> #define PARTITION_SYSTEM_GUID \
>     EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
>               0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B)
> 
> Thanks,
> -Toshi
> 
> _______________________________________________
> Linux-nvdimm mailing list
> Linux-nvdimm@lists.01.org
> https://lists.01.org/mailman/listinfo/linux-nvdimm
Linda Knippers May 21, 2015, 8:59 p.m. UTC | #9
On 05/21/2015 03:59 PM, Toshi Kani wrote:
> On Thu, 2015-05-21 at 13:44 -0600, Toshi Kani wrote:
>> On Thu, 2015-05-21 at 12:06 -0700, Dan Williams wrote:
>>> On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com> wrote:
>>>> On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
>>>>> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
>>>>>
>>>>>
>>>>> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
>>>>>
>>>>>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>>>>>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
>>>>>
>>>>
>>>> I do not see any issue in this conversion, which is consistent with
>>>> ToUUID defined in ACPI spec.
>>>>
>>>> My point is that the string format of GUID is endian-neutral.  Wiki
>>>> pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
>>>> Table 212, which is v2.4), is also clear about how String and Buffer are
>>>> related with actual values of GUID.
>>>
>>> I think the critical point from the UEFI spec is the "It should also
>>> be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the EFI
>>> are encoded as little endian".  That would imply the byte encoding
>>> of...
>>>
>>> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }
>>>
>>> ...should be:
>>>
>>> { f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }
>>
>> The above NFIT GUID as data values means:
>>
>> EFI_GUID(0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,
>> 0x23, 0x4C)
>>
>>> Which implies the text conversion should be:
>>>
>>> "92f701f6-13b4-405d-910b-299367e8234c"
>>
>> Nope.
> 
> Oops! Sorry, I misread your email... The above string is correct,
> although I do not think you need such conversion. 
> 
>> EFI 2.5 spec, Appendix A "GUID and Time Formats" defines that:
>> (NOTE, I simplified the table 225 to fit in this email)
>> ==
>> This specification also defines a standard text representation of the
>> GUID. This format is also sometimes called the “registry format”. It
>> consists of 36 characters, as follows:
>>
>> aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>>  :
>>
>> Table 225. Text representation relationships
>> String	Offset In Buffer   EFI_GUID
>> aa	3                  Data1[24:31]
>> bb      2                  Data1[16:23]
>> cc      1                  Data1[8:15]
>> dd      0                  Data1[0:7]
>>  :
>> ===
>>
>> Therefore:
>>
>> aa = Data1[21:31] = 92
>> bb = Data1[16:23] = F7
>> cc = Data1[8:15]  = 01
>> dd = Data1[0:7]   = F6
>>
>>> ...not
>>>
>>>> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
>>
>> Hence, the above string is correct.
> 
> Misread again... Right, the above string is NOT correct.
> 
> I think we are on the same page that the GUID strings in this patch need
> to be changed.
> 
> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23,
> 0x4C }
> 
> should be defined as:
> 
> "92f701f6-13b4-405d-910b-299367e8234c"

I've lost track of the right answer but should we be discussing
it in the context of this patch too?

http://www.spinics.net/lists/linux-acpi/msg57825.html
[PATCH 18/19] ACPICA: ACPI 6.0: Add support for NFIT table.

Dan's version of the file has lots of other UUIDs too, beyond NFIT.

-- ljk

> 
> Thanks,
> -Toshi
> 
> 
>> ToUUD then stores the given string to Buffer according to "Offset In
>> Buffer" in the above table.
>>
>> Another example, EFI 2.5 spec defines GPT partition GUID:
>>
>> ===
>> Table 19. Defined GPT Partition Entry - Partition Type GUIDs
>> EFI System Partition C12A7328-F81F-11D2-BA4B-00A0C93EC93B
>> ===
>>
>> The kernel defines it as:
>> #define PARTITION_SYSTEM_GUID \
>>     EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
>>               0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B)
>>
>> Thanks,
>> -Toshi
>>
>> _______________________________________________
>> Linux-nvdimm mailing list
>> Linux-nvdimm@lists.01.org
>> https://lists.01.org/mailman/listinfo/linux-nvdimm
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Dan Williams May 21, 2015, 9:34 p.m. UTC | #10
On Thu, May 21, 2015 at 1:59 PM, Linda Knippers <linda.knippers@hp.com> wrote:
> On 05/21/2015 03:59 PM, Toshi Kani wrote:
>> On Thu, 2015-05-21 at 13:44 -0600, Toshi Kani wrote:
>>> On Thu, 2015-05-21 at 12:06 -0700, Dan Williams wrote:
>>>> On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com> wrote:
>>>>> On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:
>>>>>> What ACPICA has done here is to define these values consistently with the ToUUID ASL macro:
>>>>>>
>>>>>>
>>>>>> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use ToUUID from ASL):
>>>>>>
>>>>>>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>>>>>>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg, ii,jj, kk,ll,mm,nn,oo,pp
>>>>>>
>>>>>
>>>>> I do not see any issue in this conversion, which is consistent with
>>>>> ToUUID defined in ACPI spec.
>>>>>
>>>>> My point is that the string format of GUID is endian-neutral.  Wiki
>>>>> pages and EFI spec agree on it.  EFI 2.5 spec, Table 225 (sorry not
>>>>> Table 212, which is v2.4), is also clear about how String and Buffer are
>>>>> related with actual values of GUID.
>>>>
>>>> I think the critical point from the UEFI spec is the "It should also
>>>> be noted that TimeLow, TimeMid, TimeHighAndVersion fields in the EFI
>>>> are encoded as little endian".  That would imply the byte encoding
>>>> of...
>>>>
>>>> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }
>>>>
>>>> ...should be:
>>>>
>>>> { f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }
>>>
>>> The above NFIT GUID as data values means:
>>>
>>> EFI_GUID(0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,
>>> 0x23, 0x4C)
>>>
>>>> Which implies the text conversion should be:
>>>>
>>>> "92f701f6-13b4-405d-910b-299367e8234c"
>>>
>>> Nope.
>>
>> Oops! Sorry, I misread your email... The above string is correct,
>> although I do not think you need such conversion.
>>
>>> EFI 2.5 spec, Appendix A "GUID and Time Formats" defines that:
>>> (NOTE, I simplified the table 225 to fit in this email)
>>> ==
>>> This specification also defines a standard text representation of the
>>> GUID. This format is also sometimes called the “registry format”. It
>>> consists of 36 characters, as follows:
>>>
>>> aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
>>>  :
>>>
>>> Table 225. Text representation relationships
>>> String       Offset In Buffer   EFI_GUID
>>> aa   3                  Data1[24:31]
>>> bb      2                  Data1[16:23]
>>> cc      1                  Data1[8:15]
>>> dd      0                  Data1[0:7]
>>>  :
>>> ===
>>>
>>> Therefore:
>>>
>>> aa = Data1[21:31] = 92
>>> bb = Data1[16:23] = F7
>>> cc = Data1[8:15]  = 01
>>> dd = Data1[0:7]   = F6
>>>
>>>> ...not
>>>>
>>>>> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
>>>
>>> Hence, the above string is correct.
>>
>> Misread again... Right, the above string is NOT correct.
>>
>> I think we are on the same page that the GUID strings in this patch need
>> to be changed.
>>
>> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23,
>> 0x4C }
>>
>> should be defined as:
>>
>> "92f701f6-13b4-405d-910b-299367e8234c"
>
> I've lost track of the right answer but should we be discussing
> it in the context of this patch too?
>
> http://www.spinics.net/lists/linux-acpi/msg57825.html
> [PATCH 18/19] ACPICA: ACPI 6.0: Add support for NFIT table.
>
> Dan's version of the file has lots of other UUIDs too, beyond NFIT.

Yeah, it's not clear whether those other GUIDs are actually GUIDs or
these byte-swapped "EFI GUID"s.  At least for NFIT it seems that the
intent was EFI GUID ordering due to the note about needing to match
the "Disk Type GUID" format from the EFI spec.

I circle back with the ACPICA folks.
Toshi Kani May 21, 2015, 10:11 p.m. UTC | #11
On Thu, 2015-05-21 at 14:34 -0700, Dan Williams wrote:
> On Thu, May 21, 2015 at 1:59 PM, Linda Knippers <linda.knippers@hp.com> wrote:
> > On 05/21/2015 03:59 PM, Toshi Kani wrote:
:
> >
> > I've lost track of the right answer but should we be discussing
> > it in the context of this patch too?
> >
> > http://www.spinics.net/lists/linux-acpi/msg57825.html
> > [PATCH 18/19] ACPICA: ACPI 6.0: Add support for NFIT table.
> >
> > Dan's version of the file has lots of other UUIDs too, beyond NFIT.
> 
> Yeah, it's not clear whether those other GUIDs are actually GUIDs or
> these byte-swapped "EFI GUID"s.  At least for NFIT it seems that the
> intent was EFI GUID ordering due to the note about needing to match
> the "Disk Type GUID" format from the EFI spec.
> 
> I circle back with the ACPICA folks.

Endianness only matters when you store GUID data into memory (or read it
from memory).  The data values themselves are independent from the
endianness.  GUIDs, EFI GUIDs, and their text strings all represent
actual data values, and therefore no swapping is necessary.

When storing EFI GUID or text string into memory/Buffer, EFI spec
defines to store it in little-endian format.  This is handled by
EFI_GUID() macro for EFI GUID values, and ToUUID / acpi_str_to_uuid()
for a string.

Thanks,
-Toshi
Moore, Robert May 22, 2015, 2:58 p.m. UTC | #12
It looks to me that you are correct and I screwed up when I made those strings. The odd thing is that we had discussed this whole issue internally for a few days -- then I went ahead and messed up the strings. I think my brain was going around in circles.

Anyway, here is the latest info, please have a look:


Below is the GUID for volatile memory region directly from the ACPI spec:


{ 0x7305944F, 0xFDDA, 0x44E3, 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52, 0xE5, 0xD0 }

Here is an example of ToUUID using a corrected version of the GUID string. Note that the ordering of the string is identical to the version in the ACPI spec:

      11:      Name (UUID, ToUUID ("7305944F-FDDA-44E3-B16C-3F22D252E5D0"))


Here is the AML output of the ToUUID macro. Note that the first three fields are reversed, the rest of the string is left as-is (as per the ToUUID definition):

00000024:  08 55 55 49 44 .........    ".UUID"
00000029:  11 13 0A 10 4F 94 05 73     "....O..s"
00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
00000039:  D2 52 E5 D0 ............    ".R.."

This is the important part:

           4F 94 05 73     "....O..s"
00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
00000039:  D2 52 E5 D0


I believe that this is correct.

Thanks for your help,
Bob




> -----Original Message-----

> From: Dan Williams [mailto:dan.j.williams@intel.com]

> Sent: Thursday, May 21, 2015 2:35 PM

> To: Linda Knippers

> Cc: Toshi Kani; Jens Axboe; linux-nvdimm@lists.01.org; Neil Brown; Greg

> KH; Wysocki, Rafael J; Moore, Robert; linux-kernel@vger.kernel.org; Linux

> ACPI; Ingo Molnar; Zheng, Lv; Christoph Hellwig

> Subject: Re: [PATCH v3 02/21] libnd, nfit: initial libnd infrastructure

> and NFIT support

> 

> On Thu, May 21, 2015 at 1:59 PM, Linda Knippers <linda.knippers@hp.com>

> wrote:

> > On 05/21/2015 03:59 PM, Toshi Kani wrote:

> >> On Thu, 2015-05-21 at 13:44 -0600, Toshi Kani wrote:

> >>> On Thu, 2015-05-21 at 12:06 -0700, Dan Williams wrote:

> >>>> On Thu, May 21, 2015 at 11:01 AM, Toshi Kani <toshi.kani@hp.com>

> wrote:

> >>>>> On Thu, 2015-05-21 at 17:49 +0000, Moore, Robert wrote:

> >>>>>> What ACPICA has done here is to define these values consistently

> with the ToUUID ASL macro:

> >>>>>>

> >>>>>>

> >>>>>> Byte encoding of UUID/GUID strings into ACPI Buffer objects (use

> ToUUID from ASL):

> >>>>>>

> >>>>>>    Input UUID/GUID String format : aabbccdd-eeff-gghh-iijj-

> kkllmmnnoopp

> >>>>>>      Expected output ACPI buffer : dd,cc,bb,aa, ff,ee, hh,gg,

> >>>>>> ii,jj, kk,ll,mm,nn,oo,pp

> >>>>>>

> >>>>>

> >>>>> I do not see any issue in this conversion, which is consistent

> >>>>> with ToUUID defined in ACPI spec.

> >>>>>

> >>>>> My point is that the string format of GUID is endian-neutral.

> >>>>> Wiki pages and EFI spec agree on it.  EFI 2.5 spec, Table 225

> >>>>> (sorry not Table 212, which is v2.4), is also clear about how

> >>>>> String and Buffer are related with actual values of GUID.

> >>>>

> >>>> I think the critical point from the UEFI spec is the "It should

> >>>> also be noted that TimeLow, TimeMid, TimeHighAndVersion fields in

> >>>> the EFI are encoded as little endian".  That would imply the byte

> >>>> encoding of...

> >>>>

> >>>> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,

> >>>> 0x23, 0x4C }

> >>>>

> >>>> ...should be:

> >>>>

> >>>> { f6,01,f7,92,b4,13,5d,40,91,0b,29,93,67,e8,23,4c }

> >>>

> >>> The above NFIT GUID as data values means:

> >>>

> >>> EFI_GUID(0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67,

> >>> 0xE8, 0x23, 0x4C)

> >>>

> >>>> Which implies the text conversion should be:

> >>>>

> >>>> "92f701f6-13b4-405d-910b-299367e8234c"

> >>>

> >>> Nope.

> >>

> >> Oops! Sorry, I misread your email... The above string is correct,

> >> although I do not think you need such conversion.

> >>

> >>> EFI 2.5 spec, Appendix A "GUID and Time Formats" defines that:

> >>> (NOTE, I simplified the table 225 to fit in this email) == This

> >>> specification also defines a standard text representation of the

> >>> GUID. This format is also sometimes called the “registry format”. It

> >>> consists of 36 characters, as follows:

> >>>

> >>> aabbccdd-eeff-gghh-iijj-kkllmmnnoopp

> >>>  :

> >>>

> >>> Table 225. Text representation relationships

> >>> String       Offset In Buffer   EFI_GUID

> >>> aa   3                  Data1[24:31]

> >>> bb      2                  Data1[16:23]

> >>> cc      1                  Data1[8:15]

> >>> dd      0                  Data1[0:7]

> >>>  :

> >>> ===

> >>>

> >>> Therefore:

> >>>

> >>> aa = Data1[21:31] = 92

> >>> bb = Data1[16:23] = F7

> >>> cc = Data1[8:15]  = 01

> >>> dd = Data1[0:7]   = F6

> >>>

> >>>> ...not

> >>>>

> >>>>> +#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-

> 299367e8234c"

> >>>

> >>> Hence, the above string is correct.

> >>

> >> Misread again... Right, the above string is NOT correct.

> >>

> >> I think we are on the same page that the GUID strings in this patch

> >> need to be changed.

> >>

> >> { 0x92F701F6, 0x13B4, 0x405D, 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8,

> >> 0x23, 0x4C }

> >>

> >> should be defined as:

> >>

> >> "92f701f6-13b4-405d-910b-299367e8234c"

> >

> > I've lost track of the right answer but should we be discussing it in

> > the context of this patch too?

> >

> > http://www.spinics.net/lists/linux-acpi/msg57825.html

> > [PATCH 18/19] ACPICA: ACPI 6.0: Add support for NFIT table.

> >

> > Dan's version of the file has lots of other UUIDs too, beyond NFIT.

> 

> Yeah, it's not clear whether those other GUIDs are actually GUIDs or these

> byte-swapped "EFI GUID"s.  At least for NFIT it seems that the intent was

> EFI GUID ordering due to the note about needing to match the "Disk Type

> GUID" format from the EFI spec.

> 

> I circle back with the ACPICA folks.
Toshi Kani May 22, 2015, 3:21 p.m. UTC | #13
On Fri, 2015-05-22 at 14:58 +0000, Moore, Robert wrote:
> It looks to me that you are correct and I screwed up when I made those strings.
> The odd thing is that we had discussed this whole issue internally for a few days
>  -- then I went ahead and messed up the strings. I think my brain was going
> around in circles.

Yes, endianness is always fun... :-)

> Anyway, here is the latest info, please have a look:
> 
> 
> Below is the GUID for volatile memory region directly from the ACPI spec:
> 
> 
> { 0x7305944F, 0xFDDA, 0x44E3, 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52, 0xE5, 0xD0 }
> 
> Here is an example of ToUUID using a corrected version of the GUID string. Note that the ordering of the string is identical to the version in the ACPI spec:
> 
>       11:      Name (UUID, ToUUID ("7305944F-FDDA-44E3-B16C-3F22D252E5D0"))
> 
> 
> Here is the AML output of the ToUUID macro. Note that the first three fields are reversed, the rest of the string is left as-is (as per the ToUUID definition):
> 
> 00000024:  08 55 55 49 44 .........    ".UUID"
> 00000029:  11 13 0A 10 4F 94 05 73     "....O..s"
> 00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
> 00000039:  D2 52 E5 D0 ............    ".R.."
> 
> This is the important part:
> 
>            4F 94 05 73     "....O..s"
> 00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
> 00000039:  D2 52 E5 D0
> 
> 
> I believe that this is correct.

Looks good!

Thanks,
-Toshi
Moore, Robert May 22, 2015, 4:12 p.m. UTC | #14
Here are the corrected strings:

/* NVDIMM - NFIT table */

#define UUID_VOLATILE_MEMORY            "7305944f-fdda-44e3-b16c-3f22d252e5d0"
#define UUID_PERSISTENT_MEMORY          "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
#define UUID_CONTROL_REGION             "92f701f6-13b4-405d-910b-299367e8234c"
#define UUID_DATA_REGION                "91af0530-5d86-470e-a6b0-0a2db9408249"
#define UUID_VOLATILE_VIRTUAL_DISK      "77ab535a-45fc-624b-5560-f7b281d1f96e"
#define UUID_VOLATILE_VIRTUAL_CD        "3d5abd30-4175-87ce-6d64-d2ade523c4bb"
#define UUID_PERSISTENT_VIRTUAL_DISK    "5cea02c9-4d07-69d3-269f-4496fbe096f9"
#define UUID_PERSISTENT_VIRTUAL_CD      "08018188-42cd-bb48-100f-5387d53ded3d"



> -----Original Message-----
> From: Toshi Kani [mailto:toshi.kani@hp.com]
> Sent: Friday, May 22, 2015 8:21 AM
> To: Moore, Robert
> Cc: Williams, Dan J; Linda Knippers; Jens Axboe; linux-
> nvdimm@lists.01.org; Neil Brown; Greg KH; Wysocki, Rafael J; linux-
> kernel@vger.kernel.org; Linux ACPI; Ingo Molnar; Zheng, Lv; Christoph
> Hellwig
> Subject: Re: [PATCH v3 02/21] libnd, nfit: initial libnd infrastructure
> and NFIT support
> 
> On Fri, 2015-05-22 at 14:58 +0000, Moore, Robert wrote:
> > It looks to me that you are correct and I screwed up when I made those
> strings.
> > The odd thing is that we had discussed this whole issue internally for
> > a few days
> >  -- then I went ahead and messed up the strings. I think my brain was
> > going around in circles.
> 
> Yes, endianness is always fun... :-)
> 
> > Anyway, here is the latest info, please have a look:
> >
> >
> > Below is the GUID for volatile memory region directly from the ACPI
> spec:
> >
> >
> > { 0x7305944F, 0xFDDA, 0x44E3, 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52,
> > 0xE5, 0xD0 }
> >
> > Here is an example of ToUUID using a corrected version of the GUID
> string. Note that the ordering of the string is identical to the version
> in the ACPI spec:
> >
> >       11:      Name (UUID, ToUUID ("7305944F-FDDA-44E3-B16C-
> 3F22D252E5D0"))
> >
> >
> > Here is the AML output of the ToUUID macro. Note that the first three
> fields are reversed, the rest of the string is left as-is (as per the
> ToUUID definition):
> >
> > 00000024:  08 55 55 49 44 .........    ".UUID"
> > 00000029:  11 13 0A 10 4F 94 05 73     "....O..s"
> > 00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
> > 00000039:  D2 52 E5 D0 ............    ".R.."
> >
> > This is the important part:
> >
> >            4F 94 05 73     "....O..s"
> > 00000031:  DA FD E3 44 B1 6C 3F 22     "...D.l?""
> > 00000039:  D2 52 E5 D0
> >
> >
> > I believe that this is correct.
> 
> Looks good!
> 
> Thanks,
> -Toshi
>

Patch
diff mbox

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index e6c3ddd92665..84d046d4ed17 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -375,6 +375,21 @@  config ACPI_REDUCED_HARDWARE_ONLY
 
 	  If you are unsure what to do, do not enable this option.
 
+config ACPI_NFIT
+	tristate "ACPI NVDIMM Firmware Interface Table (NFIT)"
+	depends on PHYS_ADDR_T_64BIT
+	depends on BLK_DEV
+	select ND_DEVICES
+	select LIBND
+	help
+	  Infrastructure to probe ACPI 6 compliant platforms for
+	  NVDIMMs (NFIT) and register a libnd device tree.  In
+	  addition to storage devices this also enables libnd 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.
+
 source "drivers/acpi/apei/Kconfig"
 
 config ACPI_EXTLOG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 623b117ad1a2..cd91093b7acf 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -70,6 +70,7 @@  obj-$(CONFIG_ACPI_PCI_SLOT)	+= pci_slot.o
 obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 obj-y				+= container.o
 obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
+obj-$(CONFIG_ACPI_NFIT)		+= nfit.o
 obj-y				+= acpi_memhotplug.o
 obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY)	+= battery.o
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
new file mode 100644
index 000000000000..13132a16901c
--- /dev/null
+++ b/drivers/acpi/nfit.c
@@ -0,0 +1,444 @@ 
+/*
+ * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+#include <linux/list_sort.h>
+#include <linux/module.h>
+#include <linux/libnd.h>
+#include <linux/list.h>
+#include <linux/acpi.h>
+#include "nfit.h"
+
+static u8 nfit_uuid[NFIT_UUID_MAX][16];
+
+static const u8 *to_nfit_uuid(enum nfit_uuids id)
+{
+	return nfit_uuid[id];
+}
+
+static int acpi_nfit_ctl(struct nd_bus_descriptor *nd_desc,
+		struct nd_dimm *nd_dimm, unsigned int cmd, void *buf,
+		unsigned int buf_len)
+{
+	return -ENOTTY;
+}
+
+static const char *spa_type_name(u16 type)
+{
+	switch (type) {
+	case NFIT_SPA_VOLATILE: return "volatile";
+	case NFIT_SPA_PM: return "pmem";
+	case NFIT_SPA_DCR: return "dimm-control-region";
+	case NFIT_SPA_BDW: return "block-data-window";
+	default: return "unknown";
+	}
+}
+
+static int nfit_spa_type(struct acpi_nfit_system_address *spa)
+{
+	int i;
+
+	for (i = 0; i < NFIT_UUID_MAX; i++)
+		if (memcmp(to_nfit_uuid(i), spa->range_guid, 16) == 0)
+			return i;
+	return -1;
+}
+
+static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, const void *end)
+{
+	struct device *dev = acpi_desc->dev;
+	struct acpi_nfit_header *hdr;
+	void *err = ERR_PTR(-ENOMEM);
+
+	if (table >= end)
+		return NULL;
+
+	hdr = (struct acpi_nfit_header *) table;
+	switch (hdr->type) {
+	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS: {
+		struct nfit_spa *nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa),
+				GFP_KERNEL);
+		struct acpi_nfit_system_address *spa = table;
+
+		if (!nfit_spa)
+			return err;
+		INIT_LIST_HEAD(&nfit_spa->list);
+		nfit_spa->spa = spa;
+		list_add_tail(&nfit_spa->list, &acpi_desc->spas);
+		dev_dbg(dev, "%s: spa index: %d type: %s\n", __func__,
+				spa->range_index,
+				spa_type_name(nfit_spa_type(spa)));
+		break;
+	}
+	case ACPI_NFIT_TYPE_MEMORY_MAP: {
+		struct nfit_memdev *nfit_memdev = devm_kzalloc(dev,
+				sizeof(*nfit_memdev), GFP_KERNEL);
+		struct acpi_nfit_memory_map *memdev = table;
+
+		if (!nfit_memdev)
+			return err;
+		INIT_LIST_HEAD(&nfit_memdev->list);
+		nfit_memdev->memdev = memdev;
+		list_add_tail(&nfit_memdev->list, &acpi_desc->memdevs);
+		dev_dbg(dev, "%s: memdev handle: %#x spa: %d dcr: %d\n",
+				__func__, memdev->device_handle, memdev->range_index,
+				memdev->region_index);
+		break;
+	}
+	case ACPI_NFIT_TYPE_CONTROL_REGION: {
+		struct nfit_dcr *nfit_dcr = devm_kzalloc(dev, sizeof(*nfit_dcr),
+				GFP_KERNEL);
+		struct acpi_nfit_control_region *dcr = table;
+
+		if (!nfit_dcr)
+			return err;
+		INIT_LIST_HEAD(&nfit_dcr->list);
+		nfit_dcr->dcr = dcr;
+		list_add_tail(&nfit_dcr->list, &acpi_desc->dcrs);
+		dev_dbg(dev, "%s: dcr index: %d windows: %d\n", __func__,
+				dcr->region_index, dcr->windows);
+		break;
+	}
+	case ACPI_NFIT_TYPE_DATA_REGION: {
+		struct nfit_bdw *nfit_bdw = devm_kzalloc(dev, sizeof(*nfit_bdw),
+				GFP_KERNEL);
+		struct acpi_nfit_data_region *bdw = table;
+
+		if (!nfit_bdw)
+			return err;
+		INIT_LIST_HEAD(&nfit_bdw->list);
+		nfit_bdw->bdw = bdw;
+		list_add_tail(&nfit_bdw->list, &acpi_desc->bdws);
+		dev_dbg(dev, "%s: bdw dcr: %d windows: %d\n", __func__,
+				bdw->region_index, bdw->windows);
+		break;
+	}
+	/* TODO */
+	case ACPI_NFIT_TYPE_INTERLEAVE:
+		dev_dbg(dev, "%s: idt\n", __func__);
+		break;
+	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
+		dev_dbg(dev, "%s: flush\n", __func__);
+		break;
+	case ACPI_NFIT_TYPE_SMBIOS:
+		dev_dbg(dev, "%s: smbios\n", __func__);
+		break;
+	default:
+		dev_err(dev, "unknown table '%d' parsing nfit\n", hdr->type);
+		break;
+	}
+
+	return table + hdr->length;
+}
+
+static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc,
+		struct nfit_mem *nfit_mem)
+{
+	u32 device_handle = __to_nfit_memdev(nfit_mem)->device_handle;
+	u16 dcr_index = nfit_mem->dcr->region_index;
+	struct nfit_spa *nfit_spa;
+
+	list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
+		u16 range_index = nfit_spa->spa->range_index;
+		int type = nfit_spa_type(nfit_spa->spa);
+		struct nfit_memdev *nfit_memdev;
+
+		if (type != NFIT_SPA_BDW)
+			continue;
+
+		list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
+			if (nfit_memdev->memdev->range_index != range_index)
+				continue;
+			if (nfit_memdev->memdev->device_handle != device_handle)
+				continue;
+			if (nfit_memdev->memdev->region_index != dcr_index)
+				continue;
+
+			nfit_mem->spa_bdw = nfit_spa->spa;
+			return;
+		}
+	}
+
+	dev_dbg(acpi_desc->dev, "SPA-BDW not found for SPA-DCR %d\n",
+			nfit_mem->spa_dcr->range_index);
+	nfit_mem->bdw = NULL;
+}
+
+static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
+		struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
+{
+	u16 dcr_index = __to_nfit_memdev(nfit_mem)->region_index;
+	struct nfit_dcr *nfit_dcr;
+	struct nfit_bdw *nfit_bdw;
+
+	list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
+		if (nfit_dcr->dcr->region_index != dcr_index)
+			continue;
+		nfit_mem->dcr = nfit_dcr->dcr;
+		break;
+	}
+
+	if (!nfit_mem->dcr) {
+		dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n", spa->range_index,
+				__to_nfit_memdev(nfit_mem) ? "" : " MEMDEV",
+				nfit_mem->dcr ? "" : " DCR");
+		return -ENODEV;
+	}
+
+	/*
+	 * We've found enough to create an nd_dimm, optionally
+	 * find an associated BDW
+	 */
+	list_add(&nfit_mem->list, &acpi_desc->dimms);
+
+	list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
+		if (nfit_bdw->bdw->region_index != dcr_index)
+			continue;
+		nfit_mem->bdw = nfit_bdw->bdw;
+		break;
+	}
+
+	if (!nfit_mem->bdw)
+		return 0;
+
+	nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
+	return 0;
+}
+
+static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
+		struct acpi_nfit_system_address *spa)
+{
+	struct nfit_mem *nfit_mem, *found;
+	struct nfit_memdev *nfit_memdev;
+	int type = nfit_spa_type(spa);
+	u16 dcr_index;
+
+	switch (type) {
+	case NFIT_SPA_DCR:
+	case NFIT_SPA_PM:
+		break;
+	default:
+		return 0;
+	}
+
+	list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
+		int rc;
+
+		if (nfit_memdev->memdev->range_index != spa->range_index)
+			continue;
+		found = NULL;
+		dcr_index = nfit_memdev->memdev->region_index;
+		list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
+			if (__to_nfit_memdev(nfit_mem)->region_index == dcr_index) {
+				found = nfit_mem;
+				break;
+			}
+
+		if (found)
+			nfit_mem = found;
+		else {
+			nfit_mem = devm_kzalloc(acpi_desc->dev,
+					sizeof(*nfit_mem), GFP_KERNEL);
+			if (!nfit_mem)
+				return -ENOMEM;
+			INIT_LIST_HEAD(&nfit_mem->list);
+		}
+
+		if (type == NFIT_SPA_DCR) {
+			/* multiple dimms may share a SPA when interleaved */
+			nfit_mem->spa_dcr = spa;
+			nfit_mem->memdev_dcr = nfit_memdev->memdev;
+		} else {
+			/*
+			 * A single dimm may belong to multiple SPA-PM
+			 * ranges, record at least one in addition to
+			 * any SPA-DCR range.
+			 */
+			nfit_mem->memdev_pmem = nfit_memdev->memdev;
+		}
+
+		if (found)
+			continue;
+
+		rc = nfit_mem_add(acpi_desc, nfit_mem, spa);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+static int nfit_mem_cmp(void *priv, struct list_head *__a, struct list_head *__b)
+{
+	struct nfit_mem *a = container_of(__a, typeof(*a), list);
+	struct nfit_mem *b = container_of(__b, typeof(*b), list);
+	u32 handleA, handleB;
+
+	handleA = __to_nfit_memdev(a)->device_handle;
+	handleB = __to_nfit_memdev(b)->device_handle;
+	if (handleA < handleB)
+		return -1;
+	else if (handleA > handleB)
+		return 1;
+	return 0;
+}
+
+static int nfit_mem_init(struct acpi_nfit_desc *acpi_desc)
+{
+	struct nfit_spa *nfit_spa;
+
+	/*
+	 * For each SPA-DCR or SPA-PMEM address range find its
+	 * corresponding MEMDEV(s).  From each MEMDEV find the
+	 * corresponding DCR.  Then, if we're operating on a SPA-DCR,
+	 * try to find a SPA-BDW and a corresponding BDW that references
+	 * the DCR.  Throw it all into an nfit_mem object.  Note, that
+	 * BDWs are optional.
+	 */
+	list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
+		int rc;
+
+		rc = nfit_mem_dcr_init(acpi_desc, nfit_spa->spa);
+		if (rc)
+			return rc;
+	}
+
+	list_sort(NULL, &acpi_desc->dimms, nfit_mem_cmp);
+
+	return 0;
+}
+
+static int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
+{
+	struct device *dev = acpi_desc->dev;
+	const void *end;
+	u8 *data;
+
+	INIT_LIST_HEAD(&acpi_desc->spas);
+	INIT_LIST_HEAD(&acpi_desc->dcrs);
+	INIT_LIST_HEAD(&acpi_desc->bdws);
+	INIT_LIST_HEAD(&acpi_desc->memdevs);
+	INIT_LIST_HEAD(&acpi_desc->dimms);
+
+	data = (u8 *) acpi_desc->nfit;
+	end = data + sz;
+	data += sizeof(struct acpi_table_nfit);
+	while (!IS_ERR_OR_NULL(data))
+		data = add_table(acpi_desc, data, end);
+
+	if (IS_ERR(data)) {
+		dev_dbg(dev, "%s: nfit table parsing error: %ld\n", __func__,
+				PTR_ERR(data));
+		return PTR_ERR(data);
+	}
+
+	if (nfit_mem_init(acpi_desc) != 0)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int acpi_nfit_add(struct acpi_device *adev)
+{
+	struct nd_bus_descriptor *nd_desc;
+	struct acpi_nfit_desc *acpi_desc;
+	struct device *dev = &adev->dev;
+	struct acpi_table_header *tbl;
+	acpi_status status = AE_OK;
+	acpi_size sz;
+	int rc;
+
+	status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz);
+	if (ACPI_FAILURE(status)) {
+		dev_err(dev, "failed to find NFIT\n");
+		return -ENXIO;
+	}
+
+	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
+	if (!acpi_desc)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, acpi_desc);
+	acpi_desc->dev = dev;
+	acpi_desc->nfit = (struct acpi_table_nfit *) tbl;
+	nd_desc = &acpi_desc->nd_desc;
+	nd_desc->provider_name = "ACPI.NFIT";
+	nd_desc->ndctl = acpi_nfit_ctl;
+
+	acpi_desc->nd_bus = nd_bus_register(dev, nd_desc);
+	if (!acpi_desc->nd_bus)
+		return -ENXIO;
+
+	rc = acpi_nfit_init(acpi_desc, sz);
+	if (rc) {
+		nd_bus_unregister(acpi_desc->nd_bus);
+		return rc;
+	}
+	return 0;
+}
+
+static int acpi_nfit_remove(struct acpi_device *adev)
+{
+	struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
+
+	nd_bus_unregister(acpi_desc->nd_bus);
+	return 0;
+}
+
+static const struct acpi_device_id acpi_nfit_ids[] = {
+	{ "ACPI0012", 0 },
+	{ "", 0 },
+};
+MODULE_DEVICE_TABLE(acpi, acpi_nfit_ids);
+
+static struct acpi_driver acpi_nfit_driver = {
+	.name = KBUILD_MODNAME,
+	.ids = acpi_nfit_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+	.ops = {
+		.add = acpi_nfit_add,
+		.remove = acpi_nfit_remove,
+	},
+};
+
+static __init int nfit_init(void)
+{
+	BUILD_BUG_ON(sizeof(struct acpi_table_nfit) != 40);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_system_address) != 56);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_memory_map) != 48);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_interleave) != 20);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_smbios) != 9);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_control_region) != 80);
+	BUILD_BUG_ON(sizeof(struct acpi_nfit_data_region) != 40);
+
+	acpi_str_to_uuid(UUID_VOLATILE_MEMORY, nfit_uuid[NFIT_SPA_VOLATILE]);
+	acpi_str_to_uuid(UUID_PERSISTENT_MEMORY, nfit_uuid[NFIT_SPA_PM]);
+	acpi_str_to_uuid(UUID_CONTROL_REGION, nfit_uuid[NFIT_SPA_DCR]);
+	acpi_str_to_uuid(UUID_DATA_REGION, nfit_uuid[NFIT_SPA_BDW]);
+	acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_VDISK]);
+	acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_CD, nfit_uuid[NFIT_SPA_VCD]);
+	acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_PDISK]);
+	acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
+	acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
+	acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
+
+	return acpi_bus_register_driver(&acpi_nfit_driver);
+}
+
+static __exit void nfit_exit(void)
+{
+	acpi_bus_unregister_driver(&acpi_nfit_driver);
+}
+
+module_init(nfit_init);
+module_exit(nfit_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
new file mode 100644
index 000000000000..ff72da9c9694
--- /dev/null
+++ b/drivers/acpi/nfit.h
@@ -0,0 +1,89 @@ 
+/*
+ * NVDIMM Firmware Interface Table - NFIT
+ *
+ * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+#ifndef __NFIT_H__
+#define __NFIT_H__
+#include <linux/types.h>
+#include <linux/libnd.h>
+#include <linux/uuid.h>
+#include <linux/acpi.h>
+#include <acpi/acuuid.h>
+
+#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
+#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
+
+enum nfit_uuids {
+	NFIT_SPA_VOLATILE,
+	NFIT_SPA_PM,
+	NFIT_SPA_DCR,
+	NFIT_SPA_BDW,
+	NFIT_SPA_VDISK,
+	NFIT_SPA_VCD,
+	NFIT_SPA_PDISK,
+	NFIT_SPA_PCD,
+	NFIT_DEV_BUS,
+	NFIT_DEV_DIMM,
+	NFIT_UUID_MAX,
+};
+
+struct nfit_spa {
+	struct acpi_nfit_system_address *spa;
+	struct list_head list;
+};
+
+struct nfit_dcr {
+	struct acpi_nfit_control_region *dcr;
+	struct list_head list;
+};
+
+struct nfit_bdw {
+	struct acpi_nfit_data_region *bdw;
+	struct list_head list;
+};
+
+struct nfit_memdev {
+	struct acpi_nfit_memory_map *memdev;
+	struct list_head list;
+};
+
+/* assembled tables for a given dimm/memory-device */
+struct nfit_mem {
+	struct acpi_nfit_memory_map *memdev_dcr;
+	struct acpi_nfit_memory_map *memdev_pmem;
+	struct acpi_nfit_control_region *dcr;
+	struct acpi_nfit_data_region *bdw;
+	struct acpi_nfit_system_address *spa_dcr;
+	struct acpi_nfit_system_address *spa_bdw;
+	struct list_head list;
+};
+
+struct acpi_nfit_desc {
+	struct nd_bus_descriptor nd_desc;
+	struct acpi_table_nfit *nfit;
+	struct list_head memdevs;
+	struct list_head dimms;
+	struct list_head spas;
+	struct list_head dcrs;
+	struct list_head bdws;
+	struct nd_bus *nd_bus;
+	struct device *dev;
+};
+
+static inline struct acpi_nfit_memory_map *__to_nfit_memdev(struct nfit_mem *nfit_mem)
+{
+	if (nfit_mem->memdev_dcr)
+		return nfit_mem->memdev_dcr;
+	return nfit_mem->memdev_pmem;
+}
+#endif /* __NFIT_H__ */
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index eb1fed5bd516..dfe40e5ca9bd 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -321,6 +321,8 @@  config BLK_DEV_NVME
 	  To compile this driver as a module, choose M here: the
 	  module will be called nvme.
 
+source "drivers/block/nd/Kconfig"
+
 config BLK_DEV_SKD
 	tristate "STEC S1120 Block Driver"
 	depends on PCI
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 9cc6c18a1c7e..07a6acecf4d8 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -24,6 +24,7 @@  obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
 obj-$(CONFIG_MG_DISK)		+= mg_disk.o
 obj-$(CONFIG_SUNVDC)		+= sunvdc.o
 obj-$(CONFIG_BLK_DEV_NVME)	+= nvme.o
+obj-$(CONFIG_ND_DEVICES)	+= nd/
 obj-$(CONFIG_BLK_DEV_SKD)	+= skd.o
 obj-$(CONFIG_BLK_DEV_OSD)	+= osdblk.o
 
diff --git a/drivers/block/nd/Kconfig b/drivers/block/nd/Kconfig
new file mode 100644
index 000000000000..9b909c21afa1
--- /dev/null
+++ b/drivers/block/nd/Kconfig
@@ -0,0 +1,20 @@ 
+menuconfig ND_DEVICES
+	bool "NVDIMM (Non-Volatile Memory Device) Support"
+	help
+	  Generic support for non-volatile memory devices including
+	  ACPI-6-NFIT defined resources.  On platforms that define an
+	  NFIT, or otherwise can discover NVDIMM resources, a libnd
+	  bus is registered to advertise PMEM (persistent memory)
+	  namespaces (/dev/pmemX) and BLK (sliding mmio window(s))
+	  namespaces (/dev/ndX). A PMEM namespace refers to a memory
+	  resource that may span multiple DIMMs and support DAX (see
+	  CONFIG_DAX).  A BLK namespace refers to an NVDIMM control
+	  region which exposes an mmio register set for windowed
+	  access mode to non-volatile memory.
+
+if ND_DEVICES
+
+config LIBND
+	tristate
+
+endif
diff --git a/drivers/block/nd/Makefile b/drivers/block/nd/Makefile
new file mode 100644
index 000000000000..a647ff6cf557
--- /dev/null
+++ b/drivers/block/nd/Makefile
@@ -0,0 +1,3 @@ 
+obj-$(CONFIG_LIBND) += libnd.o
+
+libnd-y := core.o
diff --git a/drivers/block/nd/core.c b/drivers/block/nd/core.c
new file mode 100644
index 000000000000..15b89ce1a9af
--- /dev/null
+++ b/drivers/block/nd/core.c
@@ -0,0 +1,67 @@ 
+/*
+ * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/libnd.h>
+#include <linux/slab.h>
+#include "nd-private.h"
+
+static DEFINE_IDA(nd_ida);
+
+static void nd_bus_release(struct device *dev)
+{
+	struct nd_bus *nd_bus = container_of(dev, struct nd_bus, dev);
+
+	ida_simple_remove(&nd_ida, nd_bus->id);
+	kfree(nd_bus);
+}
+
+struct nd_bus *nd_bus_register(struct device *parent,
+		struct nd_bus_descriptor *nd_desc)
+{
+	struct nd_bus *nd_bus = kzalloc(sizeof(*nd_bus), GFP_KERNEL);
+	int rc;
+
+	if (!nd_bus)
+		return NULL;
+	nd_bus->id = ida_simple_get(&nd_ida, 0, 0, GFP_KERNEL);
+	if (nd_bus->id < 0) {
+		kfree(nd_bus);
+		return NULL;
+	}
+	nd_bus->nd_desc = nd_desc;
+	nd_bus->dev.parent = parent;
+	nd_bus->dev.release = nd_bus_release;
+	dev_set_name(&nd_bus->dev, "ndbus%d", nd_bus->id);
+	rc = device_register(&nd_bus->dev);
+	if (rc) {
+		dev_dbg(&nd_bus->dev, "device registration failed: %d\n", rc);
+		put_device(&nd_bus->dev);
+		return NULL;
+	}
+
+	return nd_bus;
+}
+EXPORT_SYMBOL_GPL(nd_bus_register);
+
+void nd_bus_unregister(struct nd_bus *nd_bus)
+{
+	if (!nd_bus)
+		return;
+	device_unregister(&nd_bus->dev);
+}
+EXPORT_SYMBOL_GPL(nd_bus_unregister);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/block/nd/nd-private.h b/drivers/block/nd/nd-private.h
new file mode 100644
index 000000000000..a107a19ffa9c
--- /dev/null
+++ b/drivers/block/nd/nd-private.h
@@ -0,0 +1,23 @@ 
+/*
+ * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+#ifndef __ND_PRIVATE_H__
+#define __ND_PRIVATE_H__
+#include <linux/device.h>
+#include <linux/libnd.h>
+
+struct nd_bus {
+	struct nd_bus_descriptor *nd_desc;
+	struct device dev;
+	int id;
+};
+#endif /* __ND_PRIVATE_H__ */
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index b80b0e6dabc5..b0e431dbfd9e 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -71,6 +71,7 @@ 
 #define ACPI_SIG_SBST           "SBST"	/* Smart Battery Specification Table */
 #define ACPI_SIG_SLIT           "SLIT"	/* System Locality Distance Information Table */
 #define ACPI_SIG_SRAT           "SRAT"	/* System Resource Affinity Table */
+#define ACPI_SIG_NFIT           "NFIT"	/* NVDIMM Firmware Interface Table */
 
 /*
  * All tables must be byte-packed to match the ACPI specification, since
@@ -908,6 +909,159 @@  struct acpi_msct_proximity {
 
 /*******************************************************************************
  *
+ * NFIT - NVDIMM Interface Table (ACPI 6.0)
+ *        Version 1
+ *
+ ******************************************************************************/
+
+struct acpi_table_nfit {
+	struct acpi_table_header header;	/* Common ACPI table header */
+	u32 reserved;		/* Reserved, must be zero */
+};
+
+/* Subtable header for NFIT */
+
+struct acpi_nfit_header {
+	u16 type;
+	u16 length;
+};
+
+/* Values for subtable type in struct acpi_nfit_header */
+
+enum acpi_nfit_type {
+	ACPI_NFIT_TYPE_SYSTEM_ADDRESS = 0,
+	ACPI_NFIT_TYPE_MEMORY_MAP = 1,
+	ACPI_NFIT_TYPE_INTERLEAVE = 2,
+	ACPI_NFIT_TYPE_SMBIOS = 3,
+	ACPI_NFIT_TYPE_CONTROL_REGION = 4,
+	ACPI_NFIT_TYPE_DATA_REGION = 5,
+	ACPI_NFIT_TYPE_FLUSH_ADDRESS = 6,
+	ACPI_NFIT_TYPE_RESERVED = 7	/* 7 and greater are reserved */
+};
+
+/*
+ * NFIT Subtables
+ */
+
+/* 0: System Physical Address Range Structure */
+
+struct acpi_nfit_system_address {
+	struct acpi_nfit_header header;
+	u16 range_index;
+	u16 flags;
+	u32 reserved;		/* Reseved, must be zero */
+	u32 proximity_domain;
+	u8 range_guid[16];
+	u64 address;
+	u64 length;
+	u64 memory_mapping;
+};
+
+/* Flags */
+
+#define ACPI_NFIT_ADD_ONLINE_ONLY       (1)	/* 00: Add/Online Operation Only */
+#define ACPI_NFIT_PROXIMITY_VALID       (1<<1)	/* 01: Proximity Domain Valid */
+
+/* Range Type GUIDs appear in the include/acuuid.h file */
+
+/* 1: Memory Device to System Address Range Map Structure */
+
+struct acpi_nfit_memory_map {
+	struct acpi_nfit_header header;
+	u32 device_handle;
+	u16 physical_id;
+	u16 region_id;
+	u16 range_index;
+	u16 region_index;
+	u64 region_size;
+	u64 region_offset;
+	u64 address;
+	u16 interleave_index;
+	u16 interleave_ways;
+	u16 flags;
+	u16 reserved;		/* Reserved, must be zero */
+};
+
+/* Flags */
+
+#define ACPI_NFIT_MEM_SAVE_FAILED       (1)	/* 00: Last SAVE to Memory Device failed */
+#define ACPI_NFIT_MEM_RESTORE_FAILED    (1<<1)	/* 01: Last RESTORE from Memory Device failed */
+#define ACPI_NFIT_MEM_FLUSH_FAILED      (1<<2)	/* 02: Platform flush failed */
+#define ACPI_NFIT_MEM_ARMED             (1<<3)	/* 03: Memory Device observed to be not armed */
+#define ACPI_NFIT_MEM_HEALTH_OBSERVED   (1<<4)	/* 04: Memory Device observed SMART/health events */
+#define ACPI_NFIT_MEM_HEALTH_ENABLED    (1<<5)	/* 05: SMART/health events enabled */
+
+/* 2: Interleave Structure */
+
+struct acpi_nfit_interleave {
+	struct acpi_nfit_header header;
+	u16 interleave_index;
+	u16 reserved;		/* Reserved, must be zero */
+	u32 line_count;
+	u32 line_size;
+	u32 line_offset[1];	/* Variable length */
+};
+
+/* 3: SMBIOS Management Information Structure */
+
+struct acpi_nfit_smbios {
+	struct acpi_nfit_header header;
+	u32 reserved;		/* Reserved, must be zero */
+	u8 data[1];		/* Variable length */
+};
+
+/* 4: NVDIMM Control Region Structure */
+
+struct acpi_nfit_control_region {
+	struct acpi_nfit_header header;
+	u16 region_index;
+	u16 vendor_id;
+	u16 device_id;
+	u16 revision_id;
+	u16 subsystem_vendor_id;
+	u16 subsystem_device_id;
+	u16 subsystem_revision_id;
+	u8 reserved[6];		/* Reserved, must be zero */
+	u32 serial_number;
+	u16 code;
+	u16 windows;
+	u64 window_size;
+	u64 command_offset;
+	u64 command_size;
+	u64 status_offset;
+	u64 status_size;
+	u16 flags;
+	u8 reserved1[6];	/* Reserved, must be zero */
+};
+
+/* Flags */
+
+#define ACPI_NFIT_CONTROL_BUFFERED      (1)	/* Block Data Windows implementation is buffered */
+
+/* 5: NVDIMM Block Data Window Region Structure */
+
+struct acpi_nfit_data_region {
+	struct acpi_nfit_header header;
+	u16 region_index;
+	u16 windows;
+	u64 offset;
+	u64 size;
+	u64 capacity;
+	u64 start_address;
+};
+
+/* 6: Flush Hint Address Structure */
+
+struct acpi_nfit_flush_address {
+	struct acpi_nfit_header header;
+	u32 device_handle;
+	u16 hint_count;
+	u8 reserved[6];		/* Reserved, must be zero */
+	u64 hint_address[1];	/* Variable length */
+};
+
+/*******************************************************************************
+ *
  * SBST - Smart Battery Specification Table
  *        Version 1
  *
diff --git a/include/acpi/acuuid.h b/include/acpi/acuuid.h
new file mode 100644
index 000000000000..7c6cbb028ffc
--- /dev/null
+++ b/include/acpi/acuuid.h
@@ -0,0 +1,89 @@ 
+/******************************************************************************
+ *
+ * Name: acuuid.h - ACPI-related UUID/GUID definitions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef __ACUUID_H__
+#define __ACUUID_H__
+
+/*
+ * Note1: UUIDs and GUIDs are defined to be identical in ACPI.
+ *
+ * Note2: This file is standalone and should remain that way.
+ */
+
+/* Controllers */
+
+#define UUID_GPIO_CONTROLLER            "4f248f40-d5e2-499f-834c-27758ea1cd3f"
+#define UUID_USB_CONTROLLER             "ce2ee385-00e6-48cb-9f05-2edb927c4899"
+#define UUID_SATA_CONTROLLER            "e4db149b-fcfe-425b-a6d8-92357d78fc7f"
+
+/* Devices */
+
+#define UUID_PCI_HOST_BRIDGE            "33db4d5b-1ff7-401c-9657-7441c03dd766"
+#define UUID_I2C_DEVICE                 "3cdff6f7-4267-4555-ad05-b30a3d8938de"
+#define UUID_POWER_BUTTON               "dfbcf3c5-e7a5-44e6-9c1f-29c76f6e059c"
+
+/* Interfaces */
+
+#define UUID_DEVICE_LABELING            "e5c937d0-3553-4d7a-9117-ea4d19c3434d"
+#define UUID_PHYSICAL_PRESENCE          "3dddfaa6-361b-4eb4-a424-8d10089d1653"
+
+/* NVDIMM - NFIT table */
+
+#define UUID_VOLATILE_MEMORY            "4f940573-dafd-e344-b16c-3f22d252e5d0"
+#define UUID_PERSISTENT_MEMORY          "79d3f066-f3b4-7440-ac43-0d3318b78cdb"
+#define UUID_CONTROL_REGION             "f601f792-b413-5d40-910b-299367e8234c"
+#define UUID_DATA_REGION                "3005af91-865d-0e47-a6b0-0a2db9408249"
+#define UUID_VOLATILE_VIRTUAL_DISK      "5a53ab77-fc45-4b62-5560-f7b281d1f96e"
+#define UUID_VOLATILE_VIRTUAL_CD        "30bd5a3d-7541-ce87-6d64-d2ade523c4bb"
+#define UUID_PERSISTENT_VIRTUAL_DISK    "c902ea5c-074d-69d3-269f-4496fbe096f9"
+#define UUID_PERSISTENT_VIRTUAL_CD      "88810108-cd42-48bb-100f-5387d53ded3d"
+
+/* Miscellaneous */
+
+#define UUID_PLATFORM_CAPABILITIES      "0811b06e-4a27-44f9-8d60-3cbbc22e7b48"
+#define UUID_DYNAMIC_ENUMERATION        "d8c1a3a6-be9b-4c9b-91bf-c3cb81fc5daf"
+#define UUID_BATTERY_THERMAL_LIMIT      "4c2067e3-887d-475c-9720-4af1d3ed602e"
+#define UUID_THERMAL_EXTENSIONS         "14d399cd-7a27-4b18-8fb4-7cb7b9f4e500"
+#define UUID_DEVICE_PROPERTIES          "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
+
+#endif				/* __AUUID_H__ */
diff --git a/include/linux/libnd.h b/include/linux/libnd.h
new file mode 100644
index 000000000000..8e4441002868
--- /dev/null
+++ b/include/linux/libnd.h
@@ -0,0 +1,34 @@ 
+/*
+ * libnd - Non-volatile-memory Devices Subsystem
+ *
+ * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+#ifndef __LIBND_H__
+#define __LIBND_H__
+struct nd_dimm;
+struct nd_bus_descriptor;
+typedef int (*ndctl_fn)(struct nd_bus_descriptor *nd_desc,
+		struct nd_dimm *nd_dimm, unsigned int cmd, void *buf,
+		unsigned int buf_len);
+
+struct nd_bus_descriptor {
+	unsigned long dsm_mask;
+	char *provider_name;
+	ndctl_fn ndctl;
+};
+
+struct nd_bus;
+struct device;
+struct nd_bus *nd_bus_register(struct device *parent,
+		struct nd_bus_descriptor *nfit_desc);
+void nd_bus_unregister(struct nd_bus *nd_bus);
+#endif /* __LIBND_H__ */