* [PATCH v3 00/13] arm64: stable UEFI mappings for kexec
@ 2014-11-18 12:56 Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 01/13] arm64/mm: add explicit struct_mm argument to __create_mapping() Ard Biesheuvel
` (14 more replies)
0 siblings, 15 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:56 UTC (permalink / raw)
To: linux-arm-kernel
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
--
1.8.3.2
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 01/13] arm64/mm: add explicit struct_mm argument to __create_mapping()
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables Ard Biesheuvel
` (13 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
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.
Acked-by: Steve Capper <steve.capper@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/mm/mmu.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0bf90d26e745..83e6713143a3 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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);
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 01/13] arm64/mm: add explicit struct_mm argument to __create_mapping() Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-25 14:32 ` Will Deacon
2014-11-18 12:57 ` [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling Ard Biesheuvel
` (12 subsequent siblings)
14 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
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 <ard.biesheuvel@linaro.org>
---
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(-)
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index c2f006c48bdb..5fd40c43be80 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -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
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 41a43bf26492..1abe4d08725b 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -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.
*/
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 83e6713143a3..4d583aa9ff4e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 01/13] arm64/mm: add explicit struct_mm argument to __create_mapping() Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-25 17:39 ` Matt Fleming
2014-11-26 9:30 ` Dave Young
2014-11-18 12:57 ` [PATCH v3 04/13] efi: split off remapping code from efi_config_init() Ard Biesheuvel
` (11 subsequent siblings)
14 siblings, 2 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
Improve 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/mm/mmap.c | 5 +++--
arch/arm64/mm/mmu.c | 15 ++++++++++++++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 1d73662f00ff..802cdf0df921 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -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;
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 4d583aa9ff4e..93ba10838359 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 04/13] efi: split off remapping code from efi_config_init()
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (2 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-25 17:24 ` Matt Fleming
2014-11-18 12:57 ` [PATCH v3 05/13] efi: add common infrastructure for stub-installed virtual mapping Ard Biesheuvel
` (10 subsequent siblings)
14 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
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 <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/efi.c | 49 +++++++++++++++++++++++++++++-----------------
include/linux/efi.h | 2 ++
2 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 9035c1b74d58..0de77db4fb88 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -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)
{
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 0238d612750e..2dc8577032b3 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -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);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 05/13] efi: add common infrastructure for stub-installed virtual mapping
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (3 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 04/13] efi: split off remapping code from efi_config_init() Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 06/13] efi: register iomem resources for UEFI reserved regions Ard Biesheuvel
` (9 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
This 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index f712d47f30d8..c71498180e67 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -60,6 +60,9 @@ config EFI_RUNTIME_WRAPPERS
config EFI_ARMSTUB
bool
+config EFI_VIRTMAP
+ bool
+
endmenu
config UEFI_CPER
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index aef6a95adef5..3fd26c0ad40b 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -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
diff --git a/drivers/firmware/efi/virtmap.c b/drivers/firmware/efi/virtmap.c
new file mode 100644
index 000000000000..d1f1d416944f
--- /dev/null
+++ b/drivers/firmware/efi/virtmap.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/efi.h>
+#include <linux/mm_types.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+
+#include <asm/efi.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/mmu.h>
+
+static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
+
+static struct mm_struct efi_mm = {
+ .mm_rb = RB_ROOT,
+ .pgd = efi_pgd,
+ .mm_users = ATOMIC_INIT(2),
+ .mm_count = ATOMIC_INIT(1),
+ .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
+ .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
+ .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
+ INIT_MM_CONTEXT(efi_mm)
+};
+
+void efi_virtmap_load(void)
+{
+ WARN_ON(preemptible());
+ efi_set_pgd(&efi_mm);
+}
+
+void efi_virtmap_unload(void)
+{
+ efi_set_pgd(current->active_mm);
+}
+
+static pgprot_t efi_md_access_prot(efi_memory_desc_t *md, pgprot_t prot)
+{
+ if (md->attribute & EFI_MEMORY_WB)
+ return prot;
+ if (md->attribute & (EFI_MEMORY_WT|EFI_MEMORY_WC))
+ return pgprot_writecombine(prot);
+ return pgprot_device(prot);
+}
+
+void __init efi_virtmap_init(void)
+{
+ efi_memory_desc_t *md;
+
+ if (!efi_enabled(EFI_BOOT))
+ return;
+
+ for_each_efi_memory_desc(&memmap, md) {
+ u64 paddr, npages, size;
+ pgprot_t prot;
+
+ if (!(md->attribute & EFI_MEMORY_RUNTIME))
+ continue;
+ if (WARN(md->virt_addr == 0,
+ "UEFI virtual mapping incomplete or missing -- no entry found for 0x%llx\n",
+ 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);
+
+ /*
+ * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+ * executable, everything else can be mapped with the XN bits
+ * set.
+ */
+ if (md->type == EFI_RUNTIME_SERVICES_CODE)
+ prot = efi_md_access_prot(md, PAGE_KERNEL_EXEC);
+ else
+ prot = efi_md_access_prot(md, PAGE_KERNEL);
+
+ create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+ }
+ set_bit(EFI_VIRTMAP, &efi.flags);
+}
+
+/*
+ * Return true for RAM regions that are available for general use.
+ */
+bool efi_mem_is_usable_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 md->attribute & EFI_MEMORY_WB;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*
+ * Translate a EFI virtual address into a physical address: this is necessary,
+ * as some data members of the EFI system table are virtually remapped after
+ * SetVirtualAddressMap() has been called.
+ */
+phys_addr_t efi_to_phys(unsigned long addr)
+{
+ efi_memory_desc_t *md;
+
+ for_each_efi_memory_desc(&memmap, md) {
+ if (!(md->attribute & EFI_MEMORY_RUNTIME))
+ continue;
+ if (md->virt_addr == 0)
+ /* no virtual mapping has been installed by the stub */
+ break;
+ if (md->virt_addr <= addr &&
+ (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT))
+ return md->phys_addr + addr - md->virt_addr;
+ }
+ return addr;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2dc8577032b3..2adef3e9bf35 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -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 */
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 06/13] efi: register iomem resources for UEFI reserved regions
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (4 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 05/13] efi: add common infrastructure for stub-installed virtual mapping Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 07/13] arm64/efi: move SetVirtualAddressMap() to UEFI stub Ard Biesheuvel
` (8 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
Register 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/virtmap.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/firmware/efi/virtmap.c b/drivers/firmware/efi/virtmap.c
index d1f1d416944f..98735fb43581 100644
--- a/drivers/firmware/efi/virtmap.c
+++ b/drivers/firmware/efi/virtmap.c
@@ -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,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 07/13] arm64/efi: move SetVirtualAddressMap() to UEFI stub
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (5 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 06/13] efi: register iomem resources for UEFI reserved regions Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 08/13] arm64/efi: remove free_boot_services() and friends Ard Biesheuvel
` (7 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
In 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2c3c2ca6f8bc..a6d00b7cf60b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index a34fd3b12e2b..e2cea16f3bd7 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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 */
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 6fac253bc783..beb5a79d32c3 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -25,11 +25,10 @@
#include <asm/efi.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
+#include <asm/mmu.h>
struct efi_memory_map memmap;
-static efi_runtime_services_t *runtime;
-
static u64 efi_system_table;
static int uefi_debug __initdata;
@@ -72,6 +71,8 @@ static void __init efi_setup_idmap(void)
static int __init uefi_init(void)
{
efi_char16_t *c16;
+ void *config_tables;
+ u64 table_size;
char vendor[100] = "unknown";
int i, retval;
@@ -99,7 +100,7 @@ static int __init uefi_init(void)
efi.systab->hdr.revision & 0xffff);
/* Show what we know for posterity */
- c16 = early_memremap(efi.systab->fw_vendor,
+ c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
sizeof(vendor));
if (c16) {
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
@@ -112,8 +113,14 @@ static int __init uefi_init(void)
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor);
- retval = efi_config_init(NULL);
+ table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
+ config_tables = early_memremap(efi_to_phys(efi.systab->tables),
+ table_size);
+
+ retval = efi_config_parse_tables(config_tables,
+ efi.systab->nr_tables, NULL);
+ early_memunmap(config_tables, table_size);
out:
early_memunmap(efi.systab, sizeof(efi_system_table_t));
return retval;
@@ -328,51 +335,9 @@ void __init efi_idmap_init(void)
efi_setup_idmap();
}
-static int __init remap_region(efi_memory_desc_t *md, void **new)
-{
- u64 paddr, vaddr, npages, size;
-
- paddr = md->phys_addr;
- npages = md->num_pages;
- memrange_efi_to_native(&paddr, &npages);
- size = npages << PAGE_SHIFT;
-
- if (is_normal_ram(md))
- vaddr = (__force u64)ioremap_cache(paddr, size);
- else
- vaddr = (__force u64)ioremap(paddr, size);
-
- if (!vaddr) {
- pr_err("Unable to remap 0x%llx pages @ %p\n",
- npages, (void *)paddr);
- return 0;
- }
-
- /* adjust for any rounding when EFI and system pagesize differs */
- md->virt_addr = vaddr + (md->phys_addr - paddr);
-
- if (uefi_debug)
- pr_info(" EFI remap 0x%012llx => %p\n",
- md->phys_addr, (void *)md->virt_addr);
-
- memcpy(*new, md, memmap.desc_size);
- *new += memmap.desc_size;
-
- return 1;
-}
-
-/*
- * Switch UEFI from an identity map to a kernel virtual map
- */
static int __init arm64_enter_virtual_mode(void)
{
- efi_memory_desc_t *md;
- phys_addr_t virtmap_phys;
- void *virtmap, *virt_md;
- efi_status_t status;
u64 mapsize;
- int count = 0;
- unsigned long flags;
if (!efi_enabled(EFI_BOOT)) {
pr_info("EFI services will not be available.\n");
@@ -395,79 +360,28 @@ static int __init arm64_enter_virtual_mode(void)
efi.memmap = &memmap;
- /* Map the runtime regions */
- virtmap = kmalloc(mapsize, GFP_KERNEL);
- if (!virtmap) {
- pr_err("Failed to allocate EFI virtual memmap\n");
- return -1;
- }
- virtmap_phys = virt_to_phys(virtmap);
- virt_md = virtmap;
-
- for_each_efi_memory_desc(&memmap, md) {
- if (!(md->attribute & EFI_MEMORY_RUNTIME))
- continue;
- if (!remap_region(md, &virt_md))
- goto err_unmap;
- ++count;
- }
-
- efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
+ efi.systab = (__force void *)ioremap_cache(efi_system_table,
+ sizeof(efi_system_table_t));
if (!efi.systab) {
- /*
- * If we have no virtual mapping for the System Table at this
- * point, the memory map doesn't cover the physical offset where
- * it resides. This means the System Table will be inaccessible
- * to Runtime Services themselves once the virtual mapping is
- * installed.
- */
- pr_err("Failed to remap EFI System Table -- buggy firmware?\n");
- goto err_unmap;
+ pr_err("Failed to remap EFI System Table\n");
+ return -1;
}
set_bit(EFI_SYSTEM_TABLES, &efi.flags);
- local_irq_save(flags);
- cpu_switch_mm(idmap_pg_dir, &init_mm);
-
- /* Call SetVirtualAddressMap with the physical address of the map */
- runtime = efi.systab->runtime;
- efi.set_virtual_address_map = runtime->set_virtual_address_map;
-
- status = efi.set_virtual_address_map(count * memmap.desc_size,
- memmap.desc_size,
- memmap.desc_version,
- (efi_memory_desc_t *)virtmap_phys);
- cpu_set_reserved_ttbr0();
- flush_tlb_all();
- local_irq_restore(flags);
-
- kfree(virtmap);
-
free_boot_services();
- if (status != EFI_SUCCESS) {
- pr_err("Failed to set EFI virtual address map! [%lx]\n",
- status);
+ if (!efi_enabled(EFI_VIRTMAP)) {
+ pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
return -1;
}
/* Set up runtime services function pointers */
- runtime = efi.systab->runtime;
efi_native_runtime_setup();
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi.runtime_version = efi.systab->hdr.revision;
return 0;
-
-err_unmap:
- /* unmap all mappings that succeeded: there are 'count' of those */
- for (virt_md = virtmap; count--; virt_md += memmap.desc_size) {
- md = virt_md;
- iounmap((__force void __iomem *)md->virt_addr);
- }
- kfree(virtmap);
- return -1;
}
early_initcall(arm64_enter_virtual_mode);
@@ -484,3 +398,11 @@ static int __init arm64_dmi_init(void)
return 0;
}
core_initcall(arm64_dmi_init);
+
+void efi_set_pgd(struct mm_struct *mm)
+{
+ cpu_switch_mm(mm->pgd, mm);
+ flush_tlb_all();
+ if (icache_is_aivivt())
+ __flush_icache_all();
+}
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 2437196cc5d4..ac19b2d6a3fc 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -393,6 +393,7 @@ void __init setup_arch(char **cmdline_p)
request_standard_resources();
efi_idmap_init();
+ efi_virtmap_init();
unflatten_device_tree();
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index c846a9608cbd..7129ed55e4bb 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -168,6 +168,68 @@ fdt_set_fail:
#endif
/*
+ * This is the base address at which to start allocating virtual memory ranges
+ * for UEFI Runtime Services. This is a userland range so that we can use any
+ * allocation we choose, and eliminate the risk of a conflict after kexec.
+ */
+#define EFI_RT_VIRTUAL_BASE 0x40000000
+
+static void update_memory_map(efi_memory_desc_t *memory_map,
+ unsigned long map_size, unsigned long desc_size,
+ int *count)
+{
+ u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
+ union {
+ efi_memory_desc_t entry;
+ u8 pad[desc_size];
+ } *p, *q, tmp;
+ int i = map_size / desc_size;
+
+ p = (void *)memory_map;
+ for (q = p; i >= 0; i--, q++) {
+ u64 paddr, size;
+
+ if (!(q->entry.attribute & EFI_MEMORY_RUNTIME))
+ continue;
+
+ /*
+ * Swap the entries around so that all EFI_MEMORY_RUNTIME
+ * entries bubble to the top. This will allow us to reuse the
+ * table as input to SetVirtualAddressMap().
+ */
+ if (q != p) {
+ tmp = *p;
+ *p = *q;
+ *q = tmp;
+ }
+
+ /*
+ * Make the mapping compatible with 64k pages: this allows
+ * a 4k page size kernel to kexec a 64k page size kernel and
+ * vice versa.
+ */
+ paddr = round_down(p->entry.phys_addr, SZ_64K);
+ size = round_up(p->entry.num_pages * EFI_PAGE_SIZE +
+ p->entry.phys_addr - paddr, SZ_64K);
+
+ /*
+ * Avoid wasting memory on PTEs by choosing a virtual base that
+ * is compatible with section mappings if this region has the
+ * appropriate size and physical alignment. (Sections are 2 MB
+ * on 4k granule kernels)
+ */
+ if (IS_ALIGNED(p->entry.phys_addr, SZ_2M) && size >= SZ_2M)
+ efi_virt_base = round_up(efi_virt_base, SZ_2M);
+
+ p->entry.virt_addr = efi_virt_base + p->entry.phys_addr - paddr;
+ efi_virt_base += size;
+
+ ++p;
+ ++*count;
+ }
+}
+
+/*
* Allocate memory for a new FDT, then add EFI, commandline, and
* initrd related fields to the FDT. This routine increases the
* FDT allocation size until the allocated memory is large
@@ -196,6 +258,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
efi_memory_desc_t *memory_map;
unsigned long new_fdt_size;
efi_status_t status;
+ int runtime_entry_count = 0;
/*
* Estimate size of new FDT, and allocate memory for it. We
@@ -248,12 +311,52 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
}
}
+ /*
+ * Update the memory map with virtual addresses, and reorder the entries
+ * so that we can pass it straight into SetVirtualAddressMap()
+ */
+ update_memory_map(memory_map, map_size, desc_size,
+ &runtime_entry_count);
+
+ pr_efi(sys_table,
+ "Exiting boot services and installing virtual address map...\n");
+
/* Now we are ready to exit_boot_services.*/
status = sys_table->boottime->exit_boot_services(handle, mmap_key);
+ if (status == EFI_SUCCESS) {
+ efi_set_virtual_address_map_t *svam;
+
+ /* Install the new virtual address map */
+ svam = sys_table->runtime->set_virtual_address_map;
+ status = svam(runtime_entry_count * desc_size, desc_size,
+ desc_ver, memory_map);
- if (status == EFI_SUCCESS)
- return status;
+ /*
+ * We are beyond the point of no return here, so if the call to
+ * SetVirtualAddressMap() failed, we need to signal that to the
+ * incoming kernel but proceed normally otherwise.
+ */
+ if (status != EFI_SUCCESS) {
+ int i;
+
+ /*
+ * Set the virtual address field of all
+ * EFI_MEMORY_RUNTIME entries to 0. This will signal
+ * the incoming kernel that no virtual translation has
+ * been installed.
+ */
+ for (i = 0; i < map_size; i += desc_size) {
+ efi_memory_desc_t *p;
+
+ p = (efi_memory_desc_t *)((u8 *)memory_map + i);
+ if (!(p->attribute & EFI_MEMORY_RUNTIME))
+ break;
+ p->virt_addr = 0;
+ }
+ }
+ return EFI_SUCCESS;
+ }
pr_efi_err(sys_table, "Exit boot services failed.\n");
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 08/13] arm64/efi: remove free_boot_services() and friends
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (6 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 07/13] arm64/efi: move SetVirtualAddressMap() to UEFI stub Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 09/13] arm64/efi: remove idmap manipulations from UEFI code Ard Biesheuvel
` (6 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
Now 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/kernel/efi.c | 123 +-----------------------------------------------
1 file changed, 1 insertion(+), 122 deletions(-)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index beb5a79d32c3..9f05b4fe9fd5 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 09/13] arm64/efi: remove idmap manipulations from UEFI code
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (7 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 08/13] arm64/efi: remove free_boot_services() and friends Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 10/13] arm64/efi: use UEFI memory map unconditionally if available Ard Biesheuvel
` (5 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
Now 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
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(-)
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e2cea16f3bd7..5420ad5a4c63 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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, ...) \
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 5fd40c43be80..3d311761e3c2 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -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);
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 9f05b4fe9fd5..a48a2f9ab669 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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;
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index ac19b2d6a3fc..a6028490a28f 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -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();
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 93ba10838359..d2a1625f1055 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 10/13] arm64/efi: use UEFI memory map unconditionally if available
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (8 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 09/13] arm64/efi: remove idmap manipulations from UEFI code Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM Ard Biesheuvel
` (4 subsequent siblings)
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
On 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/kernel/efi.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index a48a2f9ab669..3009c22e2620 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (9 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 10/13] arm64/efi: use UEFI memory map unconditionally if available Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-20 17:28 ` Mark Salter
2014-11-18 12:57 ` [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE Ard Biesheuvel
` (3 subsequent siblings)
14 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
The 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.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/kernel/efi.c | 41 +++++++++--------------------------------
drivers/firmware/efi/virtmap.c | 15 +++++++++------
2 files changed, 18 insertions(+), 38 deletions(-)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 3009c22e2620..2c0a858f699e 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -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);
}
diff --git a/drivers/firmware/efi/virtmap.c b/drivers/firmware/efi/virtmap.c
index 98735fb43581..4b6a5c31629f 100644
--- a/drivers/firmware/efi/virtmap.c
+++ b/drivers/firmware/efi/virtmap.c
@@ -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);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (10 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-27 17:30 ` Matt Fleming
2014-11-18 12:57 ` [PATCH v3 13/13] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB Ard Biesheuvel
` (2 subsequent siblings)
14 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
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, if EFI_ALLOC_ALIGN is #define'd by the platform, use it to round
up all memory allocations made.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/firmware/efi/libstub/efi-stub-helper.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index a920fec8fe88..e766df60fbfb 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -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);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 13/13] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (11 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE Ard Biesheuvel
@ 2014-11-18 12:57 ` Ard Biesheuvel
2014-11-20 1:27 ` [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Geoff Levand
2014-11-20 22:05 ` Geoff Levand
14 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-18 12:57 UTC (permalink / raw)
To: linux-arm-kernel
Set EFI_ALLOC_ALIGN to 64 KB so that all allocations done by the stub
are naturally compatible with a 64 KB granule kernel.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/include/asm/efi.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 5420ad5a4c63..18d4a764d630 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -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 */
--
1.8.3.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PATCH v3 00/13] arm64: stable UEFI mappings for kexec
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (12 preceding siblings ...)
2014-11-18 12:57 ` [PATCH v3 13/13] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB Ard Biesheuvel
@ 2014-11-20 1:27 ` Geoff Levand
2014-11-20 22:05 ` Geoff Levand
14 siblings, 0 replies; 32+ messages in thread
From: Geoff Levand @ 2014-11-20 1:27 UTC (permalink / raw)
To: linux-arm-kernel
Hi Ard,
On Tue, 2014-11-18 at 13:56 +0100, Ard Biesheuvel wrote:
> 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
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-18 12:57 ` [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM Ard Biesheuvel
@ 2014-11-20 17:28 ` Mark Salter
2014-11-20 17:38 ` Ard Biesheuvel
0 siblings, 1 reply; 32+ messages in thread
From: Mark Salter @ 2014-11-20 17:28 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
> diff --git a/drivers/firmware/efi/virtmap.c
> b/drivers/firmware/efi/virtmap.c
> index 98735fb43581..4b6a5c31629f 100644
> --- a/drivers/firmware/efi/virtmap.c
> +++ b/drivers/firmware/efi/virtmap.c
> @@ -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);
> + }
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)
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-20 17:28 ` Mark Salter
@ 2014-11-20 17:38 ` Ard Biesheuvel
2014-11-20 17:54 ` Mark Salter
0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-20 17:38 UTC (permalink / raw)
To: linux-arm-kernel
On 20 November 2014 18:28, Mark Salter <msalter@redhat.com> wrote:
> On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
>> diff --git a/drivers/firmware/efi/virtmap.c
>> b/drivers/firmware/efi/virtmap.c
>> index 98735fb43581..4b6a5c31629f 100644
>> --- a/drivers/firmware/efi/virtmap.c
>> +++ b/drivers/firmware/efi/virtmap.c
>> @@ -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);
>> + }
>
> What exactly is the memblock_remove trying 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.
> 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)
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-20 17:38 ` Ard Biesheuvel
@ 2014-11-20 17:54 ` Mark Salter
2014-11-21 12:07 ` Ard Biesheuvel
0 siblings, 1 reply; 32+ messages in thread
From: Mark Salter @ 2014-11-20 17:54 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 2014-11-20 at 18:38 +0100, Ard Biesheuvel wrote:
> On 20 November 2014 18:28, Mark Salter <msalter@redhat.com> wrote:
> > On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
> >> diff --git a/drivers/firmware/efi/virtmap.c
> >> b/drivers/firmware/efi/virtmap.c
> >> index 98735fb43581..4b6a5c31629f 100644
> >> --- a/drivers/firmware/efi/virtmap.c
> >> +++ b/drivers/firmware/efi/virtmap.c
> >> @@ -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);
> >> + }
> >
> > What exactly is the memblock_remove trying 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.
>
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.
>
> > 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)
> >
> >
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 00/13] arm64: stable UEFI mappings for kexec
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
` (13 preceding siblings ...)
2014-11-20 1:27 ` [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Geoff Levand
@ 2014-11-20 22:05 ` Geoff Levand
2014-11-22 8:49 ` Ard Biesheuvel
14 siblings, 1 reply; 32+ messages in thread
From: Geoff Levand @ 2014-11-20 22:05 UTC (permalink / raw)
To: linux-arm-kernel
Hi Ard,
On Tue, 2014-11-18 at 13:56 +0100, Ard Biesheuvel wrote:
> 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
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-20 17:54 ` Mark Salter
@ 2014-11-21 12:07 ` Ard Biesheuvel
2014-11-21 15:21 ` Mark Salter
0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-21 12:07 UTC (permalink / raw)
To: linux-arm-kernel
On 20 November 2014 18:54, Mark Salter <msalter@redhat.com> wrote:
> On Thu, 2014-11-20 at 18:38 +0100, Ard Biesheuvel wrote:
>> On 20 November 2014 18:28, Mark Salter <msalter@redhat.com> wrote:
>> > On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
>> >> diff --git a/drivers/firmware/efi/virtmap.c
>> >> b/drivers/firmware/efi/virtmap.c
>> >> index 98735fb43581..4b6a5c31629f 100644
>> >> --- a/drivers/firmware/efi/virtmap.c
>> >> +++ b/drivers/firmware/efi/virtmap.c
>> >> @@ -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);
>> >> + }
>> >
>> > What exactly is the memblock_remove trying 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.
>>
> 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.
>
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?
--
Ard.
>>
>> > 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)
>> >
>> >
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-21 12:07 ` Ard Biesheuvel
@ 2014-11-21 15:21 ` Mark Salter
2014-11-26 16:59 ` Ard Biesheuvel
0 siblings, 1 reply; 32+ messages in thread
From: Mark Salter @ 2014-11-21 15:21 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2014-11-21 at 13:07 +0100, Ard Biesheuvel wrote:
> On 20 November 2014 18:54, Mark Salter <msalter@redhat.com> wrote:
> > On Thu, 2014-11-20 at 18:38 +0100, Ard Biesheuvel wrote:
> >> On 20 November 2014 18:28, Mark Salter <msalter@redhat.com> wrote:
> >> > On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
> >> >> diff --git a/drivers/firmware/efi/virtmap.c
> >> >> b/drivers/firmware/efi/virtmap.c
> >> >> index 98735fb43581..4b6a5c31629f 100644
> >> >> --- a/drivers/firmware/efi/virtmap.c
> >> >> +++ b/drivers/firmware/efi/virtmap.c
> >> >> @@ -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);
> >> >> + }
> >> >
> >> > What exactly is the memblock_remove trying 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.
> >>
> > 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.
> >
>
> 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.
Maybe we should add a new memblock to keep track of uefi tables.
The memblock_is_reserved() seems overly permissive to me.
>
> 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.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 00/13] arm64: stable UEFI mappings for kexec
2014-11-20 22:05 ` Geoff Levand
@ 2014-11-22 8:49 ` Ard Biesheuvel
0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-22 8:49 UTC (permalink / raw)
To: linux-arm-kernel
On 20 November 2014 23:05, Geoff Levand <geoff@infradead.org> wrote:
> Hi Ard,
>
> On Tue, 2014-11-18 at 13:56 +0100, Ard Biesheuvel wrote:
>> 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
>
Good stuff! Thanks for testing this.
Let's align so that we can get this merged in the same cycle.
Thanks,
Ard.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables
2014-11-18 12:57 ` [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables Ard Biesheuvel
@ 2014-11-25 14:32 ` Will Deacon
0 siblings, 0 replies; 32+ messages in thread
From: Will Deacon @ 2014-11-25 14:32 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 18, 2014 at 12:57:01PM +0000, Ard Biesheuvel wrote:
> 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 <ard.biesheuvel@linaro.org>
> ---
> 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:
Reviewed-by: Will Deacon <will.deacon@arm.com>
Will
> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> index c2f006c48bdb..5fd40c43be80 100644
> --- a/arch/arm64/include/asm/mmu.h
> +++ b/arch/arm64/include/asm/mmu.h
> @@ -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
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index 41a43bf26492..1abe4d08725b 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -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.
> */
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 83e6713143a3..4d583aa9ff4e 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -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)
> --
> 1.8.3.2
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 04/13] efi: split off remapping code from efi_config_init()
2014-11-18 12:57 ` [PATCH v3 04/13] efi: split off remapping code from efi_config_init() Ard Biesheuvel
@ 2014-11-25 17:24 ` Matt Fleming
2014-11-25 17:48 ` Will Deacon
0 siblings, 1 reply; 32+ messages in thread
From: Matt Fleming @ 2014-11-25 17:24 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 18 Nov, at 01:57:03PM, Ard Biesheuvel wrote:
> 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 <ard.biesheuvel@linaro.org>
> ---
> 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?
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-18 12:57 ` [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling Ard Biesheuvel
@ 2014-11-25 17:39 ` Matt Fleming
2014-11-25 17:48 ` Borislav Petkov
2014-11-26 9:30 ` Dave Young
1 sibling, 1 reply; 32+ messages in thread
From: Matt Fleming @ 2014-11-25 17:39 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 18 Nov, at 01:57:02PM, Ard Biesheuvel wrote:
> Improve 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.
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.
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-25 17:39 ` Matt Fleming
@ 2014-11-25 17:48 ` Borislav Petkov
0 siblings, 0 replies; 32+ messages in thread
From: Borislav Petkov @ 2014-11-25 17:48 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 25, 2014 at 05:39:25PM +0000, Matt Fleming wrote:
> On Tue, 18 Nov, at 01:57:02PM, Ard Biesheuvel wrote:
> > Improve 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.
>
> 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!
> Hooking this into the /dev/mem infrastructure 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...
--
Regards/Gruss,
Boris.
Sent from a fat crate under my desk. Formatting is fine.
--
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 04/13] efi: split off remapping code from efi_config_init()
2014-11-25 17:24 ` Matt Fleming
@ 2014-11-25 17:48 ` Will Deacon
0 siblings, 0 replies; 32+ messages in thread
From: Will Deacon @ 2014-11-25 17:48 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 25, 2014 at 05:24:19PM +0000, Matt Fleming wrote:
> On Tue, 18 Nov, at 01:57:03PM, Ard Biesheuvel wrote:
> > 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 <ard.biesheuvel@linaro.org>
> > ---
> > 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?
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
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-18 12:57 ` [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling Ard Biesheuvel
2014-11-25 17:39 ` Matt Fleming
@ 2014-11-26 9:30 ` Dave Young
2014-11-26 16:23 ` Ard Biesheuvel
1 sibling, 1 reply; 32+ messages in thread
From: Dave Young @ 2014-11-26 9:30 UTC (permalink / raw)
To: linux-arm-kernel
On 11/18/14 at 01:57pm, Ard Biesheuvel wrote:
> Improve 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;
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.
> - avoid using non-cached mappings for those parts of System RAM, as it
> may result in mismatched attributes.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm64/mm/mmap.c | 5 +++--
> arch/arm64/mm/mmu.c | 15 ++++++++++++++-
> 2 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
> index 1d73662f00ff..802cdf0df921 100644
> --- a/arch/arm64/mm/mmap.c
> +++ b/arch/arm64/mm/mmap.c
> @@ -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;
> }
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 4d583aa9ff4e..93ba10838359 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -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
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-26 9:30 ` Dave Young
@ 2014-11-26 16:23 ` Ard Biesheuvel
2014-11-27 6:22 ` Dave Young
0 siblings, 1 reply; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-26 16:23 UTC (permalink / raw)
To: linux-arm-kernel
On 26 November 2014 at 10:30, Dave Young <dyoung@redhat.com> wrote:
> On 11/18/14 at 01:57pm, Ard Biesheuvel wrote:
>> Improve 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;
>
> Ard, can you elabrate a bit? Are this for the acpi case because no dtb in
> procfs?
>
No, that is a different issue.
> Anyway I also think using /dev/mem looks 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.
--
Ard.
>> - avoid using non-cached mappings for those parts of System RAM, as it
>> may result in mismatched attributes.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> arch/arm64/mm/mmap.c | 5 +++--
>> arch/arm64/mm/mmu.c | 15 ++++++++++++++-
>> 2 files changed, 17 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
>> index 1d73662f00ff..802cdf0df921 100644
>> --- a/arch/arm64/mm/mmap.c
>> +++ b/arch/arm64/mm/mmap.c
>> @@ -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;
>> }
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 4d583aa9ff4e..93ba10838359 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -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
>>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM
2014-11-21 15:21 ` Mark Salter
@ 2014-11-26 16:59 ` Ard Biesheuvel
0 siblings, 0 replies; 32+ messages in thread
From: Ard Biesheuvel @ 2014-11-26 16:59 UTC (permalink / raw)
To: linux-arm-kernel
On 21 November 2014 at 16:21, Mark Salter <msalter@redhat.com> wrote:
> On Fri, 2014-11-21 at 13:07 +0100, Ard Biesheuvel wrote:
>> On 20 November 2014 18:54, Mark Salter <msalter@redhat.com> wrote:
>> > On Thu, 2014-11-20 at 18:38 +0100, Ard Biesheuvel wrote:
>> >> On 20 November 2014 18:28, Mark Salter <msalter@redhat.com> wrote:
>> >> > On Tue, 2014-11-18 at 13:57 +0100, Ard Biesheuvel wrote:
>> >> >> diff --git a/drivers/firmware/efi/virtmap.c
>> >> >> b/drivers/firmware/efi/virtmap.c
>> >> >> index 98735fb43581..4b6a5c31629f 100644
>> >> >> --- a/drivers/firmware/efi/virtmap.c
>> >> >> +++ b/drivers/firmware/efi/virtmap.c
>> >> >> @@ -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);
>> >> >> + }
>> >> >
>> >> > What exactly is the memblock_remove trying 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.
>> >>
>> > 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.
>> >
>>
>> 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.
>
> 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
>>
>> 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.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling
2014-11-26 16:23 ` Ard Biesheuvel
@ 2014-11-27 6:22 ` Dave Young
0 siblings, 0 replies; 32+ messages in thread
From: Dave Young @ 2014-11-27 6:22 UTC (permalink / raw)
To: linux-arm-kernel
On 11/26/14 at 05:23pm, Ard Biesheuvel wrote:
> On 26 November 2014 at 10:30, Dave Young <dyoung@redhat.com> wrote:
> > On 11/18/14 at 01:57pm, Ard Biesheuvel wrote:
> >> Improve 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;
> >
> > Ard, can you elabrate a bit? Are this for the acpi case because no dtb in
> > procfs?
> >
>
> No, that is a different issue.
>
> > Anyway I also think using /dev/mem looks 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.
Ard, Ok, thanks for the clarification.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE
2014-11-18 12:57 ` [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE Ard Biesheuvel
@ 2014-11-27 17:30 ` Matt Fleming
0 siblings, 0 replies; 32+ messages in thread
From: Matt Fleming @ 2014-11-27 17:30 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 18 Nov, at 01:57:11PM, Ard Biesheuvel wrote:
> 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, if EFI_ALLOC_ALIGN is #define'd by the platform, use it to round
> up all memory allocations made.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> drivers/firmware/efi/libstub/efi-stub-helper.c | 25 +++++++++++++++++--------
> 1 file changed, 17 insertions(+), 8 deletions(-)
Looks OK to me.
Acked-by: Matt Fleming <matt.fleming@intel.com>
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2014-11-27 17:30 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-18 12:56 [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 01/13] arm64/mm: add explicit struct_mm argument to __create_mapping() Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 02/13] arm64/mm: add create_pgd_mapping() to create private page tables Ard Biesheuvel
2014-11-25 14:32 ` Will Deacon
2014-11-18 12:57 ` [PATCH v3 03/13] arm64: improve CONFIG_STRICT_DEVMEM handling Ard Biesheuvel
2014-11-25 17:39 ` Matt Fleming
2014-11-25 17:48 ` Borislav Petkov
2014-11-26 9:30 ` Dave Young
2014-11-26 16:23 ` Ard Biesheuvel
2014-11-27 6:22 ` Dave Young
2014-11-18 12:57 ` [PATCH v3 04/13] efi: split off remapping code from efi_config_init() Ard Biesheuvel
2014-11-25 17:24 ` Matt Fleming
2014-11-25 17:48 ` Will Deacon
2014-11-18 12:57 ` [PATCH v3 05/13] efi: add common infrastructure for stub-installed virtual mapping Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 06/13] efi: register iomem resources for UEFI reserved regions Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 07/13] arm64/efi: move SetVirtualAddressMap() to UEFI stub Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 08/13] arm64/efi: remove free_boot_services() and friends Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 09/13] arm64/efi: remove idmap manipulations from UEFI code Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 10/13] arm64/efi: use UEFI memory map unconditionally if available Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 11/13] arm64/efi: use plain memblock API for adding and removing reserved RAM Ard Biesheuvel
2014-11-20 17:28 ` Mark Salter
2014-11-20 17:38 ` Ard Biesheuvel
2014-11-20 17:54 ` Mark Salter
2014-11-21 12:07 ` Ard Biesheuvel
2014-11-21 15:21 ` Mark Salter
2014-11-26 16:59 ` Ard Biesheuvel
2014-11-18 12:57 ` [PATCH v3 12/13] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE Ard Biesheuvel
2014-11-27 17:30 ` Matt Fleming
2014-11-18 12:57 ` [PATCH v3 13/13] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB Ard Biesheuvel
2014-11-20 1:27 ` [PATCH v3 00/13] arm64: stable UEFI mappings for kexec Geoff Levand
2014-11-20 22:05 ` Geoff Levand
2014-11-22 8:49 ` Ard Biesheuvel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).