grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

grub causing NVDIMMs to be treated as normal memory


From: Elliott, Robert (Persistent Memory)
Subject: grub causing NVDIMMs to be treated as normal memory
Date: Tue, 24 Nov 2015 23:52:39 +0000

We've noticed that some combinations of grub and old linux kernels

end up interpreting the UEFI memory map EfiPersistentMemory type 14

(formerly a reserved value) as regular memory in the linux e820

table, causing silent data corruption on the NVDIMMs.  That occurs

even though grub prints this message suggesting everything is safe:

    Unknown memory type 14, considering reserved

 

In broken versions of grub, the code parsing the UEFI memory map

has a "default" case that falls through to the

GRUB_EFI_BOOT_SERVICES_DATA case, which marks the memory range

as GRUB_MEMORY_AVAILABLE and ends up in e820 as regular memory.

 

In unbroken versions of grub, that "default" case falls through to

the GRUB_EFI_RESERVED_MEMORY_TYPE case, which marks the memory range

as GRUB_MACHINE_MEMORY_RESERVED and ends up in e820 as reserved.

 

Each of these kernels behaves differently:

* without EFI boot stub (pre-2011 kernel 3.3)

* with EFI boot stub (May 2015, kernel 4.1)

* with EFI boot stub, with May 2015 patch to understand type 14

 

Kernels that don't have the EFI boot stub are at the mercy of how

grub translates the memory map.  I'm not sure how the pre-4.1

EFI boot stub kernels worked. New kernels work fine.

 

Does anyone know how prevalent the use of dangerous combinations

might be?

 

Might other OS loaders (syslinux, elilo, ?) have issues like this?

 

 

Example broken grub code

========================

http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/mmap/efi/mmap.c:

 

grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,

                     int avoid_efi_boot_services)

{

...

       case GRUB_EFI_UNUSABLE_MEMORY:

         hook (desc->physical_start, desc->num_pages * 4096,

              GRUB_MEMORY_BADRAM, hook_data);

         break;

 

       default:

         grub_printf ("Unknown memory type %d, considering reserved\n",

                     desc->type);

 

       case GRUB_EFI_BOOT_SERVICES_DATA:

         if (!avoid_efi_boot_services)

           {

             hook (desc->physical_start, desc->num_pages * 4096,

                  GRUB_MEMORY_AVAILABLE, hook_data);

             break;

           }

       case GRUB_EFI_RESERVED_MEMORY_TYPE:

       case GRUB_EFI_RUNTIME_SERVICES_DATA:

       case GRUB_EFI_MEMORY_MAPPED_IO:

       case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:

       case GRUB_EFI_PAL_CODE:

         hook (desc->physical_start, desc->num_pages * 4096,

              GRUB_MEMORY_RESERVED, hook_data);

         break;

 

Example unbroken grub code

==========================

https://github.com/jolicloud/grub2/blob/master/mmap/efi/mmap.c:

 

grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,

                                                grub_uint64_t,

                                                grub_uint32_t))

{

...

       default:

         grub_printf ("Unknown memory type %d, considering reserved\n",

                     desc->type);

 

       case GRUB_EFI_RESERVED_MEMORY_TYPE:

       case GRUB_EFI_RUNTIME_SERVICES_DATA:

       case GRUB_EFI_UNUSABLE_MEMORY:

       case GRUB_EFI_MEMORY_MAPPED_IO:

       case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:

       case GRUB_EFI_PAL_CODE:

         hook (desc->physical_start, desc->num_pages * 4096,

              GRUB_MACHINE_MEMORY_RESERVED);

         break;

 

       case GRUB_EFI_LOADER_CODE:

       case GRUB_EFI_LOADER_DATA:

       case GRUB_EFI_BOOT_SERVICES_CODE:

       case GRUB_EFI_BOOT_SERVICES_DATA:

       case GRUB_EFI_CONVENTIONAL_MEMORY:

         hook (desc->physical_start, desc->num_pages * 4096,

              GRUB_MACHINE_MEMORY_AVAILABLE);

         break;

 

 

---

Robert Elliott, HPE Persistent Memory

 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]