arm64: stable UEFI mappings for kexec
v3 cover arm64: stable UEFI mappings for kexec
This is v3 of the series to update the UEFI memory map handling for the arm64 architecture so that:
- virtual mappings of UEFI Runtime Services are stable across kexec
- userland mappings via /dev/mem use cache attributes that are compatible with the memory type of the UEFI memory map entry
- code that can be reused for 32-bit ARM is moved to a common area.
This time, I tried to address the following concerns:
- raised by Mark Salter, regarding the use of page_is_ram() in ACPI code, and the ability to infer memory attributes from it;
- raised by Mark Rutland, regarding the need to address the non-EFI case as well.
The general idea is to make more use of the iomem resource table. In this series, instead of not installing memblocks for reserved regions, they are installed using memblock_add() directly (which is page size agnostic, and so doesn't do any rounding), which is closer to Mark Salter's original approach, only now, there is no need to deal with the unaligned residues. As a result, all memory with the EFI_MEMORY_WB attribute is covered by a 'System RAM' iomem resource, which makes page_is_ram() work as expected again.
Then, in addition to memblock_reserve()'ing the RAM regions reserved by UEFI, they are memblock_remove()'d as well, but only after the 'System RAM' regions have been set up by the existing code. This way, we can wire up pfn_valid() and page_is_ram() so that the former will tell us whether the kernel may actually be using a pfn, whereas the latter will tell us whether it needs to be mapped MT_NORMAL. This greatly simplifies the /dev/mem handling under CONFIG_STRICT_DEVMEM, and unifies the EFI and non-EFI cases.
All UEFI memory regions are installed as iomem resources themselves. This helps prevent drivers from attaching to devices that are also driven by the firmware, but regions subordinate to 'System RAM' are also added. This is an example taken from QEMU/mach-virt:
04000000-07ffffff : UEFI Runtime I/O
09000000-09000fff : /pl011 at 9000000
09000000-09000fff : uart-pl011
09010000-09010fff : UEFI Runtime I/O
0a000000-0a0001ff : a000000.virtio_mmio
[...]
0a003e00-0a003fff : a003e00.virtio_mmio
40000000-bfffffff : System RAM
40080000-406ff1e3 : Kernel code
4073d000-407e4fff : Kernel data
b711d000-b71dffff : UEFI Reserved
bfb21000-bfb34fff : UEFI Reserved
bfb35000-bfb66fff : UEFI Reserved
bfb6a000-bfb6afff : UEFI Reserved
bfb82000-bfb82fff : UEFI Reserved
MMIO regions without the EFI_MEMORY_RUNTIME attribute will be registered as 'UEFI Reserved', non-busy and non-exclusive, so drivers (and /dev/mem) can still bind to them.
Changes with respect to v2:
- removed EFI specific memory attribute handling from virtmap.c
- added iomem resource handling
- make /dev/mem handling EFI-agnostic
- added two patches to round up allocations done by the stub to 64 KB; this is not strictly necessary now that we are using memblock_add() directly, but it is an improvement for arm64 regardless.
============== v1 blurb ==================
The main premise of these patches is that, in order to support kexec, we need to add code to the kernel that is able to deal with the state of the firmware after SetVirtualAddressMap() [SVAM] has been called. However, if we are going to deal with that anyway, why not make that the default state, and have only a single code path for both cases.
This means SVAM() needs to move to the stub, and hence the code that invents the virtual layout needs to move with it. The result is that the kernel proper is entered with the virt_addr members of all EFI_MEMORY_RUNTIME regions assigned, and the mapping installed into the firmware. The kernel proper needs to set up the page tables, and switch to them while performing the runtime services calls. Note that there is also an efi_to_phys() to translate the values of the fw_vendor and tables fields of the EFI system table. Again, this is something we need to do anyway under kexec, or we end up handing over state between one kernel and the next, which implies different code paths between non-kexec and kexec.
The layout is chosen such that it used the userland half of the virtual address space (TTBR0), which means no additional alignment or reservation is required to ensure that it will always be available.
One thing that may stand out is the reordering of the memory map. The reason for doing this is that we can use the same memory map as input to SVAM(). The alternative is allocating memory for it using boot services, but that clutters up the existing logic a bit between getting the memory map, populating the fdt, and loop again if it didn't fit.
Ard Biesheuvel (13):
arm64/mm: add explicit struct_mm argument to __create_mapping() arm64/mm: add create_pgd_mapping() to create private page tables
arm64: improve CONFIG_STRICT_DEVMEM handling
efi: split off remapping code from efi_config_init()
efi: add common infrastructure for stub-installed virtual mapping
efi: register iomem resources for UEFI reserved regions arm64/efi: move SetVirtualAddressMap() to UEFI stub arm64/efi: remove free_boot_services() and friends arm64/efi: remove idmap manipulations from UEFI code arm64/efi: use UEFI memory map unconditionally if available arm64/efi: use plain memblock API for adding and removing reserved RAM
efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE arm64/efi: set EFI_ALLOC_ALIGN to 64 KB
arch/arm64/Kconfig | 1 + arch/arm64/include/asm/efi.h | 20 +- arch/arm64/include/asm/mmu.h | 5 +- arch/arm64/include/asm/pgtable.h | 5 + arch/arm64/kernel/efi.c | 331 +++---------------------- arch/arm64/kernel/setup.c | 2 +- arch/arm64/mm/mmap.c | 5 +- arch/arm64/mm/mmu.c | 75 +++--- drivers/firmware/efi/Kconfig | 3 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efi.c | 49 ++-- drivers/firmware/efi/libstub/efi-stub-helper.c | 25 +- drivers/firmware/efi/libstub/fdt.c | 107 +++++++- drivers/firmware/efi/virtmap.c | 173 +++++++++++++ include/linux/efi.h | 14 +- 15 files changed, 447 insertions(+), 369 deletions(-) create mode 100644 drivers/firmware/efi/virtmap.c
Signature · 1 line
1.8.3.2
PATCH v3 1/13 arm64/mm: add explicit struct_mm argument to __create_mapping()
Currently, swapper_pg_dir and idmap_pg_dir share the init_mm mm_struct instance. To allow the introduction of other pg_dir instances, for instance, for UEFI's mapping of Runtime Services, make the struct_mm instance an explicit argument that gets passed down to the pmd and pte instantiation functions. Note that the consumers (pmd_populate/pgd_populate) of the mm_struct argument don't actually inspect it, but let's fix it for correctness' sake.
--- arch/arm64/mm/mmu.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-)
arch/arm64/mm/mmu.c +16 -15
@@ -155,9 +155,9 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, }while (pte++, addr +=PAGE_SIZE , addr != end); } -static void __init alloc_init_pmd (pud_t *pud,unsigned long addr, -unsigned long end,phys_addr_t phys, -int map_io) +static void __init alloc_init_pmd (struct mm_struct *mm,pud_t *pud, +unsigned long addr,unsigned long end, +phys_addr_t phys,int map_io) {pmd_t *pmd;unsigned long next;
@@ -177,7 +177,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,*/ if (pud_none (*pud) ||pud_bad (*pud)) { pmd =early_alloc (PTRS_PER_PMD *sizeof (pmd_t)); -pud_populate (&init_mm, pud, pmd); +pud_populate (mm, pud, pmd); } pmd =pmd_offset (pud, addr);
@@ -201,16 +201,16 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, }while (pmd++, addr = next, addr != end); } -static void __init alloc_init_pud (pgd_t *pgd,unsigned long addr, -unsigned long end,unsigned long phys, -int map_io) +static void __init alloc_init_pud (struct mm_struct *mm,pgd_t *pgd, +unsigned long addr,unsigned long end, +unsigned long phys,int map_io) {pud_t *pud;unsigned long next;if (pgd_none (*pgd)) { pud =early_alloc (PTRS_PER_PUD *sizeof (pud_t)); -pgd_populate (&init_mm, pgd, pud); +pgd_populate (mm, pgd, pud); }BUG_ON (pgd_bad (*pgd));
@@ -239,7 +239,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,flush_tlb_all (); } }else { -alloc_init_pmd (pud, addr, next, phys, map_io); +alloc_init_pmd (mm, pud, addr, next, phys, map_io); } phys += next - addr; }while (pud++, addr = next, addr != end);
@@ -249,9 +249,9 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,* Create the page directory entries and any necessary page tables for the * mapping specified by 'md'. */ -static void __init __create_mapping (pgd_t *pgd,phys_addr_t phys, -unsigned long virt,phys_addr_t size, -int map_io) +static void __init __create_mapping (struct mm_struct *mm,pgd_t *pgd, +phys_addr_t phys,unsigned long virt, +phys_addr_t size,int map_io) {unsigned long addr, length, end, next;
@@ -261,7 +261,7 @@ static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, end = addr + length;do { next =pgd_addr_end (addr, end); -alloc_init_pud (pgd, addr, next, phys, map_io); +alloc_init_pud (mm, pgd, addr, next, phys, map_io); phys += next - addr; }while (pgd++, addr = next, addr != end); }
@@ -274,7 +274,8 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, &phys, virt);return ; } -__create_mapping (pgd_offset_k (virt &PAGE_MASK ), phys, virt, size,0 ); +__create_mapping (&init_mm,pgd_offset_k (virt &PAGE_MASK ), phys, virt, + size,0 ); }void __init create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io)
@@ -283,7 +284,7 @@ void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io)pr_warn ("BUG: not creating id mapping for %pa\n" , &addr);return ; } -__create_mapping (&idmap_pg_dir[pgd_index (addr)], +__create_mapping (&init_mm, &idmap_pg_dir[pgd_index (addr)], addr, addr, size, map_io); }
Signature · 1 line
1.8.3.2
PATCH v3 2/13 arm64/mm: add create_pgd_mapping() to create private page tables
In reply to Ard BiesheuvelFor UEFI, we need to install the memory mappings used for Runtime Services in a dedicated set of page tables. Add create_pgd_mapping(), which allows us to allocate and install those page table entries early.
--- arch/arm64/include/asm/mmu.h | 3 +++ arch/arm64/include/asm/pgtable.h | 5 +++++ arch/arm64/mm/mmu.c | 43 ++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 21 deletions(-)
arch/arm64/include/asm/mmu.h +3 -0
@@ -33,5 +33,8 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);extern void init_mem_pgprot (void );/* create an identity mapping for memory (or io if map_io is true) */ extern void create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io); +extern void create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys, +unsigned long virt,phys_addr_t size, +pgprot_t prot);#endif
arch/arm64/include/asm/pgtable.h +5 -0
@@ -264,6 +264,11 @@ static inline pmd_t pte_pmd(pte_t pte)return __pmd (pte_val (pte)); } +static inline pgprot_t mk_sect_prot (pgprot_t prot) +{ +return __pgprot (pgprot_val (prot) & ~PTE_TABLE_BIT ); +} +/* * THP definitions. */
arch/arm64/mm/mmu.c +22 -21
108 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH v3 2/13 arm64/mm: add create_pgd_mapping() to create private page tables
Quoted 10 lines · Ard Biesheuvel
For UEFI, we need to install the memory mappings used for Runtime Services in a dedicated set of page tables. Add
create_pgd_mapping(), which allows us to allocate and install those page table entries early.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/include/asm/mmu.h | 3 +++ arch/arm64/include/asm/pgtable.h | 5 +++++ arch/arm64/mm/mmu.c | 43 ++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 21 deletions(-)
Looks fairly mechanical to me:
Will
Quoted 155 lines
arch/arm64/include/asm/mmu.h +3
-0@@ -33,5 +33,8 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);extern void init_mem_pgprot (void );/* create an identity mapping for memory (or io if map_io is true) */ extern void create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io); +extern void create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys, +unsigned long virt,phys_addr_t size, +pgprot_t prot);#endif arch/arm64/include/asm/pgtable.h +5
-0@@ -264,6 +264,11 @@ static inline pmd_t pte_pmd(pte_t pte)return __pmd (pte_val (pte)); } +static inline pgprot_t mk_sect_prot (pgprot_t prot) +{ +return __pgprot (pgprot_val (prot) & ~PTE_TABLE_BIT ); +} +/* * THP definitions. */ arch/arm64/mm/mmu.c +22
-21@@ -157,20 +157,10 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,static void __init alloc_init_pmd (struct mm_struct *mm,pud_t *pud,unsigned long addr,unsigned long end, -phys_addr_t phys,int map_io) +phys_addr_t phys,pgprot_t prot) {pmd_t *pmd;unsigned long next; -pmdval_t prot_sect; -pgprot_t prot_pte; - -if (map_io) { - prot_sect = PROT_SECT_DEVICE_nGnRE; - prot_pte =__pgprot (PROT_DEVICE_nGnRE); - }else { - prot_sect =PROT_SECT_NORMAL_EXEC ; - prot_pte =PAGE_KERNEL_EXEC ; - }/* * Check for initial section mappings in the pgd/pud and remove them. @@ -186,7 +176,8 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud,/* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK ) ==0 ) {pmd_t old_pmd =*pmd; -set_pmd (pmd,__pmd (phys | prot_sect)); +set_pmd (pmd,__pmd (phys | +pgprot_val (mk_sect_prot (prot))));/* * Check for previous table entries created during * boot (__create_page_tables) and flush them. @@ -195,7 +186,7 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud,flush_tlb_all (); }else {alloc_init_pte (pmd, addr, next,__phys_to_pfn (phys), - prot_pte); + prot); } phys += next - addr; }while (pmd++, addr = next, addr != end);@@ -203,7 +194,7 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud,static void __init alloc_init_pud (struct mm_struct *mm,pgd_t *pgd,unsigned long addr,unsigned long end, -unsigned long phys,int map_io) +unsigned long phys,pgprot_t prot) {pud_t *pud;unsigned long next;@@ -221,10 +212,11 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd,/* * For 4K granule only, attempt to put down a 1GB block */ -if (!map_io && (PAGE_SHIFT ==12 ) && +if ((PAGE_SHIFT ==12 ) && ((addr | next | phys) & ~PUD_MASK ) ==0 ) {pud_t old_pud = *pud; -set_pud (pud,__pud (phys |PROT_SECT_NORMAL_EXEC )); +set_pud (pud,__pud (phys | +pgprot_val (mk_sect_prot (prot))));/* * If we have an old value for a pud, it will @@ -239,7 +231,7 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd,flush_tlb_all (); } }else { -alloc_init_pmd (mm, pud, addr, next, phys, map_io); +alloc_init_pmd (mm, pud, addr, next, phys, prot); } phys += next - addr; }while (pud++, addr = next, addr != end);@@ -251,7 +243,7 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd,*/ static void __init __create_mapping (struct mm_struct *mm,pgd_t *pgd,phys_addr_t phys,unsigned long virt, -phys_addr_t size,int map_io) +phys_addr_t size,pgprot_t prot) {unsigned long addr, length, end, next;@@ -261,7 +253,7 @@ static void __init __create_mapping(struct mm_struct *mm, pgd_t *pgd, end = addr + length;do { next =pgd_addr_end (addr, end); -alloc_init_pud (mm, pgd, addr, next, phys, map_io); +alloc_init_pud (mm, pgd, addr, next, phys, prot); phys += next - addr; }while (pgd++, addr = next, addr != end); }@@ -275,7 +267,7 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt,return ; }__create_mapping (&init_mm,pgd_offset_k (virt &PAGE_MASK ), phys, virt, - size,0 ); + size,PAGE_KERNEL_EXEC ); }void __init create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io)@@ -285,7 +277,16 @@ void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io)return ; }__create_mapping (&init_mm, &idmap_pg_dir[pgd_index (addr)], - addr, addr, size, map_io); + addr, addr, size, + map_io ?__pgprot (PROT_DEVICE_nGnRE) + :PAGE_KERNEL_EXEC ); +} + +void __init create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys, +unsigned long virt,phys_addr_t size, +pgprot_t prot) +{ +__create_mapping (mm,pgd_offset (mm, virt), phys, virt, size, prot); }static void __init map_mem (void )Signature · 1 line
1.8.3.2
PATCH v3 3/13 arm64: improve CONFIG_STRICT_DEVMEM handling
In reply to Ard BiesheuvelImprove the handling of /dev/mem mappings under CONFIG_STRICT_DEVMEM by:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;
- avoid using non-cached mappings for those parts of System RAM, as it may result in mismatched attributes.
--- arch/arm64/mm/mmap.c | 5 +++-- arch/arm64/mm/mmu.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-)
arch/arm64/mm/mmap.c +3 -2
@@ -127,14 +127,15 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)/* * devmem_is_allowed() checks to see if /dev/mem access to a certain address * is valid. The argument is a physical page number. We mimic x86 here by -* disallowing access to system RAM as well as device-exclusive MMIO regions. +* disallowing access to system RAM that is in active use by the kernel, as +* well as device-exclusive MMIO regions. * This effectively disable read()/write() on /dev/mem. */ int devmem_is_allowed (unsigned long pfn) {if (iomem_is_exclusive (pfn <<PAGE_SHIFT ))return 0 ; -if (!page_is_ram (pfn)) +if (!pfn_valid (pfn))return 1 ;return 0 ; }
arch/arm64/mm/mmu.c +14 -1
@@ -121,7 +121,7 @@ early_param("cachepolicy", early_cachepolicy);pgprot_t phys_mem_access_prot (struct file *file,unsigned long pfn,unsigned long size,pgprot_t vma_prot) { -if (!pfn_valid (pfn)) +if (!page_is_ram (pfn))return pgprot_noncached (vma_prot);else if (file->f_flags &O_SYNC )return pgprot_writecombine (vma_prot);
@@ -129,6 +129,19 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, }EXPORT_SYMBOL (phys_mem_access_prot); +/* +* This definition of phys_mem_access_prot_allowed() overrides +* the __weak definition in drivers/char/mem.c +*/ +int phys_mem_access_prot_allowed (struct file *file,unsigned long pfn, +unsigned long size,pgprot_t *prot) +{ +/* Disallow read-write access to reserved system RAM */ +if ((pgprot_val (*prot) &PTE_WRITE ) &&page_is_ram (pfn)) +return 0 ; +return 1 ; +} +static void __init *early_alloc (unsigned long sz) {void *ptr =__va (memblock_alloc (sz, sz));
Signature · 1 line
1.8.3.2
Re: [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
Quoted 6 lines · Ard Biesheuvel
Improve the handling of
/dev/memmappings underCONFIG_STRICT_DEVMEMby:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;
- avoid using non-cached mappings for those parts of System RAM, as it may result in mismatched attributes.
Is this really the best way to expose EFI config tables?
We already have parts in /sys/firmware/efi/ and in particular we expose the runtime mappings there for kexec on x86.
Hooking this into the /dev/mem infrastructure just seems wrong to me.
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
Re: [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
Quoted 8 lines · Matt Fleming
Quoted 6 lines · Ard Biesheuvel
Improve the handling of
/dev/memmappings underCONFIG_STRICT_DEVMEMby:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;
- avoid using non-cached mappings for those parts of System RAM, as it may result in mismatched attributes.
Quoted 4 lines
Is this really the best way to expose EFI config tables?
We already have parts in
/sys/firmware/efi/and in particular we expose the runtime mappings there for kexec on x86.
Yeah!
Quoted 1 line
Hooking this into the
/dev/meminfrastructure just seems wrong to me.
And this virtmap.c thing is arm-only, AFAICT, but it looks like generic code and like a wholly new way of doing the efi page table.
This thing needs to be properly split into generic pieces which go into drivers/firmware/efi/ and arm-specific which would make that EFI_VIRTMAP into an arch bit.
And so on and so on...
Signature · 5 lines
Regards/Gruss,
Boris.
Sent from a fat crate under my desk. Formatting is fine.
--PATCH v3 3/13 arm64: improve CONFIG_STRICT_DEVMEM handling
In reply to Ard BiesheuvelQuoted 4 lines · Ard Biesheuvel
Improve the handling of
/dev/memmappings underCONFIG_STRICT_DEVMEMby:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;
Ard, can you elabrate a bit? Are this for the acpi case because no dtb in procfs?
Anyway I also think using /dev/mem looks not a good way to expose infomation to userspace.
Quoted 67 lines
- avoid using non-cached mappings for those parts of System RAM, as it may result in mismatched attributes.
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/mm/mmap.c | 5 +++-- arch/arm64/mm/mmu.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-)arch/arm64/mm/mmap.c +3
-2@@ -127,14 +127,15 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)/* * devmem_is_allowed() checks to see if /dev/mem access to a certain address * is valid. The argument is a physical page number. We mimic x86 here by -* disallowing access to system RAM as well as device-exclusive MMIO regions. +* disallowing access to system RAM that is in active use by the kernel, as +* well as device-exclusive MMIO regions. * This effectively disable read()/write() on /dev/mem. */ int devmem_is_allowed (unsigned long pfn) {if (iomem_is_exclusive (pfn <<PAGE_SHIFT ))return 0 ; -if (!page_is_ram (pfn)) +if (!pfn_valid (pfn))return 1 ;return 0 ; }arch/arm64/mm/mmu.c +14
-1@@ -121,7 +121,7 @@ early_param("cachepolicy", early_cachepolicy);pgprot_t phys_mem_access_prot (struct file *file,unsigned long pfn,unsigned long size,pgprot_t vma_prot) { -if (!pfn_valid (pfn)) +if (!page_is_ram (pfn))return pgprot_noncached (vma_prot);else if (file->f_flags &O_SYNC )return pgprot_writecombine (vma_prot);@@ -129,6 +129,19 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, }EXPORT_SYMBOL (phys_mem_access_prot); +/* +* This definition of phys_mem_access_prot_allowed() overrides +* the __weak definition in drivers/char/mem.c +*/ +int phys_mem_access_prot_allowed (struct file *file,unsigned long pfn, +unsigned long size,pgprot_t *prot) +{ +/* Disallow read-write access to reserved system RAM */ +if ((pgprot_val (*prot) &PTE_WRITE ) &&page_is_ram (pfn)) +return 0 ; +return 1 ; +} +static void __init *early_alloc (unsigned long sz) {void *ptr =__va (memblock_alloc (sz, sz));Signature · 1 line
1.8.3.2
PATCH v3 3/13 arm64: improve CONFIG_STRICT_DEVMEM handling
Quoted 9 lines · Dave Young
Quoted 4 lines · Ard Biesheuvel
Improve the handling of
/dev/memmappings underCONFIG_STRICT_DEVMEMby:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;Ard, can you elabrate a bit? Are this for the acpi case because no dtb in procfs?
No, that is a different issue.
Quoted 3 lines
Anyway I also think using
/dev/memlooks not a good way to expose infomation to userspace.
This is for compatibility with existing tools like dmidecode and lshw that already use /dev/mem.
However, on x86, the tables they access are in iomem resource ranges that are accessible under CONFIG_STRICT_DEVMEM, whereas on arm64, those regions are inaccessible.
So while our position is that using /dev/mem for *anything* is an awful idea, this particular patch just tries to bring arm64 in line with what currently existing tools expect.
Signature · 1 line
Ard.
Quoted 67 lines
Quoted 67 lines
- avoid using non-cached mappings for those parts of System RAM, as it may result in mismatched attributes.
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/mm/mmap.c | 5 +++-- arch/arm64/mm/mmu.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-)arch/arm64/mm/mmap.c +3
-2@@ -127,14 +127,15 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)/* * devmem_is_allowed() checks to see if /dev/mem access to a certain address * is valid. The argument is a physical page number. We mimic x86 here by -* disallowing access to system RAM as well as device-exclusive MMIO regions. +* disallowing access to system RAM that is in active use by the kernel, as +* well as device-exclusive MMIO regions. * This effectively disable read()/write() on /dev/mem. */ int devmem_is_allowed (unsigned long pfn) {if (iomem_is_exclusive (pfn <<PAGE_SHIFT ))return 0 ; -if (!page_is_ram (pfn)) +if (!pfn_valid (pfn))return 1 ;return 0 ; }arch/arm64/mm/mmu.c +14
-2@@ -121,7 +121,7 @@ early_param("cachepolicy", early_cachepolicy);pgprot_t phys_mem_access_prot (struct file *file,unsigned long pfn,unsigned long size,pgprot_t vma_prot) { -if (!pfn_valid (pfn)) +if (!page_is_ram (pfn))return pgprot_noncached (vma_prot);else if (file->f_flags &O_SYNC )return pgprot_writecombine (vma_prot);@@ -129,6 +129,19 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, }EXPORT_SYMBOL (phys_mem_access_prot); +/* +* This definition of phys_mem_access_prot_allowed() overrides +* the __weak definition in drivers/char/mem.c +*/ +int phys_mem_access_prot_allowed (struct file *file,unsigned long pfn, +unsigned long size,pgprot_t *prot) +{ +/* Disallow read-write access to reserved system RAM */ +if ((pgprot_val (*prot) &PTE_WRITE ) &&page_is_ram (pfn)) +return 0 ; +return 1 ; +} +static void __init *early_alloc (unsigned long sz) {void *ptr =__va (memblock_alloc (sz, sz)); --1.8.3.2
PATCH v3 3/13 arm64: improve CONFIG_STRICT_DEVMEM handling
Quoted 23 lines · Ard Biesheuvel
Quoted 9 lines · Dave Young
Quoted 4 lines · Ard Biesheuvel
Improve the handling of
/dev/memmappings underCONFIG_STRICT_DEVMEMby:
- allowing read-only access to parts of System RAM that are not considered memory by the kernel, this is mainly intended for exposing UEFI Configuration tables to userland;Ard, can you elabrate a bit? Are this for the acpi case because no dtb in procfs?
No, that is a different issue.
Quoted 3 lines
Anyway I also think using
/dev/memlooks not a good way to expose infomation to userspace.This is for compatibility with existing tools like dmidecode and lshw that already use
/dev/mem.
However, on x86, the tables they access are in iomem resource ranges that are accessible underCONFIG_STRICT_DEVMEM, whereas on arm64, those regions are inaccessible.
Quoted 3 lines
So while our position is that using
/dev/memfor *anything* is an awful idea, this particular patch just tries to bring arm64 in line with what currently existing tools expect.
Ard, Ok, thanks for the clarification.
PATCH v3 4/13 efi: split off remapping code from efi_config_init()
In reply to Ard BiesheuvelSplit of the remapping code from efi_config_init() so that the caller can perform its own remapping. This is necessary to correctly handle virtually remapped UEFI memory regions under kexec, as efi.systab will have been updated to a virtual address.
--- drivers/firmware/efi/efi.c | 49 +++++++++++++++++++++++++++++----------------- include/linux/efi.h | 2 ++ 2 files changed, 33 insertions(+), 18 deletions(-)
drivers/firmware/efi/efi.c +31 -18
@@ -293,9 +293,10 @@ static __init int match_config_table(efi_guid_t *guid,return 0 ; } -int __init efi_config_init (efi_config_table_type_t *arch_tables) +int __init efi_config_parse_tables (void *config_tables,int count, +efi_config_table_type_t *arch_tables) { -void *config_tables, *tablep; +void *tablep;int i, sz;if (efi_enabled (EFI_64BIT ))
@@ -303,19 +304,9 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)else sz =sizeof (efi_config_table_32_t); -/* -* Let's see what config tables the firmware passed to us. -*/ - config_tables =early_memremap (efi.systab->tables, - efi.systab->nr_tables * sz); -if (config_tables ==NULL ) { -pr_err ("Could not map Configuration table!\n" ); -return -ENOMEM ; - } - tablep = config_tables;pr_info ("" ); -for (i =0 ; i < efi.systab->nr_tables; i++) { +for (i =0 ; i < count; i++) {efi_guid_t guid;unsigned long table;
@@ -328,8 +319,6 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)if (table64 >>32 ) {pr_cont ("\n" );pr_err ("Table located above 4GB, disabling EFI.\n" ); -early_memunmap (config_tables, - efi.systab->nr_tables * sz);return -EINVAL ; }#endif
@@ -344,13 +333,37 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) tablep += sz; }pr_cont ("\n" ); -early_memunmap (config_tables, efi.systab->nr_tables * sz); -set_bit (EFI_CONFIG_TABLES , &efi.flags); -return 0 ; } +int __init efi_config_init (efi_config_table_type_t *arch_tables) +{ +void *config_tables; +int sz, ret; + +if (efi_enabled (EFI_64BIT )) + sz =sizeof (efi_config_table_64_t); +else + sz =sizeof (efi_config_table_32_t); + +/* +* Let's see what config tables the firmware passed to us. +*/ + config_tables =early_memremap (efi.systab->tables, + efi.systab->nr_tables * sz); +if (config_tables ==NULL ) { +pr_err ("Could not map Configuration table!\n" ); +return -ENOMEM ; + } + + ret =efi_config_parse_tables (config_tables, efi.systab->nr_tables, + arch_tables); + +early_memunmap (config_tables, efi.systab->nr_tables * sz); +return ret; +} +#ifdef CONFIG_EFI_VARS_MODULE static int __init efi_load_efivars (void ) {
include/linux/efi.h +2 -0
@@ -875,6 +875,8 @@ static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned lon#endif extern void __iomem *efi_lookup_mapped_addr (u64 phys_addr);extern int efi_config_init (efi_config_table_type_t *arch_tables); +extern int efi_config_parse_tables (void *config_tables,int count, +efi_config_table_type_t *arch_tables);extern u64 efi_get_iobase (void );extern u32 efi_mem_type (unsigned long phys_addr);extern u64 efi_mem_attributes (unsigned long phys_addr);
Signature · 1 line
1.8.3.2
PATCH v3 4/13 efi: split off remapping code from efi_config_init()
Quoted 10 lines · Ard Biesheuvel
Split of the remapping code from
efi_config_init()so that the caller can perform its own remapping. This is necessary to correctly handle virtually remapped UEFI memory regions under kexec, as efi.systab will have been updated to a virtual address.Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/efi.c | 49 +++++++++++++++++++++++++++++----------------- include/linux/efi.h | 2 ++ 2 files changed, 33 insertions(+), 18 deletions(-)
Looks straight forward.
What tree are these going through?
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
PATCH v3 4/13 efi: split off remapping code from efi_config_init()
Quoted 12 lines · Matt Fleming
Quoted 10 lines · Ard Biesheuvel
Split of the remapping code from
efi_config_init()so that the caller can perform its own remapping. This is necessary to correctly handle virtually remapped UEFI memory regions under kexec, as efi.systab will have been updated to a virtual address.Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/efi.c | 49 +++++++++++++++++++++++++++++----------------- include/linux/efi.h | 2 ++ 2 files changed, 33 insertions(+), 18 deletions(-)
Quoted 3 lines
Looks straight forward.
What tree are these going through?
I think a bunch of the series is still under review, so we can probably decide on that nearer 3.20 based on any dependencies that crop up.
Will
PATCH v3 5/13 efi: add common infrastructure for stub-installed virtual mapping
In reply to Ard BiesheuvelThis introduces the common infrastructure to be shared between arm64 and ARM that wires up the UEFI memory map into system RAM discovery, virtual mappings for Runtime Services and aligning cache attributes between kernel and userland (/dev/mem) mappings for regions owned by UEFI.
--- drivers/firmware/efi/Kconfig | 3 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/virtmap.c | 134 +++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 12 +++- 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/virtmap.c
drivers/firmware/efi/Kconfig +3 -0
@@ -60,6 +60,9 @@ config EFI_RUNTIME_WRAPPERS config EFI_ARMSTUB bool +config EFI_VIRTMAP + bool + endmenu config UEFI_CPER
drivers/firmware/efi/Makefile +1 -0
@@ -8,3 +8,4 @@ obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_ARM_STUB) += libstub/ +obj-$(CONFIG_EFI_VIRTMAP) += virtmap.o
drivers/firmware/efi/virtmap.c new file +134 -0
134 lines not on this page · raw message
include/linux/efi.h +11 -1
@@ -941,7 +941,8 @@ extern int __init efi_setup_pcdp_console(char *);#define EFI_MEMMAP 4/* Can we use EFI memory map? */ #define EFI_64BIT 5/* Is the firmware 64-bit? */ #define EFI_PARAVIRT 6/* Access is via a paravirt interface */ -#define EFI_ARCH_1 7/* First arch-specific bit */ +#define EFI_VIRTMAP 7/* Use virtmap installed by the stub */ +#define EFI_ARCH_1 8/* First arch-specific bit */ #ifdef CONFIG_EFI /*
@@ -952,6 +953,7 @@ static inline bool efi_enabled(int feature) return test_bit(feature, &efi.flags) != 0; }extern void efi_reboot (enum reboot_mode reboot_mode,const char *__unused); +extern void efi_virtmap_init (void );#else static inline bool efi_enabled (int feature) {
@@ -959,6 +961,7 @@ static inline bool efi_enabled(int feature) }static inline void efi_reboot (enum reboot_mode reboot_mode,const char *__unused) {} +static inline void efi_virtmap_init (void ) {}#endif /*
@@ -1250,4 +1253,11 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,efi_status_t efi_parse_options (char *cmdline);bool efi_runtime_disabled (void ); + +phys_addr_t efi_to_phys (unsigned long addr); +bool efi_mem_is_usable_region (efi_memory_desc_t *md); + +void efi_virtmap_load (void ); +void efi_virtmap_unload (void ); +#endif /* _LINUX_EFI_H */
Signature · 1 line
1.8.3.2
PATCH v3 6/13 efi: register iomem resources for UEFI reserved regions
In reply to Ard BiesheuvelRegister memory regions reserved by UEFI as IORESOURCE_MEM resources, so that they are reserved for other uses, and also makes them turn up in /proc/iomem.
--- drivers/firmware/efi/virtmap.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
drivers/firmware/efi/virtmap.c +36 -0
@@ -13,6 +13,7 @@#include <linux/rwsem.h> #include <linux/spinlock.h> #include <linux/atomic.h> +#include <linux/bootmem.h> #include <asm/efi.h> #include <asm/pgtable.h>
@@ -52,6 +53,39 @@ static pgprot_t efi_md_access_prot(efi_memory_desc_t *md, pgprot_t prot)return pgprot_device (prot); } +static __init void efi_register_mem_resource (efi_memory_desc_t *md) +{ +struct resource *res, *parent; + + res =alloc_bootmem_low (sizeof (*res)); + res->start = md->phys_addr; + res->end = res->start + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ; + res->flags =IORESOURCE_MEM ; + +if (md->type ==EFI_MEMORY_MAPPED_IO && + (md->attribute &EFI_MEMORY_RUNTIME )) { +/* +* Device regions with the EFI_MEMORY_RUNTIME attribute +* are owned by the UEFI firmware, so make sure they are +* tagged as exclusive: this will also prevent access +* via /dev/mem if CONFIG_STRICT_DEVMEM is in effect. +*/ + res->name ="UEFI Runtime I/O" ; + res->flags |=IORESOURCE_EXCLUSIVE ; + }else { + res->name ="UEFI Reserved" ; + } + +/* +* Try to register this resource at the top level. If it conflicts with +* an existing entry ('System RAM', most likely), register it as its +* child instead. +*/ + parent =request_resource_conflict (&iomem_resource, res); +if (parent) +request_resource (parent, res); +} +void __init efi_virtmap_init (void ) {efi_memory_desc_t *md;
@@ -63,6 +97,8 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot; +if (!efi_mem_is_usable_region (md)) +efi_register_mem_resource (md);if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ; if (WARN(md->virt_addr == 0,
Signature · 1 line
1.8.3.2
PATCH v3 7/13 arm64/efi: move SetVirtualAddressMap() to UEFI stub
In reply to Ard BiesheuvelIn order to support kexec, the kernel needs to be able to deal with the state of the UEFI firmware after SetVirtualAddressMap() has been called. To avoid having separate code paths for non-kexec and kexec, let's move the call to SetVirtualAddressMap() to the stub: this will guarantee us that it will only be called once (since the stub is not executed during kexec), and ensures that the UEFI state is identical between kexec and normal boot.
This implies that the layout of the virtual mapping needs to be created by the stub as well. All regions are rounded up to a naturally aligned multiple of 64 KB (for compatibility with 64k pages kernels) and recorded in the UEFI memory map. The kernel proper reads those values and installs the mappings in a dedicated set of page tables that are swapped in during UEFI Runtime Services calls.
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/efi.h | 16 +++-- arch/arm64/kernel/efi.c | 128 ++++++++----------------------------- arch/arm64/kernel/setup.c | 1 + drivers/firmware/efi/libstub/fdt.c | 107 ++++++++++++++++++++++++++++++- 5 files changed, 144 insertions(+), 109 deletions(-)
arch/arm64/Kconfig +1 -0
@@ -393,6 +393,7 @@ config EFI select EFI_RUNTIME_WRAPPERS select EFI_STUB select EFI_ARMSTUB + select EFI_VIRTMAP default y help This option provides support for runtime services provided
arch/arm64/include/asm/efi.h +12 -4
@@ -14,21 +14,27 @@ extern void efi_idmap_init(void);#define efi_call_virt (f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab->runtime->f; \ + efi_##f##_t *__f; \ efi_status_t __s; \ \ - kernel_neon_begin(); \ + kernel_neon_begin();/* disables preemption */ \ +efi_virtmap_load (); \ + __f = efi.systab->runtime->f; \ __s =__f (__VA_ARGS__); \ +efi_virtmap_unload (); \kernel_neon_end (); \ __s; \ })#define __efi_call_virt (f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab->runtime->f; \ + efi_##f##_t *__f; \ \ - kernel_neon_begin(); \ + kernel_neon_begin();/* disables preemption */ \ +efi_virtmap_load (); \ + __f = efi.systab->runtime->f; \__f (__VA_ARGS__); \ +efi_virtmap_unload (); \kernel_neon_end (); \ })
@@ -44,4 +50,6 @@ extern void efi_idmap_init(void);#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +void efi_set_pgd (struct mm_struct *mm); +#endif /* _ASM_EFI_H */
arch/arm64/kernel/efi.c +25 -103
190 lines not on this page · raw message
arch/arm64/kernel/setup.c +1 -0
@@ -393,6 +393,7 @@ void __init setup_arch(char **cmdline_p)request_standard_resources ();efi_idmap_init (); +efi_virtmap_init ();unflatten_device_tree ();
drivers/firmware/efi/libstub/fdt.c +105 -2
129 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH v3 8/13 arm64/efi: remove free_boot_services() and friends
In reply to Ard BiesheuvelNow that we are calling SetVirtualAddressMap() from the stub, there is no need to reserve boot-only memory regions, which implies that there is also no reason to free them again later.
--- arch/arm64/kernel/efi.c | 123 +----------------------------------------------- 1 file changed, 1 insertion(+), 122 deletions(-)
arch/arm64/kernel/efi.c +1 -122
@@ -170,9 +170,7 @@ static __init void reserve_regions(void)if (is_normal_ram (md))early_init_dt_add_memory_arch (paddr, size); -if (is_reserve_region (md) || - md->type ==EFI_BOOT_SERVICES_CODE || - md->type ==EFI_BOOT_SERVICES_DATA ) { +if (is_reserve_region (md)) {memblock_reserve (paddr, size);if (uefi_debug)pr_cont ("*" );
@@ -185,123 +183,6 @@ static __init void reserve_regions(void)set_bit (EFI_MEMMAP , &efi.flags); } - -static u64 __init free_one_region (u64 start,u64 end) -{ -u64 size = end - start; - -if (uefi_debug) -pr_info (" EFI freeing: 0x%012llx-0x%012llx\n" , start, end -1 ); - -free_bootmem_late (start, size); -return size; -} - -static u64 __init free_region (u64 start,u64 end) -{ -u64 map_start, map_end, total =0 ; - -if (end <= start) -return total; - - map_start = (u64 )memmap.phys_map; - map_end =PAGE_ALIGN (map_start + (memmap.map_end - memmap.map)); - map_start &=PAGE_MASK ; - -if (start < map_end && end > map_start) { -/* region overlaps UEFI memmap */ -if (start < map_start) - total +=free_one_region (start, map_start); - -if (map_end < end) - total +=free_one_region (map_end, end); - }else - total +=free_one_region (start, end); - -return total; -} - -static void __init free_boot_services (void ) -{ -u64 total_freed =0 ; -u64 keep_end, free_start, free_end; -efi_memory_desc_t *md; - -/* -* If kernel uses larger pages than UEFI, we have to be careful -* not to inadvertantly free memory we want to keep if there is -* overlap@the kernel page size alignment. We do not want to -* free is_reserve_region() memory nor the UEFI memmap itself. -* -* The memory map is sorted, so we keep track of the end of -* any previous region we want to keep, remember any region -* we want to free and defer freeing it until we encounter -* the next region we want to keep. This way, before freeing -* it, we can clip it as needed to avoid freeing memory we -* want to keep for UEFI. -*/ - - keep_end =0 ; - free_start =0 ; - -for_each_efi_memory_desc (&memmap, md) { -u64 paddr, npages, size; - -if (is_reserve_region (md)) { -/* -* We don't want to free any memory from this region. -*/ -if (free_start) { -/* adjust free_end then free region */ -if (free_end > md->phys_addr) - free_end -=PAGE_SIZE ; - total_freed +=free_region (free_start, free_end); - free_start =0 ; - } - keep_end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ); -continue ; - } - -if (md->type !=EFI_BOOT_SERVICES_CODE && - md->type !=EFI_BOOT_SERVICES_DATA ) { -/* no need to free this region */ -continue ; - } - -/* -* We want to free memory from this region. -*/ - paddr = md->phys_addr; - npages = md->num_pages; -memrange_efi_to_native (&paddr, &npages); - size = npages <<PAGE_SHIFT ; - -if (free_start) { -if (paddr <= free_end) - free_end = paddr + size; -else { - total_freed +=free_region (free_start, free_end); - free_start = paddr; - free_end = paddr + size; - } - }else { - free_start = paddr; - free_end = paddr + size; - } -if (free_start < keep_end) { - free_start +=PAGE_SIZE ; -if (free_start >= free_end) - free_start =0 ; - } - } -if (free_start) - total_freed +=free_region (free_start, free_end); - -if (total_freed) -pr_info ("Freed 0x%llx bytes of EFI boot services memory" , - total_freed); -} -void __init efi_init (void ) {struct efi_fdt_params params;
@@ -368,8 +249,6 @@ static int __init arm64_enter_virtual_mode(void) }set_bit (EFI_SYSTEM_TABLES , &efi.flags); -free_boot_services (); -if (!efi_enabled (EFI_VIRTMAP )) {pr_err ("No UEFI virtual mapping was installed -- runtime services will not be available\n" );return -1 ;
Signature · 1 line
1.8.3.2
PATCH v3 9/13 arm64/efi: remove idmap manipulations from UEFI code
In reply to Ard BiesheuvelNow that we have moved the call to SetVirtualAddressMap() to the stub, UEFI has no use for the ID map, so we can drop the code that installs ID mappings for UEFI memory regions.
--- arch/arm64/include/asm/efi.h | 2 -- arch/arm64/include/asm/mmu.h | 2 -- arch/arm64/kernel/efi.c | 30 ------------------------------ arch/arm64/kernel/setup.c | 1 - arch/arm64/mm/mmu.c | 12 ------------ 5 files changed, 47 deletions(-)
arch/arm64/include/asm/efi.h +0 -2
@@ -6,10 +6,8 @@#ifdef CONFIG_EFI extern void efi_init (void ); -extern void efi_idmap_init (void );#else #define efi_init () -#define efi_idmap_init ()#endif #define efi_call_virt (f, ...) \
arch/arm64/include/asm/mmu.h +0 -2
@@ -31,8 +31,6 @@ extern void paging_init(void);extern void setup_mm_for_reboot (void );extern void __iomem *early_io_map (phys_addr_t phys,unsigned long virt);extern void init_mem_pgprot (void ); -/* create an identity mapping for memory (or io if map_io is true) */ -extern void create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io);extern void create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys,unsigned long virt,phys_addr_t size,pgprot_t prot);
arch/arm64/kernel/efi.c +0 -30
@@ -47,27 +47,6 @@ static int __init is_normal_ram(efi_memory_desc_t *md)return 0 ; } -static void __init efi_setup_idmap (void ) -{ -struct memblock_region *r; -efi_memory_desc_t *md; -u64 paddr, npages, size; - -for_each_memblock (memory, r) -create_id_mapping (r->base, r->size,0 ); - -/* map runtime io spaces */ -for_each_efi_memory_desc (&memmap, md) { -if (!(md->attribute &EFI_MEMORY_RUNTIME ) ||is_normal_ram (md)) -continue ; - paddr = md->phys_addr; - npages = md->num_pages; -memrange_efi_to_native (&paddr, &npages); - size = npages <<PAGE_SHIFT ; -create_id_mapping (paddr, size,1 ); - } -} -static int __init uefi_init (void ) {efi_char16_t *c16;
@@ -207,15 +186,6 @@ void __init efi_init(void)reserve_regions (); } -void __init efi_idmap_init (void ) -{ -if (!efi_enabled (EFI_BOOT )) -return ; - -/* boot time idmap_pg_dir is incomplete, so fill in missing parts */ -efi_setup_idmap (); -} -static int __init arm64_enter_virtual_mode (void ) {u64 mapsize;
arch/arm64/kernel/setup.c +0 -1
@@ -392,7 +392,6 @@ void __init setup_arch(char **cmdline_p)paging_init ();request_standard_resources (); -efi_idmap_init ();efi_virtmap_init ();unflatten_device_tree ();
arch/arm64/mm/mmu.c +0 -12
@@ -283,18 +283,6 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, size, PAGE_KERNEL_EXEC); } -void __init create_id_mapping (phys_addr_t addr,phys_addr_t size,int map_io) -{ -if ((addr >>PGDIR_SHIFT ) >=ARRAY_SIZE (idmap_pg_dir)) { -pr_warn ("BUG: not creating id mapping for %pa\n" , &addr); -return ; - } -__create_mapping (&init_mm, &idmap_pg_dir[pgd_index (addr)], - addr, addr, size, - map_io ?__pgprot (PROT_DEVICE_nGnRE) - :PAGE_KERNEL_EXEC ); -} -void __init create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys,unsigned long virt,phys_addr_t size,pgprot_t prot)
Signature · 1 line
1.8.3.2
PATCH v3 10/13 arm64/efi: use UEFI memory map unconditionally if available
In reply to Ard BiesheuvelOn systems that boot via UEFI, all memory nodes are deleted from the device tree, and instead, the size and location of system RAM is derived from the UEFI memory map. This is handled by reserve_regions, which not only reserves parts of memory that UEFI declares as reserved, but also installs the memblocks that cover the remaining usable memory.
Currently, reserve_regions() is only called if uefi_init() succeeds. However, it does not actually depend on anything that uefi_init() does, and not calling reserve_regions() results in a broken boot, so it is better to just call it unconditionally.
--- arch/arm64/kernel/efi.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
arch/arm64/kernel/efi.c +4 -7
@@ -180,8 +180,7 @@ void __init efi_init(void) memmap.desc_size = params.desc_size; memmap.desc_version = params.desc_ver; -if (uefi_init () <0 ) -return ; +WARN_ON (uefi_init () <0 );reserve_regions (); }
@@ -190,15 +189,13 @@ static int __init arm64_enter_virtual_mode(void) {u64 mapsize; -if (!efi_enabled (EFI_BOOT )) { -pr_info ("EFI services will not be available.\n" ); -return -1 ; - } +if (!efi_enabled (EFI_MEMMAP )) +return 0 ; mapsize = memmap.map_end - memmap.map;early_memunmap (memmap.map, mapsize); -if (efi_runtime_disabled ()) { +if (!efi_enabled (EFI_BOOT ) ||efi_runtime_disabled ()) {pr_info ("EFI runtime services will be disabled.\n" );return -1 ; }
Signature · 1 line
1.8.3.2
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
In reply to Ard BiesheuvelThe memblock API is agnostic of page size, so we can use it on both 4 KB and 64 KB granule kernels to install all UEFI memory regions (EFI_MEMORY_WB) using memblock_add(), and the memblock layer will stitch all unaligned regions together. Then we start punching holes in it for the reserved regions, this time taking the native page size into account.
Finally, the reserved regions are memblock_remove()'d as well. This will ensure that the regions are accessible via mmap(/dev/mem), even when CONFIG_STRICT_DEVMEM is in effect.
--- arch/arm64/kernel/efi.c | 41 +++++++++-------------------------------- drivers/firmware/efi/virtmap.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 38 deletions(-)
arch/arm64/kernel/efi.c +9 -32
@@ -105,24 +105,6 @@ out:return retval; } -/* -* Return true for RAM regions we want to permanently reserve. -*/ -static __init int is_reserve_region (efi_memory_desc_t *md) -{ -switch (md->type) { -case EFI_LOADER_CODE : -case EFI_LOADER_DATA : -case EFI_BOOT_SERVICES_CODE : -case EFI_BOOT_SERVICES_DATA : -case EFI_CONVENTIONAL_MEMORY : -return 0 ; -default : -break ; - } -return is_normal_ram (md); -} -static __init void reserve_regions (void ) {efi_memory_desc_t *md;
@@ -134,31 +116,26 @@ static __init void reserve_regions(void)for_each_efi_memory_desc (&memmap, md) { paddr = md->phys_addr; npages = md->num_pages; + size = npages <<EFI_PAGE_SHIFT ;if (uefi_debug) {char buf[64 ]; -pr_info (" 0x%012llx-0x%012llx %s" , - paddr, paddr + (npages <<EFI_PAGE_SHIFT ) -1 , +pr_info (" 0x%012llx-0x%012llx %s\n" , + paddr, paddr + size -1 ,efi_md_typeattr_format (buf,sizeof (buf), md)); } -memrange_efi_to_native (&paddr, &npages); - size = npages <<PAGE_SHIFT ; +if (is_normal_ram (md)) { +memblock_add (paddr, size); -if (is_normal_ram (md)) -early_init_dt_add_memory_arch (paddr, size); - -if (is_reserve_region (md)) { -memblock_reserve (paddr, size); -if (uefi_debug) -pr_cont ("*" ); +if (!efi_mem_is_usable_region (md)) { +memrange_efi_to_native (&paddr, &npages); +memblock_reserve (paddr, npages <<PAGE_SHIFT ); + } } -if (uefi_debug) -pr_cont ("\n" ); } -set_bit (EFI_MEMMAP , &efi.flags); }
drivers/firmware/efi/virtmap.c +9 -6
@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h>
@@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot; -if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ; if (WARN(md->virt_addr == 0,
@@ -106,11 +114,6 @@ void __init efi_virtmap_init(void) md->phys_addr))return ; - paddr = md->phys_addr; - npages = md->num_pages; -memrange_efi_to_native (&paddr, &npages); - size = npages <<PAGE_SHIFT ; -pr_info (" EFI remap 0x%012llx => %p\n" , md->phys_addr, (void *)md->virt_addr);
Signature · 1 line
1.8.3.2
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }
What exactly is the memblock_remove trying to accomplish? With it, I get:
Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = fffffe03d5890000 [00000008] *pgd=00000043d5ae0003, *pud=00000043d5ae0003, *pmd=00000043d5ae0003, *pte=0000000000000000 Internal error: Oops: 96000007 [#1] SMP Modules linked in: CPU: 0 PID: 107 Comm: modprobe Not tainted 3.18.0-rc5+ #8 Hardware name: APM X-Gene Mustang board (DT) task: fffffe03d5770000 ti: fffffe03dd300000 task.ti: fffffe03dd300000 PC is at mem_cgroup_begin_page_stat+0x40/0x110 LR is at mem_cgroup_begin_page_stat+0x40/0x110 pc : [<fffffe00001ec34c>] lr : [<fffffe00001ec34c>] pstate: 60000145 sp : fffffe03dd303a80 x29: fffffe03dd303a80 x28: 000000000000ffe0 x27: fffffdfef0f56bc0 x26: 0000000000000000 x25: 000003ff89b80000 x24: 0000000000000000 x23: fffffe03dd303ae8 x22: fffffe03dd303ae7 x21: 0000000000000000 x20: fffffe03d58a0420 x19: fffffdfef0004500 x18: 0000000000000000 x17: 000003ff89ba40dc x16: 000003ff89bbff90 x15: 000003ff89ba3b44 x14: 31313030343d6e66 x13: 7020303035343030 x12: 0000000000000006 x11: 0000000000000000 x10: 0000000000000186 x9 : 0000000000000187 x8 : 3030306665666466 x7 : fffffe0001041c18 x6 : 00000000000000ff x5 : fffffe00004aaf20 x4 : fffffe00004b209c x3 : 0000000000000000 x2 : 0000000000000000 x1 : fffffe0000f6a5d0 x0 : 0000000000000000
Process modprobe (pid: 107, stack limit = 0xfffffe03dd300058)
Stack: (0xfffffe03dd303a80 to 0xfffffe03dd304000) 3a80: dd303ac0 fffffe03 001c3e20 fffffe00 f0004500 fffffdfe d58a0420 fffffe03 3aa0: f0004500 fffffdfe d58f4dc0 fffffe03 00000000 00000000 001b62d4 fffffe00 3ac0: dd303af0 fffffe03 001b9984 fffffe00 01140f53 00200040 d58a0420 fffffe03 3ae0: d5880000 fffffe03 d58a0420 fffffe03 dd303b40 fffffe03 001b9c4c fffffe00 3b00: d58a0420 fffffe03 89b80000 000003ff f0f56bf0 fffffdfe 00000000 00000000 ... 3fa0: 89b907b7 000003ff 89bbf000 000003ff 89bc16e8 000003ff eb753490 000003ff 3fc0: 89b91f9c 000003ff eb753490 000003ff 89b91fac 000003ff 20000000 00000000 3fe0: 00000000 00000000 ffffffff ffffffff aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa Call trace: [<fffffe00001ec34c>] mem_cgroup_begin_page_stat+0x40/0x110 [<fffffe00001c3e1c>] page_add_file_rmap+0x24/0x80 [<fffffe00001b9980>] do_set_pte+0x108/0x19c [<fffffe00001b9c48>] do_read_fault.isra.93+0x234/0x28c [<fffffe00001ba57c>] handle_mm_fault+0x488/0xd64 [<fffffe00000a0ea0>] do_page_fault+0x224/0x358 [<fffffe0000090128>] do_mem_abort+0x4c/0xb0 Exception stack(0xfffffe03dd303e30 to 0xfffffe03dd303f50) 3e20: 00000000 00000000 89bbf000 000003ff 3e40: ffffffff ffffffff 89b91fac 000003ff 01043280 fffffe00 00000002 00000000 3e60: dd303e70 fffffe03 008ce3a0 fffffe00 dd303e90 fffffe03 001c0400 fffffe00 3e80: d5880000 fffffe03 000cbc60 fffffe00 eb753610 000003ff 00092fdc fffffe00 3ea0: 00000000 00000000 89bbf000 000003ff ffffffff ffffffff 89ba4654 000003ff 3ec0: 80000000 00000000 d5521480 fffffe03 89bc16e8 000003ff 89bc1a40 000003ff 3ee0: 00000004 00000000 89b80000 000003ff fefefeff fefefefe 00000000 00000000 3f00: 0000000f 00000000 89bc1028 000003ff 89ba7000 000003ff 0000079c 00000000 3f20: 00400000 00000000 ffff0000 ffffffff 004038a0 00000000 00010000 00000000 3f40: 89ba3c1c 000003ff 89ba3b44 000003ff Code: b9405835 35000275 aa1303e0 9400065c (f9400413)
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 18 lines · Mark Salter
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;
Quoted 14 lines
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }What exactly is the
memblock_removetrying to accomplish? With it, I get:
The idea was pfn_valid() will then return false for those pfns, allowing us to distinguish them from memory that the kernel may be using, primarily for /dev/mem filtering. But apparently it is causing problems for you, so I will have to figure out if there is a better way of addressing this.
Quoted 61 lines
Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = fffffe03d5890000 [00000008] *pgd=00000043d5ae0003, *pud=00000043d5ae0003, *pmd=00000043d5ae0003, *pte=0000000000000000 Internal error: Oops: 96000007 [#1] SMP Modules linked in: CPU: 0 PID: 107 Comm: modprobe Not tainted 3.18.0-rc5+ #8 Hardware name: APM X-Gene Mustang board (DT) task: fffffe03d5770000 ti: fffffe03dd300000 task.ti: fffffe03dd300000 PC is at mem_cgroup_begin_page_stat+0x40/0x110 LR is at mem_cgroup_begin_page_stat+0x40/0x110 pc : [<fffffe00001ec34c>] lr : [<fffffe00001ec34c>] pstate: 60000145 sp : fffffe03dd303a80 x29: fffffe03dd303a80 x28: 000000000000ffe0 x27: fffffdfef0f56bc0 x26: 0000000000000000 x25: 000003ff89b80000 x24: 0000000000000000 x23: fffffe03dd303ae8 x22: fffffe03dd303ae7 x21: 0000000000000000 x20: fffffe03d58a0420 x19: fffffdfef0004500 x18: 0000000000000000 x17: 000003ff89ba40dc x16: 000003ff89bbff90 x15: 000003ff89ba3b44 x14: 31313030343d6e66 x13: 7020303035343030 x12: 0000000000000006 x11: 0000000000000000 x10: 0000000000000186 x9 : 0000000000000187 x8 : 3030306665666466 x7 : fffffe0001041c18 x6 : 00000000000000ff x5 : fffffe00004aaf20 x4 : fffffe00004b209c x3 : 0000000000000000 x2 : 0000000000000000 x1 : fffffe0000f6a5d0 x0 : 0000000000000000Process modprobe (pid: 107, stack limit =
0xfffffe03dd300058)Stack: (0xfffffe03dd303a80 to 0xfffffe03dd304000) 3a80: dd303ac0 fffffe03 001c3e20 fffffe00 f0004500 fffffdfe d58a0420 fffffe03 3aa0: f0004500 fffffdfe d58f4dc0 fffffe03 00000000 00000000 001b62d4 fffffe00 3ac0: dd303af0 fffffe03 001b9984 fffffe00 01140f53 00200040 d58a0420 fffffe03 3ae0: d5880000 fffffe03 d58a0420 fffffe03 dd303b40 fffffe03 001b9c4c fffffe00 3b00: d58a0420 fffffe03 89b80000 000003ff f0f56bf0 fffffdfe 00000000 00000000 ... 3fa0: 89b907b7 000003ff 89bbf000 000003ff 89bc16e8 000003ff eb753490 000003ff 3fc0: 89b91f9c 000003ff eb753490 000003ff 89b91fac 000003ff 20000000 00000000 3fe0: 00000000 00000000 ffffffff ffffffff aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa Call trace: [<fffffe00001ec34c>] mem_cgroup_begin_page_stat+0x40/0x110 [<fffffe00001c3e1c>] page_add_file_rmap+0x24/0x80 [<fffffe00001b9980>] do_set_pte+0x108/0x19c [<fffffe00001b9c48>] do_read_fault.isra.93+0x234/0x28c [<fffffe00001ba57c>] handle_mm_fault+0x488/0xd64 [<fffffe00000a0ea0>] do_page_fault+0x224/0x358 [<fffffe0000090128>] do_mem_abort+0x4c/0xb0 Exception stack(0xfffffe03dd303e30 to 0xfffffe03dd303f50) 3e20: 00000000 00000000 89bbf000 000003ff 3e40: ffffffff ffffffff 89b91fac 000003ff 01043280 fffffe00 00000002 00000000 3e60: dd303e70 fffffe03 008ce3a0 fffffe00 dd303e90 fffffe03 001c0400 fffffe00 3e80: d5880000 fffffe03 000cbc60 fffffe00 eb753610 000003ff 00092fdc fffffe00 3ea0: 00000000 00000000 89bbf000 000003ff ffffffff ffffffff 89ba4654 000003ff 3ec0: 80000000 00000000 d5521480 fffffe03 89bc16e8 000003ff 89bc1a40 000003ff 3ee0: 00000004 00000000 89b80000 000003ff fefefeff fefefefe 00000000 00000000 3f00: 0000000f 00000000 89bc1028 000003ff 89ba7000 000003ff 0000079c 00000000 3f20: 00400000 00000000 ffff0000 ffffffff 004038a0 00000000 00010000 00000000 3f40: 89ba3c1c 000003ff 89ba3b44 000003ff Code: b9405835 35000275 aa1303e0 9400065c (f9400413)
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 34 lines · Ard Biesheuvel
Quoted 18 lines · Mark Salter
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;Quoted 14 lines
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }What exactly is the
memblock_removetrying to accomplish? With it, I get:
Quoted 6 lines
The idea was
pfn_valid()will then return false for those pfns, allowing us to distinguish them from memory that the kernel may be using, primarily for/dev/memfiltering. But apparently it is causing problems for you, so I will have to figure out if there is a better way of addressing this.
Okay. Well I think that works for pfn_valid, but it is confusing the mem_cgroup code. I think because you end up with multiple memory regions after creating the holes. Earlier memory management code saw one memory region. And because this comes after paging_init(), all of the memory ends up in the kernel linear mapping which is something we were trying to avoid.
Quoted 62 lines
Quoted 62 lines
Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = fffffe03d5890000 [00000008] *pgd=00000043d5ae0003, *pud=00000043d5ae0003, *pmd=00000043d5ae0003, *pte=0000000000000000 Internal error: Oops: 96000007 [#1] SMP Modules linked in: CPU: 0 PID: 107 Comm: modprobe Not tainted 3.18.0-rc5+ #8 Hardware name: APM X-Gene Mustang board (DT) task: fffffe03d5770000 ti: fffffe03dd300000 task.ti: fffffe03dd300000 PC is at mem_cgroup_begin_page_stat+0x40/0x110 LR is at mem_cgroup_begin_page_stat+0x40/0x110 pc : [<fffffe00001ec34c>] lr : [<fffffe00001ec34c>] pstate: 60000145 sp : fffffe03dd303a80 x29: fffffe03dd303a80 x28: 000000000000ffe0 x27: fffffdfef0f56bc0 x26: 0000000000000000 x25: 000003ff89b80000 x24: 0000000000000000 x23: fffffe03dd303ae8 x22: fffffe03dd303ae7 x21: 0000000000000000 x20: fffffe03d58a0420 x19: fffffdfef0004500 x18: 0000000000000000 x17: 000003ff89ba40dc x16: 000003ff89bbff90 x15: 000003ff89ba3b44 x14: 31313030343d6e66 x13: 7020303035343030 x12: 0000000000000006 x11: 0000000000000000 x10: 0000000000000186 x9 : 0000000000000187 x8 : 3030306665666466 x7 : fffffe0001041c18 x6 : 00000000000000ff x5 : fffffe00004aaf20 x4 : fffffe00004b209c x3 : 0000000000000000 x2 : 0000000000000000 x1 : fffffe0000f6a5d0 x0 : 0000000000000000Process modprobe (pid: 107, stack limit =
0xfffffe03dd300058)Stack: (0xfffffe03dd303a80 to 0xfffffe03dd304000) 3a80: dd303ac0 fffffe03 001c3e20 fffffe00 f0004500 fffffdfe d58a0420 fffffe03 3aa0: f0004500 fffffdfe d58f4dc0 fffffe03 00000000 00000000 001b62d4 fffffe00 3ac0: dd303af0 fffffe03 001b9984 fffffe00 01140f53 00200040 d58a0420 fffffe03 3ae0: d5880000 fffffe03 d58a0420 fffffe03 dd303b40 fffffe03 001b9c4c fffffe00 3b00: d58a0420 fffffe03 89b80000 000003ff f0f56bf0 fffffdfe 00000000 00000000 ... 3fa0: 89b907b7 000003ff 89bbf000 000003ff 89bc16e8 000003ff eb753490 000003ff 3fc0: 89b91f9c 000003ff eb753490 000003ff 89b91fac 000003ff 20000000 00000000 3fe0: 00000000 00000000 ffffffff ffffffff aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa Call trace: [<fffffe00001ec34c>] mem_cgroup_begin_page_stat+0x40/0x110 [<fffffe00001c3e1c>] page_add_file_rmap+0x24/0x80 [<fffffe00001b9980>] do_set_pte+0x108/0x19c [<fffffe00001b9c48>] do_read_fault.isra.93+0x234/0x28c [<fffffe00001ba57c>] handle_mm_fault+0x488/0xd64 [<fffffe00000a0ea0>] do_page_fault+0x224/0x358 [<fffffe0000090128>] do_mem_abort+0x4c/0xb0 Exception stack(0xfffffe03dd303e30 to 0xfffffe03dd303f50) 3e20: 00000000 00000000 89bbf000 000003ff 3e40: ffffffff ffffffff 89b91fac 000003ff 01043280 fffffe00 00000002 00000000 3e60: dd303e70 fffffe03 008ce3a0 fffffe00 dd303e90 fffffe03 001c0400 fffffe00 3e80: d5880000 fffffe03 000cbc60 fffffe00 eb753610 000003ff 00092fdc fffffe00 3ea0: 00000000 00000000 89bbf000 000003ff ffffffff ffffffff 89ba4654 000003ff 3ec0: 80000000 00000000 d5521480 fffffe03 89bc16e8 000003ff 89bc1a40 000003ff 3ee0: 00000004 00000000 89b80000 000003ff fefefeff fefefefe 00000000 00000000 3f00: 0000000f 00000000 89bc1028 000003ff 89ba7000 000003ff 0000079c 00000000 3f20: 00400000 00000000 ffff0000 ffffffff 004038a0 00000000 00010000 00000000 3f40: 89ba3c1c 000003ff 89ba3b44 000003ff Code: b9405835 35000275 aa1303e0 9400065c (f9400413)
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 41 lines · Mark Salter
Quoted 34 lines · Ard Biesheuvel
Quoted 18 lines · Mark Salter
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;Quoted 14 lines
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }What exactly is the
memblock_removetrying to accomplish? With it, I get:Quoted 6 lines
The idea was
pfn_valid()will then return false for those pfns, allowing us to distinguish them from memory that the kernel may be using, primarily for/dev/memfiltering. But apparently it is causing problems for you, so I will have to figure out if there is a better way of addressing this.
Quoted 7 lines
Okay. Well I think that works for
pfn_valid, but it is confusing themem_cgroupcode. I think because you end up with multiple memory regions after creating the holes. Earlier memory management code saw one memory region. And because this comes afterpaging_init(), all of the memory ends up in the kernel linear mapping which is something we were trying to avoid.
I will drop the memblock_remove() then. I guess I could make the test in devmem_is_allowed() do
if (!memblock_is_memory() || memblock_is_reserved())
instead of 'if (!pfn_valid())' so that reserved regions become accessible with having to remove them.
Are you happy with the other change in this patch, i.e., using memblock_add() directly so that we don't have to deal with the rounding?
Signature · 1 line
Ard.
Quoted 64 lines
Quoted 62 lines
Quoted 62 lines
Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = fffffe03d5890000 [00000008] *pgd=00000043d5ae0003, *pud=00000043d5ae0003, *pmd=00000043d5ae0003, *pte=0000000000000000 Internal error: Oops: 96000007 [#1] SMP Modules linked in: CPU: 0 PID: 107 Comm: modprobe Not tainted 3.18.0-rc5+ #8 Hardware name: APM X-Gene Mustang board (DT) task: fffffe03d5770000 ti: fffffe03dd300000 task.ti: fffffe03dd300000 PC is at mem_cgroup_begin_page_stat+0x40/0x110 LR is at mem_cgroup_begin_page_stat+0x40/0x110 pc : [<fffffe00001ec34c>] lr : [<fffffe00001ec34c>] pstate: 60000145 sp : fffffe03dd303a80 x29: fffffe03dd303a80 x28: 000000000000ffe0 x27: fffffdfef0f56bc0 x26: 0000000000000000 x25: 000003ff89b80000 x24: 0000000000000000 x23: fffffe03dd303ae8 x22: fffffe03dd303ae7 x21: 0000000000000000 x20: fffffe03d58a0420 x19: fffffdfef0004500 x18: 0000000000000000 x17: 000003ff89ba40dc x16: 000003ff89bbff90 x15: 000003ff89ba3b44 x14: 31313030343d6e66 x13: 7020303035343030 x12: 0000000000000006 x11: 0000000000000000 x10: 0000000000000186 x9 : 0000000000000187 x8 : 3030306665666466 x7 : fffffe0001041c18 x6 : 00000000000000ff x5 : fffffe00004aaf20 x4 : fffffe00004b209c x3 : 0000000000000000 x2 : 0000000000000000 x1 : fffffe0000f6a5d0 x0 : 0000000000000000Process modprobe (pid: 107, stack limit =
0xfffffe03dd300058)Stack: (0xfffffe03dd303a80 to 0xfffffe03dd304000) 3a80: dd303ac0 fffffe03 001c3e20 fffffe00 f0004500 fffffdfe d58a0420 fffffe03 3aa0: f0004500 fffffdfe d58f4dc0 fffffe03 00000000 00000000 001b62d4 fffffe00 3ac0: dd303af0 fffffe03 001b9984 fffffe00 01140f53 00200040 d58a0420 fffffe03 3ae0: d5880000 fffffe03 d58a0420 fffffe03 dd303b40 fffffe03 001b9c4c fffffe00 3b00: d58a0420 fffffe03 89b80000 000003ff f0f56bf0 fffffdfe 00000000 00000000 ... 3fa0: 89b907b7 000003ff 89bbf000 000003ff 89bc16e8 000003ff eb753490 000003ff 3fc0: 89b91f9c 000003ff eb753490 000003ff 89b91fac 000003ff 20000000 00000000 3fe0: 00000000 00000000 ffffffff ffffffff aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa Call trace: [<fffffe00001ec34c>] mem_cgroup_begin_page_stat+0x40/0x110 [<fffffe00001c3e1c>] page_add_file_rmap+0x24/0x80 [<fffffe00001b9980>] do_set_pte+0x108/0x19c [<fffffe00001b9c48>] do_read_fault.isra.93+0x234/0x28c [<fffffe00001ba57c>] handle_mm_fault+0x488/0xd64 [<fffffe00000a0ea0>] do_page_fault+0x224/0x358 [<fffffe0000090128>] do_mem_abort+0x4c/0xb0 Exception stack(0xfffffe03dd303e30 to 0xfffffe03dd303f50) 3e20: 00000000 00000000 89bbf000 000003ff 3e40: ffffffff ffffffff 89b91fac 000003ff 01043280 fffffe00 00000002 00000000 3e60: dd303e70 fffffe03 008ce3a0 fffffe00 dd303e90 fffffe03 001c0400 fffffe00 3e80: d5880000 fffffe03 000cbc60 fffffe00 eb753610 000003ff 00092fdc fffffe00 3ea0: 00000000 00000000 89bbf000 000003ff ffffffff ffffffff 89ba4654 000003ff 3ec0: 80000000 00000000 d5521480 fffffe03 89bc16e8 000003ff 89bc1a40 000003ff 3ee0: 00000004 00000000 89b80000 000003ff fefefeff fefefefe 00000000 00000000 3f00: 0000000f 00000000 89bc1028 000003ff 89ba7000 000003ff 0000079c 00000000 3f20: 00400000 00000000 ffff0000 ffffffff 004038a0 00000000 00010000 00000000 3f40: 89ba3c1c 000003ff 89ba3b44 000003ff Code: b9405835 35000275 aa1303e0 9400065c (f9400413)
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 50 lines · Ard Biesheuvel
Quoted 41 lines · Mark Salter
Quoted 34 lines · Ard Biesheuvel
Quoted 18 lines · Mark Salter
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;Quoted 14 lines
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }What exactly is the
memblock_removetrying to accomplish? With it, I get:Quoted 6 lines
The idea was
pfn_valid()will then return false for those pfns, allowing us to distinguish them from memory that the kernel may be using, primarily for/dev/memfiltering. But apparently it is causing problems for you, so I will have to figure out if there is a better way of addressing this.Quoted 7 lines
Okay. Well I think that works for
pfn_valid, but it is confusing themem_cgroupcode. I think because you end up with multiple memory regions after creating the holes. Earlier memory management code saw one memory region. And because this comes afterpaging_init(), all of the memory ends up in the kernel linear mapping which is something we were trying to avoid.
Quoted 7 lines
I will drop the
memblock_remove()then. I guess I could make the test indevmem_is_allowed()doif (!memblock_is_memory() ||
memblock_is_reserved())instead of 'if (!pfn_valid())' so that reserved regions become accessible with having to remove them.
Maybe we should add a new memblock to keep track of uefi tables. The memblock_is_reserved() seems overly permissive to me.
Quoted 5 lines
Are you happy with the other change in this patch, i.e., using
memblock_add()directly so that we don't have to deal with the rounding?
Yeah, I think that's okay. Everything else seems to be working fine in my testing.
PATCH v3 11/13 arm64/efi: use plain memblock API for adding and removing reserved RAM
Quoted 54 lines · Mark Salter
Quoted 53 lines · Ard Biesheuvel
Quoted 41 lines · Mark Salter
Quoted 34 lines · Ard Biesheuvel
Quoted 18 lines · Mark Salter
Quoted 17 lines · Ard Biesheuvel
drivers/firmware/efi/virtmap.c +1
-0@@ -8,6 +8,7 @@*/ #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/rbtree.h> #include <linux/rwsem.h> @@ -97,8 +98,15 @@ void __init efi_virtmap_init(void)u64 paddr, npages, size;pgprot_t prot;Quoted 14 lines
drivers/firmware/efi/virtmap.c void __init efi_virtmap_init(void) · line 109
Quoted 10 lines
drivers/firmware/efi/virtmap.c +8
-1-if (!efi_mem_is_usable_region (md)) + paddr = md->phys_addr; + npages = md->num_pages; +memrange_efi_to_native (&paddr, &npages); + size = npages <<PAGE_SHIFT ; + +if (!efi_mem_is_usable_region (md)) {efi_register_mem_resource (md); +memblock_remove (paddr, size); + }What exactly is the
memblock_removetrying to accomplish? With it, I get:Quoted 6 lines
The idea was
pfn_valid()will then return false for those pfns, allowing us to distinguish them from memory that the kernel may be using, primarily for/dev/memfiltering. But apparently it is causing problems for you, so I will have to figure out if there is a better way of addressing this.Quoted 7 lines
Okay. Well I think that works for
pfn_valid, but it is confusing themem_cgroupcode. I think because you end up with multiple memory regions after creating the holes. Earlier memory management code saw one memory region. And because this comes afterpaging_init(), all of the memory ends up in the kernel linear mapping which is something we were trying to avoid.I will drop the
memblock_remove()then. I guess I could make the test indevmem_is_allowed()do
Quoted 8 lines
Quoted 4 lines
if (!memblock_is_memory() ||
memblock_is_reserved())instead of 'if (!pfn_valid())' so that reserved regions become accessible with having to remove them.
Maybe we should add a new memblock to keep track of uefi tables. The
memblock_is_reserved()seems overly permissive to me.
OK. So instead, I will split reserve_regions() into 2 passes:
- first pass adds all EFI_MEMORY_WB regions (unrounded)
- second pass one removes all reserved regions (rounded up to OS page size)
That way, the devmem stuff should still work as well.
QEMU example:
Processing EFI memory map:
0x0000b711d000-0x0000b71dffff [Runtime Data |RUN| | | |
|WB|WT|WC|UC] 0x0000bfb21000-0x0000bfb34fff [Runtime Code |RUN| | | | |WB|WT|WC|UC] 0x0000bfb35000-0x0000bfb66fff [Runtime Data |RUN| | | | |WB|WT|WC|UC] 0x0000bfb6a000-0x0000bfb6afff [Runtime Data |RUN| | | | |WB|WT|WC|UC] 0x0000bfb82000-0x0000bfb82fff [Runtime Data |RUN| | | | |WB|WT|WC|UC] 0x000004000000-0x000007ffffff [Memory Mapped I/O |RUN| | | | | | | |UC] 0x000009010000-0x000009010fff [Memory Mapped I/O |RUN| | | | | | | |UC] 0x000040000000-0x0000407affff [Loader Data | | | | | |WB|WT|WC|UC] 0x0000b71e0000-0x0000bb77efff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x0000bb77f000-0x0000bbc00fff [Boot Data | | | | | |WB|WT|WC|UC] 0x0000bbc01000-0x0000bbdc2fff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x0000bbdc3000-0x0000bc01ffff [Boot Data | | | | | |WB|WT|WC|UC] 0x0000bc020000-0x0000bfa43fff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x0000bfa44000-0x0000bfb20fff [Boot Code | | | | | |WB|WT|WC|UC] 0x0000407b0000-0x00005fdfffff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x00005fe00000-0x00005fe0ffff [Loader Data | | | | | |WB|WT|WC|UC] 0x0000bfb67000-0x0000bfb69fff [Boot Data | | | | | |WB|WT|WC|UC] 0x00005fe10000-0x0000b6337fff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x0000bfb6b000-0x0000bfb7efff [Conventional Memory| | | | | |WB|WT|WC|UC] 0x0000bfb7f000-0x0000bfb81fff [Boot Data | | | | | |WB|WT|WC|UC] 0x0000b6338000-0x0000b6338fff [Loader Data | | | | | |WB|WT|WC|UC] 0x0000bfb83000-0x0000bfffffff [Boot Data | | | | | |WB|WT|WC|UC] 0x0000b6339000-0x0000b6a4bfff [Loader Code | | | | | |WB|WT|WC|UC] 0x0000b6a4c000-0x0000b711cfff [Boot Code | | | | | |WB|WT|WC|UC]
MEMBLOCK configuration:
memory size = 0x7fef5000 reserved size = 0x1724000
memory.cnt = 0x5
memory[0x0] [0x00000040000000-0x000000b711cfff], 0x7711d000 bytes flags: 0x0 memory[0x1] [0x000000b71e0000-0x000000bfb20fff], 0x8941000 bytes flags: 0x0 memory[0x2] [0x000000bfb67000-0x000000bfb69fff], 0x3000 bytes flags: 0x0 memory[0x3] [0x000000bfb6b000-0x000000bfb81fff], 0x17000 bytes flags: 0x0 memory[0x4] [0x000000bfb83000-0x000000bfffffff], 0x47d000 bytes flags: 0x0 reserved.cnt = 0x4
reserved[0x0] [0x00000040080000-0x00000040792fff], 0x713000 bytes flags: 0x0 reserved[0x1] [0x0000005fe00000-0x0000005fe0ffff], 0x10000 bytes flags: 0x0 reserved[0x2] [0x000000b6338000-0x000000b6338fff], 0x1000 bytes flags: 0x0 reserved[0x3] [0x000000be800000-0x000000bf7fffff], 0x1000000 bytes flags: 0x0
memblock_free: [0x00000040792000-0x00000040792fff]
__create_mapping.isra.6+0x9c/0x2ac
Quoted 9 lines
Quoted 5 lines
Are you happy with the other change in this patch, i.e., using
memblock_add()directly so that we don't have to deal with the rounding?Yeah, I think that's okay. Everything else seems to be working fine in my testing.
Cheers,
Ard.
PATCH v3 12/13 efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE
In reply to Ard BiesheuvelOn systems with 64 KB pages, it is preferable for UEFI memory map entries to be 64 KB aligned multiples of 64 KB, because it relieves us of having to deal with the residues.
So, if EFI_ALLOC_ALIGN is #define'd by the platform, use it to round up all memory allocations made.
--- drivers/firmware/efi/libstub/efi-stub-helper.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)
drivers/firmware/efi/libstub/efi-stub-helper.c +17 -8
@@ -32,6 +32,15 @@static unsigned long __chunk_size =EFI_READ_CHUNK_SIZE ; +/* +* Allow the platform to override the allocation granularity: this allows +* systems that have the capability to run with a larger page size to deal +* with the allocations for initrd and fdt more efficiently. +*/ +#ifndef EFI_ALLOC_ALIGN +#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE +#endif +struct file_info {efi_file_handle_t *handle;u64 size;
@@ -150,10 +159,10 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,* a specific address. We are doing page-based allocations, * so we must be aligned to a page. */ -if (align <EFI_PAGE_SIZE ) - align =EFI_PAGE_SIZE ; +if (align <EFI_ALLOC_ALIGN ) + align =EFI_ALLOC_ALIGN ; - nr_pages =round_up (size,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + nr_pages =round_up (size,EFI_ALLOC_ALIGN ) /EFI_PAGE_SIZE ; again:for (i =0 ; i < map_size / desc_size; i++) {efi_memory_desc_t *desc;
@@ -235,10 +244,10 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,* a specific address. We are doing page-based allocations, * so we must be aligned to a page. */ -if (align <EFI_PAGE_SIZE ) - align =EFI_PAGE_SIZE ; +if (align <EFI_ALLOC_ALIGN ) + align =EFI_ALLOC_ALIGN ; - nr_pages =round_up (size,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + nr_pages =round_up (size,EFI_ALLOC_ALIGN ) /EFI_PAGE_SIZE ;for (i =0 ; i < map_size / desc_size; i++) {efi_memory_desc_t *desc;unsigned long m = (unsigned long )map;
@@ -292,7 +301,7 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,if (!size)return ; - nr_pages =round_up (size,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + nr_pages =round_up (size,EFI_ALLOC_ALIGN ) /EFI_PAGE_SIZE ;efi_call_early (free_pages, addr, nr_pages); }
@@ -561,7 +570,7 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,* to the preferred address. If that fails, allocate as low * as possible while respecting the required alignment. */ - nr_pages =round_up (alloc_size,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + nr_pages =round_up (alloc_size,EFI_ALLOC_ALIGN ) /EFI_PAGE_SIZE ; status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS ,EFI_LOADER_DATA , nr_pages, &efi_addr);
Signature · 1 line
1.8.3.2
PATCH v3 12/13 efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE
Quoted 10 lines · Ard Biesheuvel
On systems with 64 KB pages, it is preferable for UEFI memory map entries to be 64 KB aligned multiples of 64 KB, because it relieves us of having to deal with the residues.
So, ifEFI_ALLOC_ALIGNis #define'd by the platform, use it to round up all memory allocations made.Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/libstub/efi-stub-helper.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)
Looks OK to me.
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
PATCH v3 13/13 arm64/efi: set EFI_ALLOC_ALIGN to 64 KB
In reply to Ard BiesheuvelSet EFI_ALLOC_ALIGN to 64 KB so that all allocations done by the stub are naturally compatible with a 64 KB granule kernel.
--- arch/arm64/include/asm/efi.h | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/include/asm/efi.h +2 -0
@@ -48,6 +48,8 @@ extern void efi_init(void);#define efi_call_early (f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define EFI_ALLOC_ALIGN SZ_64K +void efi_set_pgd (struct mm_struct *mm);#endif /* _ASM_EFI_H */
Signature · 1 line
1.8.3.2
v3 cover arm64: stable UEFI mappings for kexec
In reply to Ard BiesheuvelHi Ard,
Quoted 2 lines · Ard Biesheuvel
This is v3 of the series to update the UEFI memory map handling for the arm64 architecture so that:
Just to let you know, I merged these into my kexec master branch [1] and could do a kexec re-boot on a non-EFI system (VE fast model). I'll try with EFI enabled firmware next.
[1] https://git.linaro.org/people/geoff.levand/linux-kexec.git
-Geoff
v3 cover arm64: stable UEFI mappings for kexec
In reply to Ard BiesheuvelHi Ard,
Quoted 2 lines · Ard Biesheuvel
This is v3 of the series to update the UEFI memory map handling for the arm64 architecture so that:
I merged in your EFI patches into my master branch [1] and was able to do a successful chain of (four) kexec re-boots of the same kernel image on the ARM base model running LEG 14.10 EFI binaries [2]. EFI showed:
UEFI v2.40 (ARM Fixed Virtual Platform EFI Oct 23 2014 15:53:09, 0x00000000)
I only verified that all CPU's came up and that /proc/meminfo and the /proc/iomem 'System RAM' entries looked ok.
[1] https://git.linaro.org/people/geoff.levand/linux-kexec.git
[2] https://releases.linaro.org/14.10/components/kernel/uefi-linaro/release/fvp_minimal
-Geoff
v3 cover arm64: stable UEFI mappings for kexec
Quoted 11 lines · Geoff Levand
Hi Ard,
Quoted 2 lines · Ard Biesheuvel
This is v3 of the series to update the UEFI memory map handling for the arm64 architecture so that:
I merged in your EFI patches into my master branch [1] and was able to do a successful chain of (four) kexec re-boots of the same kernel image on the ARM base model running LEG 14.10 EFI binaries [2]. EFI showed:
Quoted 8 lines
UEFI v2.40 (ARM Fixed Virtual Platform EFI Oct 23 2014 15:53:09,
0x00000000)I only verified that all CPU's came up and that
/proc/meminfoand the/proc/iomem'System RAM' entries looked ok.[1] https://git.linaro.org/people/geoff.levand/linux-kexec.git
[2] https://releases.linaro.org/14.10/components/kernel/uefi-linaro/release/fvp_minimal
Good stuff! Thanks for testing this.
Let's align so that we can get this merged in the same cycle.
Thanks,
Ard.