diff mbox

[v2,01/20] e820, efi: add ACPI 6.0 persistent memory types

Message ID 20150428182417.35812.92834.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive)
State Superseded
Delegated to: Dan Williams
Headers show

Commit Message

Dan Williams April 28, 2015, 6:24 p.m. UTC
ACPI 6.0 formalizes e820-type-7 and efi-type-14 as persistent memory.
Mark it "reserved" and allow it to be claimed by a persistent memory
device driver.

This definition is in addition to the Linux kernel's existing type-12
definition that was recently added in support of shipping platforms with
NVDIMM support that predate ACPI 6.0 (which now classifies type-12 as
OEM reserved).  We may choose to exploit this wealth of definitions for
NVDIMMs to differentiate E820_PRAM (type-12) from E820_PMEM (type-7).
One potential differentiation is that PMEM is not backed by struct page
by default in contrast to PRAM.  For now, they are effectively treated
as aliases by the mm.

Note, /proc/iomem can be consulted for differentiating legacy
"Persistent RAM" E820_PRAM vs standard "Persistent I/O Memory"
E820_PMEM.

Cc: Boaz Harrosh <boaz@plexistor.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jens Axboe <axboe@fb.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Andy Lutomirski <luto@amacapital.net>
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/arm64/kernel/efi.c          |    1 +
 arch/ia64/kernel/efi.c           |    4 ++++
 arch/x86/boot/compressed/eboot.c |    4 ++++
 arch/x86/include/uapi/asm/e820.h |    1 +
 arch/x86/kernel/e820.c           |   26 +++++++++++++++++++++++---
 arch/x86/platform/efi/efi.c      |    3 +++
 include/linux/efi.h              |    3 ++-
 7 files changed, 38 insertions(+), 4 deletions(-)

Comments

Andy Lutomirski April 28, 2015, 8:49 p.m. UTC | #1
On Tue, Apr 28, 2015 at 11:24 AM, Dan Williams <dan.j.williams@intel.com> wrote:
> ACPI 6.0 formalizes e820-type-7 and efi-type-14 as persistent memory.
> Mark it "reserved" and allow it to be claimed by a persistent memory
> device driver.
>
> This definition is in addition to the Linux kernel's existing type-12
> definition that was recently added in support of shipping platforms with
> NVDIMM support that predate ACPI 6.0 (which now classifies type-12 as
> OEM reserved).  We may choose to exploit this wealth of definitions for
> NVDIMMs to differentiate E820_PRAM (type-12) from E820_PMEM (type-7).
> One potential differentiation is that PMEM is not backed by struct page
> by default in contrast to PRAM.  For now, they are effectively treated
> as aliases by the mm.
>
> Note, /proc/iomem can be consulted for differentiating legacy
> "Persistent RAM" E820_PRAM vs standard "Persistent I/O Memory"
> E820_PMEM.
>
> Cc: Boaz Harrosh <boaz@plexistor.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: Jens Axboe <axboe@fb.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Matthew Wilcox <willy@linux.intel.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Acked-by: Andy Lutomirski <luto@amacapital.net>
> Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/arm64/kernel/efi.c          |    1 +
>  arch/ia64/kernel/efi.c           |    4 ++++
>  arch/x86/boot/compressed/eboot.c |    4 ++++
>  arch/x86/include/uapi/asm/e820.h |    1 +
>  arch/x86/kernel/e820.c           |   26 +++++++++++++++++++++++---
>  arch/x86/platform/efi/efi.c      |    3 +++
>  include/linux/efi.h              |    3 ++-
>  7 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index ab21e0d58278..9d4aa18f2a82 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -158,6 +158,7 @@ static __init int is_reserve_region(efi_memory_desc_t *md)
>         case EFI_BOOT_SERVICES_CODE:
>         case EFI_BOOT_SERVICES_DATA:
>         case EFI_CONVENTIONAL_MEMORY:
> +       case EFI_PERSISTENT_MEMORY:
>                 return 0;
>         default:
>                 break;
> diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
> index c52d7540dc05..9028bc268cd7 100644
> --- a/arch/ia64/kernel/efi.c
> +++ b/arch/ia64/kernel/efi.c
> @@ -1223,6 +1223,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
>                                 flags |= IORESOURCE_DISABLED;
>                                 break;
>
> +                       case EFI_PERSISTENT_MEMORY:
> +                               name = "persistent";
> +                               break;
> +
>                         case EFI_RESERVED_TYPE:
>                         case EFI_RUNTIME_SERVICES_CODE:
>                         case EFI_RUNTIME_SERVICES_DATA:
> diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> index ef17683484e9..dde5bf7726f4 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -1222,6 +1222,10 @@ static efi_status_t setup_e820(struct boot_params *params,
>                         e820_type = E820_NVS;
>                         break;
>
> +               case EFI_PERSISTENT_MEMORY:
> +                       e820_type = E820_PMEM;
> +                       break;
> +
>                 default:
>                         continue;
>                 }
> diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
> index 960a8a9dc4ab..0f457e6eab18 100644
> --- a/arch/x86/include/uapi/asm/e820.h
> +++ b/arch/x86/include/uapi/asm/e820.h
> @@ -32,6 +32,7 @@
>  #define E820_ACPI      3
>  #define E820_NVS       4
>  #define E820_UNUSABLE  5
> +#define E820_PMEM      7
>
>  /*
>   * This is a non-standardized way to represent ADR or NVDIMM regions that
> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
> index 11cc7d54ec3f..d38b53a7e9b2 100644
> --- a/arch/x86/kernel/e820.c
> +++ b/arch/x86/kernel/e820.c
> @@ -149,6 +149,7 @@ static void __init e820_print_type(u32 type)
>         case E820_UNUSABLE:
>                 printk(KERN_CONT "unusable");
>                 break;
> +       case E820_PMEM:
>         case E820_PRAM:
>                 printk(KERN_CONT "persistent (type %u)", type);
>                 break;

I'd kind of like to make it more clear what's going on here.  It
doesn't help that the spec chose poor names.

How about "NVDIMM physical aperture" for E820_PMEM and "legacy
persistent RAM" for E820_PRAM?

Otherwise this looks generaly sensible, although I don't really
understand why e820_type_to_string and e820_print_type are different.

--Andy
Dan Williams April 28, 2015, 8:57 p.m. UTC | #2
On Tue, Apr 28, 2015 at 1:49 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Tue, Apr 28, 2015 at 11:24 AM, Dan Williams <dan.j.williams@intel.com> wrote:
>> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
>> index 11cc7d54ec3f..d38b53a7e9b2 100644
>> --- a/arch/x86/kernel/e820.c
>> +++ b/arch/x86/kernel/e820.c
>> @@ -149,6 +149,7 @@ static void __init e820_print_type(u32 type)
>>         case E820_UNUSABLE:
>>                 printk(KERN_CONT "unusable");
>>                 break;
>> +       case E820_PMEM:
>>         case E820_PRAM:
>>                 printk(KERN_CONT "persistent (type %u)", type);
>>                 break;
>
> I'd kind of like to make it more clear what's going on here.  It
> doesn't help that the spec chose poor names.
>
> How about "NVDIMM physical aperture" for E820_PMEM and "legacy
> persistent RAM" for E820_PRAM?

The term "aperture" to me implies this BLK (mmio-windowed) mode of
accessing persistent media that the NFIT specification introduces.  In
fact, those ranges are mapped E820_RESERVED.  E820_PMEM really is a
memory range that happens to be persistent.

> Otherwise this looks generaly sensible, although I don't really
> understand why e820_type_to_string and e820_print_type are different.

 e820_type_to_string() appears in /proc/iomem and seems to afford
being more descriptive than e820_print_type() that just scrolls by in
dmesg, but I'm just guessing.
Andy Lutomirski April 28, 2015, 9:05 p.m. UTC | #3
On Tue, Apr 28, 2015 at 1:57 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> On Tue, Apr 28, 2015 at 1:49 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Tue, Apr 28, 2015 at 11:24 AM, Dan Williams <dan.j.williams@intel.com> wrote:
>>> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
>>> index 11cc7d54ec3f..d38b53a7e9b2 100644
>>> --- a/arch/x86/kernel/e820.c
>>> +++ b/arch/x86/kernel/e820.c
>>> @@ -149,6 +149,7 @@ static void __init e820_print_type(u32 type)
>>>         case E820_UNUSABLE:
>>>                 printk(KERN_CONT "unusable");
>>>                 break;
>>> +       case E820_PMEM:
>>>         case E820_PRAM:
>>>                 printk(KERN_CONT "persistent (type %u)", type);
>>>                 break;
>>
>> I'd kind of like to make it more clear what's going on here.  It
>> doesn't help that the spec chose poor names.
>>
>> How about "NVDIMM physical aperture" for E820_PMEM and "legacy
>> persistent RAM" for E820_PRAM?
>
> The term "aperture" to me implies this BLK (mmio-windowed) mode of
> accessing persistent media that the NFIT specification introduces.  In
> fact, those ranges are mapped E820_RESERVED.  E820_PMEM really is a
> memory range that happens to be persistent.

Oh, I missed that.  Yuck.  What happens when you repartition one of
these things?  (Can you even do that?)

>
>> Otherwise this looks generaly sensible, although I don't really
>> understand why e820_type_to_string and e820_print_type are different.
>
>  e820_type_to_string() appears in /proc/iomem and seems to afford
> being more descriptive than e820_print_type() that just scrolls by in
> dmesg, but I'm just guessing.

Can we change that?
Jeff Moyer May 15, 2015, 3:43 p.m. UTC | #4
Dan Williams <dan.j.williams@intel.com> writes:

> @@ -919,10 +920,31 @@ static inline const char *e820_type_to_string(int e820_type)
>  	case E820_NVS:	return "ACPI Non-volatile Storage";
>  	case E820_UNUSABLE:	return "Unusable memory";
>  	case E820_PRAM: return "Persistent RAM";
> +	case E820_PMEM: return "Persistent I/O Memory";

Minor nit, but nobody refers to this stuff as persistent I/O memory.
I've heard it referred to as persistent memory or storage class memory.
In the end, I doubt it matters.

Acked-by: Jeff Moyer <jmoyer@redhat.com>
Dan Williams May 15, 2015, 3:48 p.m. UTC | #5
On Fri, May 15, 2015 at 8:43 AM, Jeff Moyer <jmoyer@redhat.com> wrote:
> Dan Williams <dan.j.williams@intel.com> writes:
>
>> @@ -919,10 +920,31 @@ static inline const char *e820_type_to_string(int e820_type)
>>       case E820_NVS:  return "ACPI Non-volatile Storage";
>>       case E820_UNUSABLE:     return "Unusable memory";
>>       case E820_PRAM: return "Persistent RAM";
>> +     case E820_PMEM: return "Persistent I/O Memory";
>
> Minor nit, but nobody refers to this stuff as persistent I/O memory.
> I've heard it referred to as persistent memory or storage class memory.
> In the end, I doubt it matters.

Had we not polluted the waters with E820_PRAM I would have chosen
"Persistent Memory", but as we now need to support both I'd assume
they need different names.

> Acked-by: Jeff Moyer <jmoyer@redhat.com>

Thanks Jeff.
Andy Lutomirski May 18, 2015, 7:28 p.m. UTC | #6
On May 16, 2015 12:48 AM, "Dan Williams" <dan.j.williams@intel.com> wrote:
>
> On Fri, May 15, 2015 at 8:43 AM, Jeff Moyer <jmoyer@redhat.com> wrote:
> > Dan Williams <dan.j.williams@intel.com> writes:
> >
> >> @@ -919,10 +920,31 @@ static inline const char *e820_type_to_string(int e820_type)
> >>       case E820_NVS:  return "ACPI Non-volatile Storage";
> >>       case E820_UNUSABLE:     return "Unusable memory";
> >>       case E820_PRAM: return "Persistent RAM";
> >> +     case E820_PMEM: return "Persistent I/O Memory";
> >
> > Minor nit, but nobody refers to this stuff as persistent I/O memory.
> > I've heard it referred to as persistent memory or storage class memory.
> > In the end, I doubt it matters.
>
> Had we not polluted the waters with E820_PRAM I would have chosen
> "Persistent Memory", but as we now need to support both I'd assume
> they need different names.

We could reverse it and call E820_PRAM "legacy persistent RAM" or
something similar.

</bikeshed>

>
> > Acked-by: Jeff Moyer <jmoyer@redhat.com>
>
> Thanks Jeff.
diff mbox

Patch

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index ab21e0d58278..9d4aa18f2a82 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -158,6 +158,7 @@  static __init int is_reserve_region(efi_memory_desc_t *md)
 	case EFI_BOOT_SERVICES_CODE:
 	case EFI_BOOT_SERVICES_DATA:
 	case EFI_CONVENTIONAL_MEMORY:
+	case EFI_PERSISTENT_MEMORY:
 		return 0;
 	default:
 		break;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index c52d7540dc05..9028bc268cd7 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -1223,6 +1223,10 @@  efi_initialize_iomem_resources(struct resource *code_resource,
 				flags |= IORESOURCE_DISABLED;
 				break;
 
+			case EFI_PERSISTENT_MEMORY:
+				name = "persistent";
+				break;
+
 			case EFI_RESERVED_TYPE:
 			case EFI_RUNTIME_SERVICES_CODE:
 			case EFI_RUNTIME_SERVICES_DATA:
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ef17683484e9..dde5bf7726f4 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1222,6 +1222,10 @@  static efi_status_t setup_e820(struct boot_params *params,
 			e820_type = E820_NVS;
 			break;
 
+		case EFI_PERSISTENT_MEMORY:
+			e820_type = E820_PMEM;
+			break;
+
 		default:
 			continue;
 		}
diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
index 960a8a9dc4ab..0f457e6eab18 100644
--- a/arch/x86/include/uapi/asm/e820.h
+++ b/arch/x86/include/uapi/asm/e820.h
@@ -32,6 +32,7 @@ 
 #define E820_ACPI	3
 #define E820_NVS	4
 #define E820_UNUSABLE	5
+#define E820_PMEM	7
 
 /*
  * This is a non-standardized way to represent ADR or NVDIMM regions that
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 11cc7d54ec3f..d38b53a7e9b2 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -149,6 +149,7 @@  static void __init e820_print_type(u32 type)
 	case E820_UNUSABLE:
 		printk(KERN_CONT "unusable");
 		break;
+	case E820_PMEM:
 	case E820_PRAM:
 		printk(KERN_CONT "persistent (type %u)", type);
 		break;
@@ -919,10 +920,31 @@  static inline const char *e820_type_to_string(int e820_type)
 	case E820_NVS:	return "ACPI Non-volatile Storage";
 	case E820_UNUSABLE:	return "Unusable memory";
 	case E820_PRAM: return "Persistent RAM";
+	case E820_PMEM: return "Persistent I/O Memory";
 	default:	return "reserved";
 	}
 }
 
+static bool do_mark_busy(u32 type, struct resource *res)
+{
+	/* this is the legacy bios/dos rom-shadow + mmio region */
+	if (res->start < (1ULL<<20))
+		return true;
+
+	/*
+	 * Treat persistent memory like device memory, i.e. reserve it
+	 * for exclusive use of a driver
+	 */
+	switch (type) {
+	case E820_RESERVED:
+	case E820_PRAM:
+	case E820_PMEM:
+		return false;
+	default:
+		return true;
+	}
+}
+
 /*
  * Mark e820 reserved areas as busy for the resource manager.
  */
@@ -952,9 +974,7 @@  void __init e820_reserve_resources(void)
 		 * pci device BAR resource and insert them later in
 		 * pcibios_resource_survey()
 		 */
-		if (((e820.map[i].type != E820_RESERVED) &&
-		     (e820.map[i].type != E820_PRAM)) ||
-		     res->start < (1ULL<<20)) {
+		if (do_mark_busy(e820.map[i].type, res)) {
 			res->flags |= IORESOURCE_BUSY;
 			insert_resource(&iomem_resource, res);
 		}
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index dbc8627a5cdf..a116e236ac3f 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -145,6 +145,9 @@  static void __init do_add_efi_memmap(void)
 		case EFI_UNUSABLE_MEMORY:
 			e820_type = E820_UNUSABLE;
 			break;
+		case EFI_PERSISTENT_MEMORY:
+			e820_type = E820_PMEM;
+			break;
 		default:
 			/*
 			 * EFI_RESERVED_TYPE EFI_RUNTIME_SERVICES_CODE
diff --git a/include/linux/efi.h b/include/linux/efi.h
index cf7e431cbc73..28868504aa17 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -85,7 +85,8 @@  typedef	struct {
 #define EFI_MEMORY_MAPPED_IO		11
 #define EFI_MEMORY_MAPPED_IO_PORT_SPACE	12
 #define EFI_PAL_CODE			13
-#define EFI_MAX_MEMORY_TYPE		14
+#define EFI_PERSISTENT_MEMORY		14
+#define EFI_MAX_MEMORY_TYPE		15
 
 /* Attribute values: */
 #define EFI_MEMORY_UC		((u64)0x0000000000000001ULL)	/* uncached */