All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-16 18:32 ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

This series adds support for booting the 32-bit ARM kernel directly from
UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
code, and the differences (primarily the PE/COFF header and entry point and
the efi_create_mapping() implementation) are split out into arm64 and ARM
versions.

Changes since v1:
- The primary difference between this version and the first one is that all
  prerequisites have either been merged, dropped for now (early FDT handling)
  or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
  on top of v4.4-rc1 directly.
- Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
  approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
  better in the next version of the spec.

Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
code. Its purpose is to annotate memory regions as normal memory even if they
are removed from the kernel direct mapping.

Patch #2 implements MEMBLOCK_NOMAP support for arm64

Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
used by runtime services from the kernel direct mapping

Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
arm-init.c and arm-runtime.c under drivers/firmware/efi.

Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
pieces, and change a couple of arm64-isms that ARM handles slightly differently.

Patch #6 enables the generic early_ioremap and early_memremap implementations
for ARM. It reuses the kmap fixmap region, which is not used that early anyway.

Patch #7 splits off the core functionality of create_mapping() into a new
function __create_mapping() that we can reuse for mapping UEFI runtime regions.

Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
using another (late) allocator.

Patch #9 implements create_mapping_late() that uses a late allocator.

Patch #10 implements MEMBLOCK_NOMAP support for ARM

Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
memory map and map the runtime services.

Patch #12 ties together all of the above, by implementing the UEFI stub, and
introducing the Kconfig symbols that allow all of this to be built.

Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
https://wiki.linaro.org/LEG/UEFIforQEMU

Ard Biesheuvel (11):
  mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  arm64: only consider memblocks with NOMAP cleared for linear mapping
  arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
  arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  ARM: add support for generic early_ioremap/early_memremap
  ARM: split off core mapping logic from create_mapping
  ARM: factor out allocation routine from __create_mapping()
  ARM: implement create_mapping_late() for EFI use
  ARM: only consider memblocks with NOMAP cleared for linear mapping
  ARM: wire up UEFI init and runtime support

Roy Franz (1):
  ARM: add UEFI stub support

 arch/arm/Kconfig                          |  20 ++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
 arch/arm/boot/compressed/head.S           |  54 +++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
 arch/arm/include/asm/Kbuild               |   1 +
 arch/arm/include/asm/efi.h                |  90 ++++++
 arch/arm/include/asm/fixmap.h             |  29 +-
 arch/arm/include/asm/mach/map.h           |   1 +
 arch/arm/kernel/Makefile                  |   1 +
 arch/arm/kernel/efi.c                     |  38 +++
 arch/arm/kernel/setup.c                   |  10 +-
 arch/arm/mm/init.c                        |   5 +-
 arch/arm/mm/ioremap.c                     |   9 +
 arch/arm/mm/mmu.c                         | 110 ++++---
 arch/arm64/include/asm/efi.h              |  16 +
 arch/arm64/kernel/efi.c                   | 331 ++------------------
 arch/arm64/mm/init.c                      |   2 +-
 arch/arm64/mm/mmu.c                       |   2 +
 drivers/firmware/efi/Makefile             |   4 +
 drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
 drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
 drivers/firmware/efi/efi.c                |   2 +
 drivers/firmware/efi/libstub/Makefile     |   9 +
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
 include/linux/memblock.h                  |   8 +
 mm/memblock.c                             |  28 ++
 28 files changed, 975 insertions(+), 356 deletions(-)
 create mode 100644 arch/arm/boot/compressed/efi-header.S
 create mode 100644 arch/arm/include/asm/efi.h
 create mode 100644 arch/arm/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-init.c
 create mode 100644 drivers/firmware/efi/arm-runtime.c
 create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-16 18:32 ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This series adds support for booting the 32-bit ARM kernel directly from
UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
code, and the differences (primarily the PE/COFF header and entry point and
the efi_create_mapping() implementation) are split out into arm64 and ARM
versions.

Changes since v1:
- The primary difference between this version and the first one is that all
  prerequisites have either been merged, dropped for now (early FDT handling)
  or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
  on top of v4.4-rc1 directly.
- Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
  approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
  better in the next version of the spec.

Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
code. Its purpose is to annotate memory regions as normal memory even if they
are removed from the kernel direct mapping.

Patch #2 implements MEMBLOCK_NOMAP support for arm64

Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
used by runtime services from the kernel direct mapping

Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
arm-init.c and arm-runtime.c under drivers/firmware/efi.

Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
pieces, and change a couple of arm64-isms that ARM handles slightly differently.

Patch #6 enables the generic early_ioremap and early_memremap implementations
for ARM. It reuses the kmap fixmap region, which is not used that early anyway.

Patch #7 splits off the core functionality of create_mapping() into a new
function __create_mapping() that we can reuse for mapping UEFI runtime regions.

Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
using another (late) allocator.

Patch #9 implements create_mapping_late() that uses a late allocator.

Patch #10 implements MEMBLOCK_NOMAP support for ARM

Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
memory map and map the runtime services.

Patch #12 ties together all of the above, by implementing the UEFI stub, and
introducing the Kconfig symbols that allow all of this to be built.

Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
https://wiki.linaro.org/LEG/UEFIforQEMU

Ard Biesheuvel (11):
  mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  arm64: only consider memblocks with NOMAP cleared for linear mapping
  arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
  arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  ARM: add support for generic early_ioremap/early_memremap
  ARM: split off core mapping logic from create_mapping
  ARM: factor out allocation routine from __create_mapping()
  ARM: implement create_mapping_late() for EFI use
  ARM: only consider memblocks with NOMAP cleared for linear mapping
  ARM: wire up UEFI init and runtime support

Roy Franz (1):
  ARM: add UEFI stub support

 arch/arm/Kconfig                          |  20 ++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
 arch/arm/boot/compressed/head.S           |  54 +++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
 arch/arm/include/asm/Kbuild               |   1 +
 arch/arm/include/asm/efi.h                |  90 ++++++
 arch/arm/include/asm/fixmap.h             |  29 +-
 arch/arm/include/asm/mach/map.h           |   1 +
 arch/arm/kernel/Makefile                  |   1 +
 arch/arm/kernel/efi.c                     |  38 +++
 arch/arm/kernel/setup.c                   |  10 +-
 arch/arm/mm/init.c                        |   5 +-
 arch/arm/mm/ioremap.c                     |   9 +
 arch/arm/mm/mmu.c                         | 110 ++++---
 arch/arm64/include/asm/efi.h              |  16 +
 arch/arm64/kernel/efi.c                   | 331 ++------------------
 arch/arm64/mm/init.c                      |   2 +-
 arch/arm64/mm/mmu.c                       |   2 +
 drivers/firmware/efi/Makefile             |   4 +
 drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
 drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
 drivers/firmware/efi/efi.c                |   2 +
 drivers/firmware/efi/libstub/Makefile     |   9 +
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
 include/linux/memblock.h                  |   8 +
 mm/memblock.c                             |  28 ++
 28 files changed, 975 insertions(+), 356 deletions(-)
 create mode 100644 arch/arm/boot/compressed/efi-header.S
 create mode 100644 arch/arm/include/asm/efi.h
 create mode 100644 arch/arm/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-init.c
 create mode 100644 drivers/firmware/efi/arm-runtime.c
 create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c

-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-16 18:32 ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds support for booting the 32-bit ARM kernel directly from
UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
code, and the differences (primarily the PE/COFF header and entry point and
the efi_create_mapping() implementation) are split out into arm64 and ARM
versions.

Changes since v1:
- The primary difference between this version and the first one is that all
  prerequisites have either been merged, dropped for now (early FDT handling)
  or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
  on top of v4.4-rc1 directly.
- Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
  approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
  better in the next version of the spec.

Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
code. Its purpose is to annotate memory regions as normal memory even if they
are removed from the kernel direct mapping.

Patch #2 implements MEMBLOCK_NOMAP support for arm64

Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
used by runtime services from the kernel direct mapping

Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
arm-init.c and arm-runtime.c under drivers/firmware/efi.

Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
pieces, and change a couple of arm64-isms that ARM handles slightly differently.

Patch #6 enables the generic early_ioremap and early_memremap implementations
for ARM. It reuses the kmap fixmap region, which is not used that early anyway.

Patch #7 splits off the core functionality of create_mapping() into a new
function __create_mapping() that we can reuse for mapping UEFI runtime regions.

Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
using another (late) allocator.

Patch #9 implements create_mapping_late() that uses a late allocator.

Patch #10 implements MEMBLOCK_NOMAP support for ARM

Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
memory map and map the runtime services.

Patch #12 ties together all of the above, by implementing the UEFI stub, and
introducing the Kconfig symbols that allow all of this to be built.

Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
https://wiki.linaro.org/LEG/UEFIforQEMU

Ard Biesheuvel (11):
  mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  arm64: only consider memblocks with NOMAP cleared for linear mapping
  arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
  arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  ARM: add support for generic early_ioremap/early_memremap
  ARM: split off core mapping logic from create_mapping
  ARM: factor out allocation routine from __create_mapping()
  ARM: implement create_mapping_late() for EFI use
  ARM: only consider memblocks with NOMAP cleared for linear mapping
  ARM: wire up UEFI init and runtime support

Roy Franz (1):
  ARM: add UEFI stub support

 arch/arm/Kconfig                          |  20 ++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
 arch/arm/boot/compressed/head.S           |  54 +++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
 arch/arm/include/asm/Kbuild               |   1 +
 arch/arm/include/asm/efi.h                |  90 ++++++
 arch/arm/include/asm/fixmap.h             |  29 +-
 arch/arm/include/asm/mach/map.h           |   1 +
 arch/arm/kernel/Makefile                  |   1 +
 arch/arm/kernel/efi.c                     |  38 +++
 arch/arm/kernel/setup.c                   |  10 +-
 arch/arm/mm/init.c                        |   5 +-
 arch/arm/mm/ioremap.c                     |   9 +
 arch/arm/mm/mmu.c                         | 110 ++++---
 arch/arm64/include/asm/efi.h              |  16 +
 arch/arm64/kernel/efi.c                   | 331 ++------------------
 arch/arm64/mm/init.c                      |   2 +-
 arch/arm64/mm/mmu.c                       |   2 +
 drivers/firmware/efi/Makefile             |   4 +
 drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
 drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
 drivers/firmware/efi/efi.c                |   2 +
 drivers/firmware/efi/libstub/Makefile     |   9 +
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
 include/linux/memblock.h                  |   8 +
 mm/memblock.c                             |  28 ++
 28 files changed, 975 insertions(+), 356 deletions(-)
 create mode 100644 arch/arm/boot/compressed/efi-header.S
 create mode 100644 arch/arm/include/asm/efi.h
 create mode 100644 arch/arm/kernel/efi.c
 create mode 100644 drivers/firmware/efi/arm-init.c
 create mode 100644 drivers/firmware/efi/arm-runtime.c
 create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  2015-11-16 18:32 ` Ard Biesheuvel
@ 2015-11-16 18:32   ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
to make it usable as an indicator that some parts of normal memory
should not be covered by the kernel direct mapping. It is up to the
arch to actually honor the attribute when laying out this mapping,
but the memblock code itself is modified to disregard these regions
for allocations and other general use.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 include/linux/memblock.h |  8 ++++++
 mm/memblock.c            | 28 ++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 24daf8fc4d7c..fec66f86eeff 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -25,6 +25,7 @@ enum {
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
 	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
 	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
+	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
 };
 
 struct memblock_region {
@@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
 int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
+int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
@@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
 	return m->flags & MEMBLOCK_MIRROR;
 }
 
+static inline bool memblock_is_nomap(struct memblock_region *m)
+{
+	return m->flags & MEMBLOCK_NOMAP;
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
 			    unsigned long  *end_pfn);
@@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 int memblock_is_memory(phys_addr_t addr);
+int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
 int memblock_is_reserved(phys_addr_t addr);
 bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index d300f1329814..07ff069fef25 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
 	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
 }
 
+/**
+ * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
+}
 
 /**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
@@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
 	return memblock_search(&memblock.memory, addr) != -1;
 }
 
+int __init_memblock memblock_is_map_memory(phys_addr_t addr)
+{
+	int i = memblock_search(&memblock.memory, addr);
+
+	if (i == -1)
+		return false;
+	return !memblock_is_nomap(&memblock.memory.regions[i]);
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
 			 unsigned long *start_pfn, unsigned long *end_pfn)
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 18:32   ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
to make it usable as an indicator that some parts of normal memory
should not be covered by the kernel direct mapping. It is up to the
arch to actually honor the attribute when laying out this mapping,
but the memblock code itself is modified to disregard these regions
for allocations and other general use.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 include/linux/memblock.h |  8 ++++++
 mm/memblock.c            | 28 ++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 24daf8fc4d7c..fec66f86eeff 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -25,6 +25,7 @@ enum {
 	MEMBLOCK_NONE		= 0x0,	/* No special request */
 	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
 	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
+	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
 };
 
 struct memblock_region {
@@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
 int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
+int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
@@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
 	return m->flags & MEMBLOCK_MIRROR;
 }
 
+static inline bool memblock_is_nomap(struct memblock_region *m)
+{
+	return m->flags & MEMBLOCK_NOMAP;
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
 			    unsigned long  *end_pfn);
@@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 int memblock_is_memory(phys_addr_t addr);
+int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
 int memblock_is_reserved(phys_addr_t addr);
 bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index d300f1329814..07ff069fef25 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
 	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
 }
 
+/**
+ * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
+}
 
 /**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
@@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
 		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
 			continue;
 
+		/* skip nomap memory unless we were asked for it explicitly */
+		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
+			continue;
+
 		if (!type_b) {
 			if (out_start)
 				*out_start = m_start;
@@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
 	return memblock_search(&memblock.memory, addr) != -1;
 }
 
+int __init_memblock memblock_is_map_memory(phys_addr_t addr)
+{
+	int i = memblock_search(&memblock.memory, addr);
+
+	if (i == -1)
+		return false;
+	return !memblock_is_nomap(&memblock.memory.regions[i]);
+}
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
 			 unsigned long *start_pfn, unsigned long *end_pfn)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 02/12] arm64: only consider memblocks with NOMAP cleared for linear mapping
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm64/mm/init.c | 2 +-
 arch/arm64/mm/mmu.c  | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 17bf39ac83ba..ac4d7cbbdd2d 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -120,7 +120,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(pfn << PAGE_SHIFT);
+	return memblock_is_map_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e3f563c81c48..0cf325c8dc55 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -421,6 +421,8 @@ static void __init map_mem(void)
 
 		if (start >= end)
 			break;
+		if (memblock_is_nomap(reg))
+			continue;
 
 		if (ARM64_SWAPPER_USES_SECTION_MAPS) {
 			/*
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 02/12] arm64: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/mm/init.c | 2 +-
 arch/arm64/mm/mmu.c  | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 17bf39ac83ba..ac4d7cbbdd2d 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -120,7 +120,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(pfn << PAGE_SHIFT);
+	return memblock_is_map_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e3f563c81c48..0cf325c8dc55 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -421,6 +421,8 @@ static void __init map_mem(void)
 
 		if (start >= end)
 			break;
+		if (memblock_is_nomap(reg))
+			continue;
 
 		if (ARM64_SWAPPER_USES_SECTION_MAPS) {
 			/*
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 02/12] arm64: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/mm/init.c | 2 +-
 arch/arm64/mm/mmu.c  | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 17bf39ac83ba..ac4d7cbbdd2d 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -120,7 +120,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(pfn << PAGE_SHIFT);
+	return memblock_is_map_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e3f563c81c48..0cf325c8dc55 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -421,6 +421,8 @@ static void __init map_mem(void)
 
 		if (start >= end)
 			break;
+		if (memblock_is_nomap(reg))
+			continue;
 
 		if (ARM64_SWAPPER_USES_SECTION_MAPS) {
 			/*
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 03/12] arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
  2015-11-16 18:32 ` Ard Biesheuvel
@ 2015-11-16 18:32   ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

Change the EFI memory reservation logic to use memblock_mark_nomap()
rather than memblock_reserve() to mark UEFI reserved regions as
occupied. In addition to reserving them against allocations done by
memblock, this will also prevent them from being covered by the linear
mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kernel/efi.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index de46b50f4cdf..c7c7fb417110 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -183,7 +183,7 @@ static __init void reserve_regions(void)
 			early_init_dt_add_memory_arch(paddr, size);
 
 		if (is_reserve_region(md)) {
-			memblock_reserve(paddr, size);
+			memblock_mark_nomap(paddr, size);
 			if (efi_enabled(EFI_DBG))
 				pr_cont("*");
 		}
@@ -205,8 +205,6 @@ void __init efi_init(void)
 
 	efi_system_table = params.system_table;
 
-	memblock_reserve(params.mmap & PAGE_MASK,
-			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
 	memmap.phys_map = params.mmap;
 	memmap.map = early_memremap(params.mmap, params.mmap_size);
 	memmap.map_end = memmap.map + params.mmap_size;
@@ -218,6 +216,9 @@ void __init efi_init(void)
 
 	reserve_regions();
 	early_memunmap(memmap.map, params.mmap_size);
+	memblock_mark_nomap(params.mmap & PAGE_MASK,
+			    PAGE_ALIGN(params.mmap_size +
+				       (params.mmap & ~PAGE_MASK)));
 }
 
 static bool __init efi_virtmap_init(void)
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 03/12] arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
@ 2015-11-16 18:32   ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Change the EFI memory reservation logic to use memblock_mark_nomap()
rather than memblock_reserve() to mark UEFI reserved regions as
occupied. In addition to reserving them against allocations done by
memblock, this will also prevent them from being covered by the linear
mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kernel/efi.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index de46b50f4cdf..c7c7fb417110 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -183,7 +183,7 @@ static __init void reserve_regions(void)
 			early_init_dt_add_memory_arch(paddr, size);
 
 		if (is_reserve_region(md)) {
-			memblock_reserve(paddr, size);
+			memblock_mark_nomap(paddr, size);
 			if (efi_enabled(EFI_DBG))
 				pr_cont("*");
 		}
@@ -205,8 +205,6 @@ void __init efi_init(void)
 
 	efi_system_table = params.system_table;
 
-	memblock_reserve(params.mmap & PAGE_MASK,
-			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
 	memmap.phys_map = params.mmap;
 	memmap.map = early_memremap(params.mmap, params.mmap_size);
 	memmap.map_end = memmap.map + params.mmap_size;
@@ -218,6 +216,9 @@ void __init efi_init(void)
 
 	reserve_regions();
 	early_memunmap(memmap.map, params.mmap_size);
+	memblock_mark_nomap(params.mmap & PAGE_MASK,
+			    PAGE_ALIGN(params.mmap_size +
+				       (params.mmap & ~PAGE_MASK)));
 }
 
 static bool __init efi_virtmap_init(void)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:32 ` Ard Biesheuvel
@ 2015-11-16 18:32   ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This splits off the early EFI init and runtime code that
- discovers the EFI params and the memory map from the FDT, and installs
  the memblocks and config tables.
- prepares and installs the EFI page tables so that UEFI Runtime Services
  can be invoked at the virtual address installed by the stub.

This will allow it to be reused for 32-bit ARM.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kernel/efi.c            | 323 +-------------------
 drivers/firmware/efi/Makefile      |   3 +
 drivers/firmware/efi/arm-init.c    | 196 ++++++++++++
 drivers/firmware/efi/arm-runtime.c | 160 ++++++++++
 4 files changed, 360 insertions(+), 322 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index c7c7fb417110..bd3b2f5adf0c 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,308 +11,11 @@
  *
  */
 
-#include <linux/atomic.h>
 #include <linux/dmi.h>
 #include <linux/efi.h>
-#include <linux/export.h>
-#include <linux/memblock.h>
-#include <linux/mm_types.h>
-#include <linux/bootmem.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/preempt.h>
-#include <linux/rbtree.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 
-#include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-
-struct efi_memory_map memmap;
-
-static u64 efi_system_table;
-
-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),
-};
-
-static int __init is_normal_ram(efi_memory_desc_t *md)
-{
-	if (md->attribute & EFI_MEMORY_WB)
-		return 1;
-	return 0;
-}
-
-/*
- * 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.
- */
-static 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;
-}
-
-static int __init uefi_init(void)
-{
-	efi_char16_t *c16;
-	void *config_tables;
-	u64 table_size;
-	char vendor[100] = "unknown";
-	int i, retval;
-
-	efi.systab = early_memremap(efi_system_table,
-				    sizeof(efi_system_table_t));
-	if (efi.systab == NULL) {
-		pr_warn("Unable to map EFI system table.\n");
-		return -ENOMEM;
-	}
-
-	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
-
-	/*
-	 * Verify the EFI Table
-	 */
-	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
-		pr_err("System table signature incorrect\n");
-		retval = -EINVAL;
-		goto out;
-	}
-	if ((efi.systab->hdr.revision >> 16) < 2)
-		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
-			efi.systab->hdr.revision >> 16,
-			efi.systab->hdr.revision & 0xffff);
-
-	/* Show what we know for posterity */
-	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
-			     sizeof(vendor) * sizeof(efi_char16_t));
-	if (c16) {
-		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = c16[i];
-		vendor[i] = '\0';
-		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
-	}
-
-	pr_info("EFI v%u.%.02u by %s\n",
-		efi.systab->hdr.revision >> 16,
-		efi.systab->hdr.revision & 0xffff, vendor);
-
-	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,
-					 sizeof(efi_config_table_64_t), NULL);
-
-	early_memunmap(config_tables, table_size);
-out:
-	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
-	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:
-	case EFI_PERSISTENT_MEMORY:
-		return 0;
-	default:
-		break;
-	}
-	return is_normal_ram(md);
-}
-
-static __init void reserve_regions(void)
-{
-	efi_memory_desc_t *md;
-	u64 paddr, npages, size;
-
-	if (efi_enabled(EFI_DBG))
-		pr_info("Processing EFI memory map:\n");
-
-	for_each_efi_memory_desc(&memmap, md) {
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-
-		if (efi_enabled(EFI_DBG)) {
-			char buf[64];
-
-			pr_info("  0x%012llx-0x%012llx %s",
-				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-				efi_md_typeattr_format(buf, sizeof(buf), md));
-		}
-
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		if (is_normal_ram(md))
-			early_init_dt_add_memory_arch(paddr, size);
-
-		if (is_reserve_region(md)) {
-			memblock_mark_nomap(paddr, size);
-			if (efi_enabled(EFI_DBG))
-				pr_cont("*");
-		}
-
-		if (efi_enabled(EFI_DBG))
-			pr_cont("\n");
-	}
-
-	set_bit(EFI_MEMMAP, &efi.flags);
-}
-
-void __init efi_init(void)
-{
-	struct efi_fdt_params params;
-
-	/* Grab UEFI information placed in FDT by stub */
-	if (!efi_get_fdt_params(&params))
-		return;
-
-	efi_system_table = params.system_table;
-
-	memmap.phys_map = params.mmap;
-	memmap.map = early_memremap(params.mmap, params.mmap_size);
-	memmap.map_end = memmap.map + params.mmap_size;
-	memmap.desc_size = params.desc_size;
-	memmap.desc_version = params.desc_ver;
-
-	if (uefi_init() < 0)
-		return;
-
-	reserve_regions();
-	early_memunmap(memmap.map, params.mmap_size);
-	memblock_mark_nomap(params.mmap & PAGE_MASK,
-			    PAGE_ALIGN(params.mmap_size +
-				       (params.mmap & ~PAGE_MASK)));
-}
-
-static bool __init efi_virtmap_init(void)
-{
-	efi_memory_desc_t *md;
-
-	for_each_efi_memory_desc(&memmap, md) {
-		u64 paddr, npages, size;
-		pgprot_t prot;
-
-		if (!(md->attribute & EFI_MEMORY_RUNTIME))
-			continue;
-		if (md->virt_addr == 0)
-			return false;
-
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		pr_info("  EFI remap 0x%016llx => %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 (!is_normal_ram(md))
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
-	}
-	return true;
-}
-
-/*
- * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
- * non-early mapping of the UEFI system table and virtual mappings for all
- * EFI_MEMORY_RUNTIME regions.
- */
-static int __init arm64_enable_runtime_services(void)
-{
-	u64 mapsize;
-
-	if (!efi_enabled(EFI_BOOT)) {
-		pr_info("EFI services will not be available.\n");
-		return -1;
-	}
-
-	if (efi_runtime_disabled()) {
-		pr_info("EFI runtime services will be disabled.\n");
-		return -1;
-	}
-
-	pr_info("Remapping and enabling EFI services.\n");
-
-	mapsize = memmap.map_end - memmap.map;
-	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
-						   mapsize);
-	if (!memmap.map) {
-		pr_err("Failed to remap EFI memory map\n");
-		return -1;
-	}
-	memmap.map_end = memmap.map + mapsize;
-	efi.memmap = &memmap;
-
-	efi.systab = (__force void *)ioremap_cache(efi_system_table,
-						   sizeof(efi_system_table_t));
-	if (!efi.systab) {
-		pr_err("Failed to remap EFI System Table\n");
-		return -1;
-	}
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
-	if (!efi_virtmap_init()) {
-		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
-		return -1;
-	}
-
-	/* Set up runtime services function pointers */
-	efi_native_runtime_setup();
-	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-
-	efi.runtime_version = efi.systab->hdr.revision;
-
-	return 0;
-}
-early_initcall(arm64_enable_runtime_services);
 
 static int __init arm64_dmi_init(void)
 {
@@ -328,30 +31,6 @@ static int __init arm64_dmi_init(void)
 }
 core_initcall(arm64_dmi_init);
 
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	if (mm == &init_mm)
-		cpu_set_reserved_ttbr0();
-	else
-		cpu_switch_mm(mm->pgd, mm);
-
-	local_flush_tlb_all();
-	if (icache_is_aivivt())
-		__local_flush_icache_all();
-}
-
-void efi_virtmap_load(void)
-{
-	preempt_disable();
-	efi_set_pgd(&efi_mm);
-}
-
-void efi_virtmap_unload(void)
-{
-	efi_set_pgd(current->active_mm);
-	preempt_enable();
-}
-
 /*
  * UpdateCapsule() depends on the system being shutdown via
  * ResetSystem().
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index ec379a4164cc..f292917b00e7 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
+
+arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
new file mode 100644
index 000000000000..4653d789f10d
--- /dev/null
+++ b/drivers/firmware/efi/arm-init.c
@@ -0,0 +1,196 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013 - 2015 Linaro Ltd.
+ *
+ * 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/init.h>
+#include <linux/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+
+#include <asm/efi.h>
+
+struct efi_memory_map memmap;
+
+u64 efi_system_table;
+
+static int __init is_normal_ram(efi_memory_desc_t *md)
+{
+	if (md->attribute & EFI_MEMORY_WB)
+		return 1;
+	return 0;
+}
+
+/*
+ * 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.
+ */
+static 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;
+}
+
+static int __init uefi_init(void)
+{
+	efi_char16_t *c16;
+	void *config_tables;
+	u64 table_size;
+	char vendor[100] = "unknown";
+	int i, retval;
+
+	efi.systab = early_memremap(efi_system_table,
+				    sizeof(efi_system_table_t));
+	if (efi.systab == NULL) {
+		pr_warn("Unable to map EFI system table.\n");
+		return -ENOMEM;
+	}
+
+	set_bit(EFI_BOOT, &efi.flags);
+	set_bit(EFI_64BIT, &efi.flags);
+
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+		pr_err("System table signature incorrect\n");
+		retval = -EINVAL;
+		goto out;
+	}
+	if ((efi.systab->hdr.revision >> 16) < 2)
+		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
+			efi.systab->hdr.revision >> 16,
+			efi.systab->hdr.revision & 0xffff);
+
+	/* Show what we know for posterity */
+	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
+			     sizeof(vendor) * sizeof(efi_char16_t));
+	if (c16) {
+		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	}
+
+	pr_info("EFI v%u.%.02u by %s\n",
+		efi.systab->hdr.revision >> 16,
+		efi.systab->hdr.revision & 0xffff, vendor);
+
+	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,
+					 sizeof(efi_config_table_64_t), NULL);
+
+	early_memunmap(config_tables, table_size);
+out:
+	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+	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:
+	case EFI_PERSISTENT_MEMORY:
+		return 0;
+	default:
+		break;
+	}
+	return is_normal_ram(md);
+}
+
+static __init void reserve_regions(void)
+{
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	if (efi_enabled(EFI_DBG))
+		pr_info("Processing EFI memory map:\n");
+
+	for_each_efi_memory_desc(&memmap, md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		if (efi_enabled(EFI_DBG)) {
+			char buf[64];
+
+			pr_info("  0x%012llx-0x%012llx %s",
+				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
+				efi_md_typeattr_format(buf, sizeof(buf), md));
+		}
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_normal_ram(md))
+			early_init_dt_add_memory_arch(paddr, size);
+
+		if (is_reserve_region(md)) {
+			memblock_mark_nomap(paddr, size);
+			if (efi_enabled(EFI_DBG))
+				pr_cont("*");
+		}
+
+		if (efi_enabled(EFI_DBG))
+			pr_cont("\n");
+	}
+
+	set_bit(EFI_MEMMAP, &efi.flags);
+}
+
+void __init efi_init(void)
+{
+	struct efi_fdt_params params;
+
+	/* Grab UEFI information placed in FDT by stub */
+	if (!efi_get_fdt_params(&params))
+		return;
+
+	efi_system_table = params.system_table;
+
+	memmap.phys_map = params.mmap;
+	memmap.map = early_memremap(params.mmap, params.mmap_size);
+	memmap.map_end = memmap.map + params.mmap_size;
+	memmap.desc_size = params.desc_size;
+	memmap.desc_version = params.desc_ver;
+
+	if (uefi_init() < 0)
+		return;
+
+	reserve_regions();
+	early_memunmap(memmap.map, params.mmap_size);
+	memblock_mark_nomap(params.mmap & PAGE_MASK,
+			    PAGE_ALIGN(params.mmap_size +
+				       (params.mmap & ~PAGE_MASK)));
+}
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
new file mode 100644
index 000000000000..e62ee5df96ca
--- /dev/null
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -0,0 +1,160 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013, 2014 Linaro Ltd.
+ *
+ * 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/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/preempt.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/efi.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+
+static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
+
+extern u64 efi_system_table;
+
+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),
+};
+
+static bool __init efi_virtmap_init(void)
+{
+	efi_memory_desc_t *md;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		u64 paddr, npages, size;
+		pgprot_t prot;
+
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (md->virt_addr == 0)
+			return false;
+
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		pr_info("  EFI remap 0x%016llx => %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->attribute & EFI_MEMORY_WB) == 0)
+			prot = __pgprot(PROT_DEVICE_nGnRE);
+		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+			 !PAGE_ALIGNED(md->phys_addr))
+			prot = PAGE_KERNEL_EXEC;
+		else
+			prot = PAGE_KERNEL;
+
+		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+	}
+	return true;
+}
+
+/*
+ * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
+ * non-early mapping of the UEFI system table and virtual mappings for all
+ * EFI_MEMORY_RUNTIME regions.
+ */
+static int __init arm64_enable_runtime_services(void)
+{
+	u64 mapsize;
+
+	if (!efi_enabled(EFI_BOOT)) {
+		pr_info("EFI services will not be available.\n");
+		return -1;
+	}
+
+	if (efi_runtime_disabled()) {
+		pr_info("EFI runtime services will be disabled.\n");
+		return -1;
+	}
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	mapsize = memmap.map_end - memmap.map;
+	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
+						   mapsize);
+	if (!memmap.map) {
+		pr_err("Failed to remap EFI memory map\n");
+		return -1;
+	}
+	memmap.map_end = memmap.map + mapsize;
+	efi.memmap = &memmap;
+
+	efi.systab = (__force void *)ioremap_cache(efi_system_table,
+						   sizeof(efi_system_table_t));
+	if (!efi.systab) {
+		pr_err("Failed to remap EFI System Table\n");
+		return -1;
+	}
+	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	if (!efi_virtmap_init()) {
+		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
+		return -1;
+	}
+
+	/* Set up runtime services function pointers */
+	efi_native_runtime_setup();
+	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+	efi.runtime_version = efi.systab->hdr.revision;
+
+	return 0;
+}
+early_initcall(arm64_enable_runtime_services);
+
+static void efi_set_pgd(struct mm_struct *mm)
+{
+	if (mm == &init_mm)
+		cpu_set_reserved_ttbr0();
+	else
+		cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
+void efi_virtmap_load(void)
+{
+	preempt_disable();
+	efi_set_pgd(&efi_mm);
+}
+
+void efi_virtmap_unload(void)
+{
+	efi_set_pgd(current->active_mm);
+	preempt_enable();
+}
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:32   ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This splits off the early EFI init and runtime code that
- discovers the EFI params and the memory map from the FDT, and installs
  the memblocks and config tables.
- prepares and installs the EFI page tables so that UEFI Runtime Services
  can be invoked at the virtual address installed by the stub.

This will allow it to be reused for 32-bit ARM.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kernel/efi.c            | 323 +-------------------
 drivers/firmware/efi/Makefile      |   3 +
 drivers/firmware/efi/arm-init.c    | 196 ++++++++++++
 drivers/firmware/efi/arm-runtime.c | 160 ++++++++++
 4 files changed, 360 insertions(+), 322 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index c7c7fb417110..bd3b2f5adf0c 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,308 +11,11 @@
  *
  */
 
-#include <linux/atomic.h>
 #include <linux/dmi.h>
 #include <linux/efi.h>
-#include <linux/export.h>
-#include <linux/memblock.h>
-#include <linux/mm_types.h>
-#include <linux/bootmem.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/preempt.h>
-#include <linux/rbtree.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 
-#include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-
-struct efi_memory_map memmap;
-
-static u64 efi_system_table;
-
-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),
-};
-
-static int __init is_normal_ram(efi_memory_desc_t *md)
-{
-	if (md->attribute & EFI_MEMORY_WB)
-		return 1;
-	return 0;
-}
-
-/*
- * 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.
- */
-static 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;
-}
-
-static int __init uefi_init(void)
-{
-	efi_char16_t *c16;
-	void *config_tables;
-	u64 table_size;
-	char vendor[100] = "unknown";
-	int i, retval;
-
-	efi.systab = early_memremap(efi_system_table,
-				    sizeof(efi_system_table_t));
-	if (efi.systab == NULL) {
-		pr_warn("Unable to map EFI system table.\n");
-		return -ENOMEM;
-	}
-
-	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
-
-	/*
-	 * Verify the EFI Table
-	 */
-	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
-		pr_err("System table signature incorrect\n");
-		retval = -EINVAL;
-		goto out;
-	}
-	if ((efi.systab->hdr.revision >> 16) < 2)
-		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
-			efi.systab->hdr.revision >> 16,
-			efi.systab->hdr.revision & 0xffff);
-
-	/* Show what we know for posterity */
-	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
-			     sizeof(vendor) * sizeof(efi_char16_t));
-	if (c16) {
-		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = c16[i];
-		vendor[i] = '\0';
-		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
-	}
-
-	pr_info("EFI v%u.%.02u by %s\n",
-		efi.systab->hdr.revision >> 16,
-		efi.systab->hdr.revision & 0xffff, vendor);
-
-	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,
-					 sizeof(efi_config_table_64_t), NULL);
-
-	early_memunmap(config_tables, table_size);
-out:
-	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
-	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:
-	case EFI_PERSISTENT_MEMORY:
-		return 0;
-	default:
-		break;
-	}
-	return is_normal_ram(md);
-}
-
-static __init void reserve_regions(void)
-{
-	efi_memory_desc_t *md;
-	u64 paddr, npages, size;
-
-	if (efi_enabled(EFI_DBG))
-		pr_info("Processing EFI memory map:\n");
-
-	for_each_efi_memory_desc(&memmap, md) {
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-
-		if (efi_enabled(EFI_DBG)) {
-			char buf[64];
-
-			pr_info("  0x%012llx-0x%012llx %s",
-				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-				efi_md_typeattr_format(buf, sizeof(buf), md));
-		}
-
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		if (is_normal_ram(md))
-			early_init_dt_add_memory_arch(paddr, size);
-
-		if (is_reserve_region(md)) {
-			memblock_mark_nomap(paddr, size);
-			if (efi_enabled(EFI_DBG))
-				pr_cont("*");
-		}
-
-		if (efi_enabled(EFI_DBG))
-			pr_cont("\n");
-	}
-
-	set_bit(EFI_MEMMAP, &efi.flags);
-}
-
-void __init efi_init(void)
-{
-	struct efi_fdt_params params;
-
-	/* Grab UEFI information placed in FDT by stub */
-	if (!efi_get_fdt_params(&params))
-		return;
-
-	efi_system_table = params.system_table;
-
-	memmap.phys_map = params.mmap;
-	memmap.map = early_memremap(params.mmap, params.mmap_size);
-	memmap.map_end = memmap.map + params.mmap_size;
-	memmap.desc_size = params.desc_size;
-	memmap.desc_version = params.desc_ver;
-
-	if (uefi_init() < 0)
-		return;
-
-	reserve_regions();
-	early_memunmap(memmap.map, params.mmap_size);
-	memblock_mark_nomap(params.mmap & PAGE_MASK,
-			    PAGE_ALIGN(params.mmap_size +
-				       (params.mmap & ~PAGE_MASK)));
-}
-
-static bool __init efi_virtmap_init(void)
-{
-	efi_memory_desc_t *md;
-
-	for_each_efi_memory_desc(&memmap, md) {
-		u64 paddr, npages, size;
-		pgprot_t prot;
-
-		if (!(md->attribute & EFI_MEMORY_RUNTIME))
-			continue;
-		if (md->virt_addr == 0)
-			return false;
-
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		pr_info("  EFI remap 0x%016llx => %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 (!is_normal_ram(md))
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
-	}
-	return true;
-}
-
-/*
- * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
- * non-early mapping of the UEFI system table and virtual mappings for all
- * EFI_MEMORY_RUNTIME regions.
- */
-static int __init arm64_enable_runtime_services(void)
-{
-	u64 mapsize;
-
-	if (!efi_enabled(EFI_BOOT)) {
-		pr_info("EFI services will not be available.\n");
-		return -1;
-	}
-
-	if (efi_runtime_disabled()) {
-		pr_info("EFI runtime services will be disabled.\n");
-		return -1;
-	}
-
-	pr_info("Remapping and enabling EFI services.\n");
-
-	mapsize = memmap.map_end - memmap.map;
-	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
-						   mapsize);
-	if (!memmap.map) {
-		pr_err("Failed to remap EFI memory map\n");
-		return -1;
-	}
-	memmap.map_end = memmap.map + mapsize;
-	efi.memmap = &memmap;
-
-	efi.systab = (__force void *)ioremap_cache(efi_system_table,
-						   sizeof(efi_system_table_t));
-	if (!efi.systab) {
-		pr_err("Failed to remap EFI System Table\n");
-		return -1;
-	}
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
-	if (!efi_virtmap_init()) {
-		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
-		return -1;
-	}
-
-	/* Set up runtime services function pointers */
-	efi_native_runtime_setup();
-	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-
-	efi.runtime_version = efi.systab->hdr.revision;
-
-	return 0;
-}
-early_initcall(arm64_enable_runtime_services);
 
 static int __init arm64_dmi_init(void)
 {
@@ -328,30 +31,6 @@ static int __init arm64_dmi_init(void)
 }
 core_initcall(arm64_dmi_init);
 
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	if (mm == &init_mm)
-		cpu_set_reserved_ttbr0();
-	else
-		cpu_switch_mm(mm->pgd, mm);
-
-	local_flush_tlb_all();
-	if (icache_is_aivivt())
-		__local_flush_icache_all();
-}
-
-void efi_virtmap_load(void)
-{
-	preempt_disable();
-	efi_set_pgd(&efi_mm);
-}
-
-void efi_virtmap_unload(void)
-{
-	efi_set_pgd(current->active_mm);
-	preempt_enable();
-}
-
 /*
  * UpdateCapsule() depends on the system being shutdown via
  * ResetSystem().
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index ec379a4164cc..f292917b00e7 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
+
+arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
new file mode 100644
index 000000000000..4653d789f10d
--- /dev/null
+++ b/drivers/firmware/efi/arm-init.c
@@ -0,0 +1,196 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013 - 2015 Linaro Ltd.
+ *
+ * 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/init.h>
+#include <linux/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+
+#include <asm/efi.h>
+
+struct efi_memory_map memmap;
+
+u64 efi_system_table;
+
+static int __init is_normal_ram(efi_memory_desc_t *md)
+{
+	if (md->attribute & EFI_MEMORY_WB)
+		return 1;
+	return 0;
+}
+
+/*
+ * 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.
+ */
+static 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;
+}
+
+static int __init uefi_init(void)
+{
+	efi_char16_t *c16;
+	void *config_tables;
+	u64 table_size;
+	char vendor[100] = "unknown";
+	int i, retval;
+
+	efi.systab = early_memremap(efi_system_table,
+				    sizeof(efi_system_table_t));
+	if (efi.systab == NULL) {
+		pr_warn("Unable to map EFI system table.\n");
+		return -ENOMEM;
+	}
+
+	set_bit(EFI_BOOT, &efi.flags);
+	set_bit(EFI_64BIT, &efi.flags);
+
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+		pr_err("System table signature incorrect\n");
+		retval = -EINVAL;
+		goto out;
+	}
+	if ((efi.systab->hdr.revision >> 16) < 2)
+		pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
+			efi.systab->hdr.revision >> 16,
+			efi.systab->hdr.revision & 0xffff);
+
+	/* Show what we know for posterity */
+	c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
+			     sizeof(vendor) * sizeof(efi_char16_t));
+	if (c16) {
+		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	}
+
+	pr_info("EFI v%u.%.02u by %s\n",
+		efi.systab->hdr.revision >> 16,
+		efi.systab->hdr.revision & 0xffff, vendor);
+
+	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,
+					 sizeof(efi_config_table_64_t), NULL);
+
+	early_memunmap(config_tables, table_size);
+out:
+	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+	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:
+	case EFI_PERSISTENT_MEMORY:
+		return 0;
+	default:
+		break;
+	}
+	return is_normal_ram(md);
+}
+
+static __init void reserve_regions(void)
+{
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	if (efi_enabled(EFI_DBG))
+		pr_info("Processing EFI memory map:\n");
+
+	for_each_efi_memory_desc(&memmap, md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		if (efi_enabled(EFI_DBG)) {
+			char buf[64];
+
+			pr_info("  0x%012llx-0x%012llx %s",
+				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
+				efi_md_typeattr_format(buf, sizeof(buf), md));
+		}
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_normal_ram(md))
+			early_init_dt_add_memory_arch(paddr, size);
+
+		if (is_reserve_region(md)) {
+			memblock_mark_nomap(paddr, size);
+			if (efi_enabled(EFI_DBG))
+				pr_cont("*");
+		}
+
+		if (efi_enabled(EFI_DBG))
+			pr_cont("\n");
+	}
+
+	set_bit(EFI_MEMMAP, &efi.flags);
+}
+
+void __init efi_init(void)
+{
+	struct efi_fdt_params params;
+
+	/* Grab UEFI information placed in FDT by stub */
+	if (!efi_get_fdt_params(&params))
+		return;
+
+	efi_system_table = params.system_table;
+
+	memmap.phys_map = params.mmap;
+	memmap.map = early_memremap(params.mmap, params.mmap_size);
+	memmap.map_end = memmap.map + params.mmap_size;
+	memmap.desc_size = params.desc_size;
+	memmap.desc_version = params.desc_ver;
+
+	if (uefi_init() < 0)
+		return;
+
+	reserve_regions();
+	early_memunmap(memmap.map, params.mmap_size);
+	memblock_mark_nomap(params.mmap & PAGE_MASK,
+			    PAGE_ALIGN(params.mmap_size +
+				       (params.mmap & ~PAGE_MASK)));
+}
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
new file mode 100644
index 000000000000..e62ee5df96ca
--- /dev/null
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -0,0 +1,160 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 2.4
+ *
+ * Copyright (C) 2013, 2014 Linaro Ltd.
+ *
+ * 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/memblock.h>
+#include <linux/mm_types.h>
+#include <linux/preempt.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/efi.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+
+static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
+
+extern u64 efi_system_table;
+
+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),
+};
+
+static bool __init efi_virtmap_init(void)
+{
+	efi_memory_desc_t *md;
+
+	for_each_efi_memory_desc(&memmap, md) {
+		u64 paddr, npages, size;
+		pgprot_t prot;
+
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (md->virt_addr == 0)
+			return false;
+
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		pr_info("  EFI remap 0x%016llx => %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->attribute & EFI_MEMORY_WB) == 0)
+			prot = __pgprot(PROT_DEVICE_nGnRE);
+		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+			 !PAGE_ALIGNED(md->phys_addr))
+			prot = PAGE_KERNEL_EXEC;
+		else
+			prot = PAGE_KERNEL;
+
+		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+	}
+	return true;
+}
+
+/*
+ * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
+ * non-early mapping of the UEFI system table and virtual mappings for all
+ * EFI_MEMORY_RUNTIME regions.
+ */
+static int __init arm64_enable_runtime_services(void)
+{
+	u64 mapsize;
+
+	if (!efi_enabled(EFI_BOOT)) {
+		pr_info("EFI services will not be available.\n");
+		return -1;
+	}
+
+	if (efi_runtime_disabled()) {
+		pr_info("EFI runtime services will be disabled.\n");
+		return -1;
+	}
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	mapsize = memmap.map_end - memmap.map;
+	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
+						   mapsize);
+	if (!memmap.map) {
+		pr_err("Failed to remap EFI memory map\n");
+		return -1;
+	}
+	memmap.map_end = memmap.map + mapsize;
+	efi.memmap = &memmap;
+
+	efi.systab = (__force void *)ioremap_cache(efi_system_table,
+						   sizeof(efi_system_table_t));
+	if (!efi.systab) {
+		pr_err("Failed to remap EFI System Table\n");
+		return -1;
+	}
+	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	if (!efi_virtmap_init()) {
+		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
+		return -1;
+	}
+
+	/* Set up runtime services function pointers */
+	efi_native_runtime_setup();
+	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+	efi.runtime_version = efi.systab->hdr.revision;
+
+	return 0;
+}
+early_initcall(arm64_enable_runtime_services);
+
+static void efi_set_pgd(struct mm_struct *mm)
+{
+	if (mm == &init_mm)
+		cpu_set_reserved_ttbr0();
+	else
+		cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
+void efi_virtmap_load(void)
+{
+	preempt_disable();
+	efi_set_pgd(&efi_mm);
+}
+
+void efi_virtmap_unload(void)
+{
+	efi_set_pgd(current->active_mm);
+	preempt_enable();
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

This refactors the EFI init and runtime code that will be shared
between arm64 and ARM so that it can be built for both archs.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm64/include/asm/efi.h       | 16 ++++++
 arch/arm64/kernel/efi.c            | 27 +++++++++
 drivers/firmware/efi/arm-init.c    |  7 ++-
 drivers/firmware/efi/arm-runtime.c | 60 ++++++--------------
 drivers/firmware/efi/efi.c         |  2 +
 5 files changed, 66 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index ef572206f1c3..1ae6f635dc2c 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -2,7 +2,9 @@
 #define _ASM_EFI_H
 
 #include <asm/io.h>
+#include <asm/mmu_context.h>
 #include <asm/neon.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
@@ -10,6 +12,8 @@ extern void efi_init(void);
 #define efi_init()
 #endif
 
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
 #define efi_call_virt(f, ...)						\
 ({									\
 	efi_##f##_t *__f;						\
@@ -63,6 +67,18 @@ extern void efi_init(void);
  *   Services are enabled and the EFI_RUNTIME_SERVICES bit set.
  */
 
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (mm == &init_mm)
+		cpu_set_reserved_ttbr0();
+	else
+		cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
 
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index bd3b2f5adf0c..1e62b5f036c1 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -17,6 +17,33 @@
 
 #include <asm/efi.h>
 
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	u64 paddr, npages, size;
+	pteval_t prot_val;
+
+	paddr = md->phys_addr;
+	npages = md->num_pages;
+	memrange_efi_to_native(&paddr, &npages);
+	size = npages << PAGE_SHIFT;
+
+	/*
+	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+	 * executable, everything else can be mapped with the XN bits
+	 * set.
+	 */
+	if ((md->attribute & EFI_MEMORY_WB) == 0)
+		prot_val = PROT_DEVICE_nGnRE;
+	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+		 !PAGE_ALIGNED(md->phys_addr))
+		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
+	else
+		prot_val = pgprot_val(PAGE_KERNEL);
+
+	create_pgd_mapping(mm, paddr, md->virt_addr, size, __pgprot(prot_val));
+	return 0;
+}
+
 static int __init arm64_dmi_init(void)
 {
 	/*
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 4653d789f10d..11de5cf210c4 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -57,7 +57,7 @@ static int __init uefi_init(void)
 {
 	efi_char16_t *c16;
 	void *config_tables;
-	u64 table_size;
+	size_t table_size;
 	char vendor[100] = "unknown";
 	int i, retval;
 
@@ -69,7 +69,8 @@ static int __init uefi_init(void)
 	}
 
 	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
+	if (IS_ENABLED(CONFIG_64BIT))
+		set_bit(EFI_64BIT, &efi.flags);
 
 	/*
 	 * Verify the EFI Table
@@ -103,7 +104,7 @@ static int __init uefi_init(void)
 				       table_size);
 
 	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-					 sizeof(efi_config_table_64_t), NULL);
+					 sizeof(efi_config_table_t), NULL);
 
 	early_memunmap(config_tables, table_size);
 out:
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index e62ee5df96ca..ad11ba6964f6 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -23,18 +23,15 @@
 
 #include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
+#include <asm/io.h>
 #include <asm/mmu.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
-
 extern u64 efi_system_table;
 
 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),
@@ -46,37 +43,26 @@ static bool __init efi_virtmap_init(void)
 {
 	efi_memory_desc_t *md;
 
+	efi_mm.pgd = pgd_alloc(&efi_mm);
+
 	for_each_efi_memory_desc(&memmap, md) {
-		u64 paddr, npages, size;
-		pgprot_t prot;
+		phys_addr_t phys = (phys_addr_t)md->phys_addr;
+		int ret;
 
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
 		if (md->virt_addr == 0)
 			return false;
 
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		pr_info("  EFI remap 0x%016llx => %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->attribute & EFI_MEMORY_WB) == 0)
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+		ret = efi_create_mapping(&efi_mm, md);
+		if  (!ret) {
+			pr_info("  EFI remap %pa => %p\n",
+				&phys, (void *)(unsigned long)md->virt_addr);
+		} else {
+			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
+				&phys, ret);
+			return false;
+		}
 	}
 	return true;
 }
@@ -86,7 +72,7 @@ static bool __init efi_virtmap_init(void)
  * non-early mapping of the UEFI system table and virtual mappings for all
  * EFI_MEMORY_RUNTIME regions.
  */
-static int __init arm64_enable_runtime_services(void)
+static int __init arm_enable_runtime_services(void)
 {
 	u64 mapsize;
 
@@ -133,19 +119,7 @@ static int __init arm64_enable_runtime_services(void)
 
 	return 0;
 }
-early_initcall(arm64_enable_runtime_services);
-
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	if (mm == &init_mm)
-		cpu_set_reserved_ttbr0();
-	else
-		cpu_switch_mm(mm->pgd, mm);
-
-	flush_tlb_all();
-	if (icache_is_aivivt())
-		__flush_icache_all();
-}
+early_initcall(arm_enable_runtime_services);
 
 void efi_virtmap_load(void)
 {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 027ca212179f..cffa89b3317b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -25,6 +25,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
+#include <asm/efi.h>
+
 struct efi __read_mostly efi = {
 	.mps			= EFI_INVALID_TABLE_ADDR,
 	.acpi			= EFI_INVALID_TABLE_ADDR,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This refactors the EFI init and runtime code that will be shared
between arm64 and ARM so that it can be built for both archs.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/include/asm/efi.h       | 16 ++++++
 arch/arm64/kernel/efi.c            | 27 +++++++++
 drivers/firmware/efi/arm-init.c    |  7 ++-
 drivers/firmware/efi/arm-runtime.c | 60 ++++++--------------
 drivers/firmware/efi/efi.c         |  2 +
 5 files changed, 66 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index ef572206f1c3..1ae6f635dc2c 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -2,7 +2,9 @@
 #define _ASM_EFI_H
 
 #include <asm/io.h>
+#include <asm/mmu_context.h>
 #include <asm/neon.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
@@ -10,6 +12,8 @@ extern void efi_init(void);
 #define efi_init()
 #endif
 
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
 #define efi_call_virt(f, ...)						\
 ({									\
 	efi_##f##_t *__f;						\
@@ -63,6 +67,18 @@ extern void efi_init(void);
  *   Services are enabled and the EFI_RUNTIME_SERVICES bit set.
  */
 
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (mm == &init_mm)
+		cpu_set_reserved_ttbr0();
+	else
+		cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
 
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index bd3b2f5adf0c..1e62b5f036c1 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -17,6 +17,33 @@
 
 #include <asm/efi.h>
 
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	u64 paddr, npages, size;
+	pteval_t prot_val;
+
+	paddr = md->phys_addr;
+	npages = md->num_pages;
+	memrange_efi_to_native(&paddr, &npages);
+	size = npages << PAGE_SHIFT;
+
+	/*
+	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+	 * executable, everything else can be mapped with the XN bits
+	 * set.
+	 */
+	if ((md->attribute & EFI_MEMORY_WB) == 0)
+		prot_val = PROT_DEVICE_nGnRE;
+	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+		 !PAGE_ALIGNED(md->phys_addr))
+		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
+	else
+		prot_val = pgprot_val(PAGE_KERNEL);
+
+	create_pgd_mapping(mm, paddr, md->virt_addr, size, __pgprot(prot_val));
+	return 0;
+}
+
 static int __init arm64_dmi_init(void)
 {
 	/*
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 4653d789f10d..11de5cf210c4 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -57,7 +57,7 @@ static int __init uefi_init(void)
 {
 	efi_char16_t *c16;
 	void *config_tables;
-	u64 table_size;
+	size_t table_size;
 	char vendor[100] = "unknown";
 	int i, retval;
 
@@ -69,7 +69,8 @@ static int __init uefi_init(void)
 	}
 
 	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
+	if (IS_ENABLED(CONFIG_64BIT))
+		set_bit(EFI_64BIT, &efi.flags);
 
 	/*
 	 * Verify the EFI Table
@@ -103,7 +104,7 @@ static int __init uefi_init(void)
 				       table_size);
 
 	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-					 sizeof(efi_config_table_64_t), NULL);
+					 sizeof(efi_config_table_t), NULL);
 
 	early_memunmap(config_tables, table_size);
 out:
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index e62ee5df96ca..ad11ba6964f6 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -23,18 +23,15 @@
 
 #include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
+#include <asm/io.h>
 #include <asm/mmu.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
-
 extern u64 efi_system_table;
 
 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),
@@ -46,37 +43,26 @@ static bool __init efi_virtmap_init(void)
 {
 	efi_memory_desc_t *md;
 
+	efi_mm.pgd = pgd_alloc(&efi_mm);
+
 	for_each_efi_memory_desc(&memmap, md) {
-		u64 paddr, npages, size;
-		pgprot_t prot;
+		phys_addr_t phys = (phys_addr_t)md->phys_addr;
+		int ret;
 
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
 		if (md->virt_addr == 0)
 			return false;
 
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		pr_info("  EFI remap 0x%016llx => %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->attribute & EFI_MEMORY_WB) == 0)
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+		ret = efi_create_mapping(&efi_mm, md);
+		if  (!ret) {
+			pr_info("  EFI remap %pa => %p\n",
+				&phys, (void *)(unsigned long)md->virt_addr);
+		} else {
+			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
+				&phys, ret);
+			return false;
+		}
 	}
 	return true;
 }
@@ -86,7 +72,7 @@ static bool __init efi_virtmap_init(void)
  * non-early mapping of the UEFI system table and virtual mappings for all
  * EFI_MEMORY_RUNTIME regions.
  */
-static int __init arm64_enable_runtime_services(void)
+static int __init arm_enable_runtime_services(void)
 {
 	u64 mapsize;
 
@@ -133,19 +119,7 @@ static int __init arm64_enable_runtime_services(void)
 
 	return 0;
 }
-early_initcall(arm64_enable_runtime_services);
-
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	if (mm == &init_mm)
-		cpu_set_reserved_ttbr0();
-	else
-		cpu_switch_mm(mm->pgd, mm);
-
-	flush_tlb_all();
-	if (icache_is_aivivt())
-		__flush_icache_all();
-}
+early_initcall(arm_enable_runtime_services);
 
 void efi_virtmap_load(void)
 {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 027ca212179f..cffa89b3317b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -25,6 +25,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
+#include <asm/efi.h>
+
 struct efi __read_mostly efi = {
 	.mps			= EFI_INVALID_TABLE_ADDR,
 	.acpi			= EFI_INVALID_TABLE_ADDR,
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This refactors the EFI init and runtime code that will be shared
between arm64 and ARM so that it can be built for both archs.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/include/asm/efi.h       | 16 ++++++
 arch/arm64/kernel/efi.c            | 27 +++++++++
 drivers/firmware/efi/arm-init.c    |  7 ++-
 drivers/firmware/efi/arm-runtime.c | 60 ++++++--------------
 drivers/firmware/efi/efi.c         |  2 +
 5 files changed, 66 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index ef572206f1c3..1ae6f635dc2c 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -2,7 +2,9 @@
 #define _ASM_EFI_H
 
 #include <asm/io.h>
+#include <asm/mmu_context.h>
 #include <asm/neon.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
@@ -10,6 +12,8 @@ extern void efi_init(void);
 #define efi_init()
 #endif
 
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
 #define efi_call_virt(f, ...)						\
 ({									\
 	efi_##f##_t *__f;						\
@@ -63,6 +67,18 @@ extern void efi_init(void);
  *   Services are enabled and the EFI_RUNTIME_SERVICES bit set.
  */
 
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (mm == &init_mm)
+		cpu_set_reserved_ttbr0();
+	else
+		cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
 
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index bd3b2f5adf0c..1e62b5f036c1 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -17,6 +17,33 @@
 
 #include <asm/efi.h>
 
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	u64 paddr, npages, size;
+	pteval_t prot_val;
+
+	paddr = md->phys_addr;
+	npages = md->num_pages;
+	memrange_efi_to_native(&paddr, &npages);
+	size = npages << PAGE_SHIFT;
+
+	/*
+	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+	 * executable, everything else can be mapped with the XN bits
+	 * set.
+	 */
+	if ((md->attribute & EFI_MEMORY_WB) == 0)
+		prot_val = PROT_DEVICE_nGnRE;
+	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+		 !PAGE_ALIGNED(md->phys_addr))
+		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
+	else
+		prot_val = pgprot_val(PAGE_KERNEL);
+
+	create_pgd_mapping(mm, paddr, md->virt_addr, size, __pgprot(prot_val));
+	return 0;
+}
+
 static int __init arm64_dmi_init(void)
 {
 	/*
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 4653d789f10d..11de5cf210c4 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -57,7 +57,7 @@ static int __init uefi_init(void)
 {
 	efi_char16_t *c16;
 	void *config_tables;
-	u64 table_size;
+	size_t table_size;
 	char vendor[100] = "unknown";
 	int i, retval;
 
@@ -69,7 +69,8 @@ static int __init uefi_init(void)
 	}
 
 	set_bit(EFI_BOOT, &efi.flags);
-	set_bit(EFI_64BIT, &efi.flags);
+	if (IS_ENABLED(CONFIG_64BIT))
+		set_bit(EFI_64BIT, &efi.flags);
 
 	/*
 	 * Verify the EFI Table
@@ -103,7 +104,7 @@ static int __init uefi_init(void)
 				       table_size);
 
 	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-					 sizeof(efi_config_table_64_t), NULL);
+					 sizeof(efi_config_table_t), NULL);
 
 	early_memunmap(config_tables, table_size);
 out:
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index e62ee5df96ca..ad11ba6964f6 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -23,18 +23,15 @@
 
 #include <asm/cacheflush.h>
 #include <asm/efi.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
+#include <asm/io.h>
 #include <asm/mmu.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
-
 extern u64 efi_system_table;
 
 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),
@@ -46,37 +43,26 @@ static bool __init efi_virtmap_init(void)
 {
 	efi_memory_desc_t *md;
 
+	efi_mm.pgd = pgd_alloc(&efi_mm);
+
 	for_each_efi_memory_desc(&memmap, md) {
-		u64 paddr, npages, size;
-		pgprot_t prot;
+		phys_addr_t phys = (phys_addr_t)md->phys_addr;
+		int ret;
 
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
 		if (md->virt_addr == 0)
 			return false;
 
-		paddr = md->phys_addr;
-		npages = md->num_pages;
-		memrange_efi_to_native(&paddr, &npages);
-		size = npages << PAGE_SHIFT;
-
-		pr_info("  EFI remap 0x%016llx => %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->attribute & EFI_MEMORY_WB) == 0)
-			prot = __pgprot(PROT_DEVICE_nGnRE);
-		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-			 !PAGE_ALIGNED(md->phys_addr))
-			prot = PAGE_KERNEL_EXEC;
-		else
-			prot = PAGE_KERNEL;
-
-		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+		ret = efi_create_mapping(&efi_mm, md);
+		if  (!ret) {
+			pr_info("  EFI remap %pa => %p\n",
+				&phys, (void *)(unsigned long)md->virt_addr);
+		} else {
+			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
+				&phys, ret);
+			return false;
+		}
 	}
 	return true;
 }
@@ -86,7 +72,7 @@ static bool __init efi_virtmap_init(void)
  * non-early mapping of the UEFI system table and virtual mappings for all
  * EFI_MEMORY_RUNTIME regions.
  */
-static int __init arm64_enable_runtime_services(void)
+static int __init arm_enable_runtime_services(void)
 {
 	u64 mapsize;
 
@@ -133,19 +119,7 @@ static int __init arm64_enable_runtime_services(void)
 
 	return 0;
 }
-early_initcall(arm64_enable_runtime_services);
-
-static void efi_set_pgd(struct mm_struct *mm)
-{
-	if (mm == &init_mm)
-		cpu_set_reserved_ttbr0();
-	else
-		cpu_switch_mm(mm->pgd, mm);
-
-	flush_tlb_all();
-	if (icache_is_aivivt())
-		__flush_icache_all();
-}
+early_initcall(arm_enable_runtime_services);
 
 void efi_virtmap_load(void)
 {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 027ca212179f..cffa89b3317b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -25,6 +25,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
+#include <asm/efi.h>
+
 struct efi __read_mostly efi = {
 	.mps			= EFI_INVALID_TABLE_ADDR,
 	.acpi			= EFI_INVALID_TABLE_ADDR,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 06/12] ARM: add support for generic early_ioremap/early_memremap
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

This enables the generic early_ioremap implementation for ARM.

It uses the fixmap region reserved for kmap. Since early_ioremap
is only supported before paging_init(), and kmap is only supported
afterwards, this is guaranteed not to cause any clashes.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/Kconfig              |  1 +
 arch/arm/include/asm/Kbuild   |  1 +
 arch/arm/include/asm/fixmap.h | 29 +++++++++++++++++++-
 arch/arm/kernel/setup.c       |  7 +++--
 arch/arm/mm/ioremap.c         |  9 ++++++
 arch/arm/mm/mmu.c             |  2 +-
 6 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0365cbbc9179..7e338228cc8d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -20,6 +20,7 @@ config ARM
 	select GENERIC_ALLOCATOR
 	select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_EARLY_IOREMAP
 	select GENERIC_IDLE_POLL_SETUP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index bd425302c97a..16da6380eb85 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -3,6 +3,7 @@
 generic-y += bitsperlong.h
 generic-y += cputime.h
 generic-y += current.h
+generic-y += early_ioremap.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 58cfe9f1a687..5c17d2dec777 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -19,20 +19,47 @@ enum fixed_addresses {
 	FIX_TEXT_POKE0,
 	FIX_TEXT_POKE1,
 
-	__end_of_fixed_addresses
+	__end_of_fixmap_region,
+
+	/*
+	 * Share the kmap() region with early_ioremap(): this is guaranteed
+	 * not to clash since early_ioremap() is only available before
+	 * paging_init(), and kmap() only after.
+	 */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+	__end_of_early_ioremap_region
 };
 
+static const enum fixed_addresses __end_of_fixed_addresses =
+	__end_of_fixmap_region > __end_of_early_ioremap_region ?
+	__end_of_fixmap_region : __end_of_early_ioremap_region;
+
 #define FIXMAP_PAGE_COMMON	(L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
 
 #define FIXMAP_PAGE_NORMAL	(FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
+#define FIXMAP_PAGE_RO		(FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
 
 /* Used by set_fixmap_(io|nocache), both meant for mapping a device */
 #define FIXMAP_PAGE_IO		(FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_SHARED | L_PTE_SHARED)
 #define FIXMAP_PAGE_NOCACHE	FIXMAP_PAGE_IO
 
+#define __early_set_fixmap	__set_fixmap
+
+#ifdef CONFIG_MMU
+
 void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
 void __init early_fixmap_init(void);
 
 #include <asm-generic/fixmap.h>
 
+#else
+
+static inline void early_fixmap_init(void) { }
+
+#endif
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 20edd349d379..5df2bca57c42 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -38,6 +38,7 @@
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
+#include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
 #include <asm/procinfo.h>
 #include <asm/psci.h>
@@ -956,8 +957,8 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = cmd_line;
 
-	if (IS_ENABLED(CONFIG_FIX_EARLYCON_MEM))
-		early_fixmap_init();
+	early_fixmap_init();
+	early_ioremap_init();
 
 	parse_early_param();
 
@@ -968,6 +969,8 @@ void __init setup_arch(char **cmdline_p)
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
+	early_ioremap_reset();
+
 	paging_init(mdesc);
 	request_standard_resources(mdesc);
 
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 0c81056c1dd7..66a978d05958 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -30,6 +30,7 @@
 #include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
+#include <asm/early_ioremap.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -469,3 +470,11 @@ int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_io);
 #endif
+
+/*
+ * Must be called after early_fixmap_init
+ */
+void __init early_ioremap_init(void)
+{
+	early_ioremap_setup();
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4867f5daf82c..de19f90221e2 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -390,7 +390,7 @@ void __init early_fixmap_init(void)
 	 * The early fixmap range spans multiple pmds, for which
 	 * we are not prepared:
 	 */
-	BUILD_BUG_ON((__fix_to_virt(__end_of_permanent_fixed_addresses) >> PMD_SHIFT)
+	BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
 		     != FIXADDR_TOP >> PMD_SHIFT);
 
 	pmd = fixmap_pmd(FIXADDR_TOP);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 06/12] ARM: add support for generic early_ioremap/early_memremap
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This enables the generic early_ioremap implementation for ARM.

It uses the fixmap region reserved for kmap. Since early_ioremap
is only supported before paging_init(), and kmap is only supported
afterwards, this is guaranteed not to cause any clashes.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/Kconfig              |  1 +
 arch/arm/include/asm/Kbuild   |  1 +
 arch/arm/include/asm/fixmap.h | 29 +++++++++++++++++++-
 arch/arm/kernel/setup.c       |  7 +++--
 arch/arm/mm/ioremap.c         |  9 ++++++
 arch/arm/mm/mmu.c             |  2 +-
 6 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0365cbbc9179..7e338228cc8d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -20,6 +20,7 @@ config ARM
 	select GENERIC_ALLOCATOR
 	select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_EARLY_IOREMAP
 	select GENERIC_IDLE_POLL_SETUP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index bd425302c97a..16da6380eb85 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -3,6 +3,7 @@
 generic-y += bitsperlong.h
 generic-y += cputime.h
 generic-y += current.h
+generic-y += early_ioremap.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 58cfe9f1a687..5c17d2dec777 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -19,20 +19,47 @@ enum fixed_addresses {
 	FIX_TEXT_POKE0,
 	FIX_TEXT_POKE1,
 
-	__end_of_fixed_addresses
+	__end_of_fixmap_region,
+
+	/*
+	 * Share the kmap() region with early_ioremap(): this is guaranteed
+	 * not to clash since early_ioremap() is only available before
+	 * paging_init(), and kmap() only after.
+	 */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+	__end_of_early_ioremap_region
 };
 
+static const enum fixed_addresses __end_of_fixed_addresses =
+	__end_of_fixmap_region > __end_of_early_ioremap_region ?
+	__end_of_fixmap_region : __end_of_early_ioremap_region;
+
 #define FIXMAP_PAGE_COMMON	(L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
 
 #define FIXMAP_PAGE_NORMAL	(FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
+#define FIXMAP_PAGE_RO		(FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
 
 /* Used by set_fixmap_(io|nocache), both meant for mapping a device */
 #define FIXMAP_PAGE_IO		(FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_SHARED | L_PTE_SHARED)
 #define FIXMAP_PAGE_NOCACHE	FIXMAP_PAGE_IO
 
+#define __early_set_fixmap	__set_fixmap
+
+#ifdef CONFIG_MMU
+
 void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
 void __init early_fixmap_init(void);
 
 #include <asm-generic/fixmap.h>
 
+#else
+
+static inline void early_fixmap_init(void) { }
+
+#endif
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 20edd349d379..5df2bca57c42 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -38,6 +38,7 @@
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
+#include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
 #include <asm/procinfo.h>
 #include <asm/psci.h>
@@ -956,8 +957,8 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = cmd_line;
 
-	if (IS_ENABLED(CONFIG_FIX_EARLYCON_MEM))
-		early_fixmap_init();
+	early_fixmap_init();
+	early_ioremap_init();
 
 	parse_early_param();
 
@@ -968,6 +969,8 @@ void __init setup_arch(char **cmdline_p)
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
+	early_ioremap_reset();
+
 	paging_init(mdesc);
 	request_standard_resources(mdesc);
 
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 0c81056c1dd7..66a978d05958 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -30,6 +30,7 @@
 #include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
+#include <asm/early_ioremap.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -469,3 +470,11 @@ int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_io);
 #endif
+
+/*
+ * Must be called after early_fixmap_init
+ */
+void __init early_ioremap_init(void)
+{
+	early_ioremap_setup();
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4867f5daf82c..de19f90221e2 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -390,7 +390,7 @@ void __init early_fixmap_init(void)
 	 * The early fixmap range spans multiple pmds, for which
 	 * we are not prepared:
 	 */
-	BUILD_BUG_ON((__fix_to_virt(__end_of_permanent_fixed_addresses) >> PMD_SHIFT)
+	BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
 		     != FIXADDR_TOP >> PMD_SHIFT);
 
 	pmd = fixmap_pmd(FIXADDR_TOP);
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 06/12] ARM: add support for generic early_ioremap/early_memremap
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This enables the generic early_ioremap implementation for ARM.

It uses the fixmap region reserved for kmap. Since early_ioremap
is only supported before paging_init(), and kmap is only supported
afterwards, this is guaranteed not to cause any clashes.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/Kconfig              |  1 +
 arch/arm/include/asm/Kbuild   |  1 +
 arch/arm/include/asm/fixmap.h | 29 +++++++++++++++++++-
 arch/arm/kernel/setup.c       |  7 +++--
 arch/arm/mm/ioremap.c         |  9 ++++++
 arch/arm/mm/mmu.c             |  2 +-
 6 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0365cbbc9179..7e338228cc8d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -20,6 +20,7 @@ config ARM
 	select GENERIC_ALLOCATOR
 	select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_EARLY_IOREMAP
 	select GENERIC_IDLE_POLL_SETUP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index bd425302c97a..16da6380eb85 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -3,6 +3,7 @@
 generic-y += bitsperlong.h
 generic-y += cputime.h
 generic-y += current.h
+generic-y += early_ioremap.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index 58cfe9f1a687..5c17d2dec777 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -19,20 +19,47 @@ enum fixed_addresses {
 	FIX_TEXT_POKE0,
 	FIX_TEXT_POKE1,
 
-	__end_of_fixed_addresses
+	__end_of_fixmap_region,
+
+	/*
+	 * Share the kmap() region with early_ioremap(): this is guaranteed
+	 * not to clash since early_ioremap() is only available before
+	 * paging_init(), and kmap() only after.
+	 */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+	__end_of_early_ioremap_region
 };
 
+static const enum fixed_addresses __end_of_fixed_addresses =
+	__end_of_fixmap_region > __end_of_early_ioremap_region ?
+	__end_of_fixmap_region : __end_of_early_ioremap_region;
+
 #define FIXMAP_PAGE_COMMON	(L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN | L_PTE_DIRTY)
 
 #define FIXMAP_PAGE_NORMAL	(FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK)
+#define FIXMAP_PAGE_RO		(FIXMAP_PAGE_NORMAL | L_PTE_RDONLY)
 
 /* Used by set_fixmap_(io|nocache), both meant for mapping a device */
 #define FIXMAP_PAGE_IO		(FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_SHARED | L_PTE_SHARED)
 #define FIXMAP_PAGE_NOCACHE	FIXMAP_PAGE_IO
 
+#define __early_set_fixmap	__set_fixmap
+
+#ifdef CONFIG_MMU
+
 void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
 void __init early_fixmap_init(void);
 
 #include <asm-generic/fixmap.h>
 
+#else
+
+static inline void early_fixmap_init(void) { }
+
+#endif
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 20edd349d379..5df2bca57c42 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -38,6 +38,7 @@
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
+#include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
 #include <asm/procinfo.h>
 #include <asm/psci.h>
@@ -956,8 +957,8 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = cmd_line;
 
-	if (IS_ENABLED(CONFIG_FIX_EARLYCON_MEM))
-		early_fixmap_init();
+	early_fixmap_init();
+	early_ioremap_init();
 
 	parse_early_param();
 
@@ -968,6 +969,8 @@ void __init setup_arch(char **cmdline_p)
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
+	early_ioremap_reset();
+
 	paging_init(mdesc);
 	request_standard_resources(mdesc);
 
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 0c81056c1dd7..66a978d05958 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -30,6 +30,7 @@
 #include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
+#include <asm/early_ioremap.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -469,3 +470,11 @@ int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_io);
 #endif
+
+/*
+ * Must be called after early_fixmap_init
+ */
+void __init early_ioremap_init(void)
+{
+	early_ioremap_setup();
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4867f5daf82c..de19f90221e2 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -390,7 +390,7 @@ void __init early_fixmap_init(void)
 	 * The early fixmap range spans multiple pmds, for which
 	 * we are not prepared:
 	 */
-	BUILD_BUG_ON((__fix_to_virt(__end_of_permanent_fixed_addresses) >> PMD_SHIFT)
+	BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
 		     != FIXADDR_TOP >> PMD_SHIFT);
 
 	pmd = fixmap_pmd(FIXADDR_TOP);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

In order to be able to reuse the core mapping logic of create_mapping
for mapping the UEFI Runtime Services into a private set of page tables,
split it off from create_mapping() into a separate function
__create_mapping which we will wire up in a subsequent patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/mm/mmu.c | 56 +++++++++++---------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index de19f90221e2..3100de92148b 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -818,7 +818,8 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 }
 
 #ifndef CONFIG_ARM_LPAE
-static void __init create_36bit_mapping(struct map_desc *md,
+static void __init create_36bit_mapping(struct mm_struct *mm,
+					struct map_desc *md,
 					const struct mem_type *type)
 {
 	unsigned long addr, length, end;
@@ -859,7 +860,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
 	 */
 	phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		pud_t *pud = pud_offset(pgd, addr);
@@ -876,33 +877,13 @@ static void __init create_36bit_mapping(struct map_desc *md,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'.  We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections and
- * supersections.
- */
-static void __init create_mapping(struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
 	const struct mem_type *type;
 	pgd_t *pgd;
 
-	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-		pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-		return;
-	}
-
-	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
-	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
-	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
-		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-	}
-
 	type = &mem_types[md->type];
 
 #ifndef CONFIG_ARM_LPAE
@@ -910,7 +891,7 @@ static void __init create_mapping(struct map_desc *md)
 	 * Catch 36-bit addresses
 	 */
 	if (md->pfn >= 0x100000) {
-		create_36bit_mapping(md, type);
+		create_36bit_mapping(mm, md, type);
 		return;
 	}
 #endif
@@ -925,7 +906,7 @@ static void __init create_mapping(struct map_desc *md)
 		return;
 	}
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
@@ -938,6 +919,31 @@ static void __init create_mapping(struct map_desc *md)
 }
 
 /*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections and
+ * supersections.
+ */
+static void __init create_mapping(struct map_desc *md)
+{
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
+	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
+		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	__create_mapping(&init_mm, md);
+}
+
+/*
  * Create the architecture specific mappings
  */
 void __init iotable_init(struct map_desc *io_desc, int nr)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

In order to be able to reuse the core mapping logic of create_mapping
for mapping the UEFI Runtime Services into a private set of page tables,
split it off from create_mapping() into a separate function
__create_mapping which we will wire up in a subsequent patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/mmu.c | 56 +++++++++++---------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index de19f90221e2..3100de92148b 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -818,7 +818,8 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 }
 
 #ifndef CONFIG_ARM_LPAE
-static void __init create_36bit_mapping(struct map_desc *md,
+static void __init create_36bit_mapping(struct mm_struct *mm,
+					struct map_desc *md,
 					const struct mem_type *type)
 {
 	unsigned long addr, length, end;
@@ -859,7 +860,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
 	 */
 	phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		pud_t *pud = pud_offset(pgd, addr);
@@ -876,33 +877,13 @@ static void __init create_36bit_mapping(struct map_desc *md,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'.  We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections and
- * supersections.
- */
-static void __init create_mapping(struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
 	const struct mem_type *type;
 	pgd_t *pgd;
 
-	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-		pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-		return;
-	}
-
-	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
-	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
-	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
-		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-	}
-
 	type = &mem_types[md->type];
 
 #ifndef CONFIG_ARM_LPAE
@@ -910,7 +891,7 @@ static void __init create_mapping(struct map_desc *md)
 	 * Catch 36-bit addresses
 	 */
 	if (md->pfn >= 0x100000) {
-		create_36bit_mapping(md, type);
+		create_36bit_mapping(mm, md, type);
 		return;
 	}
 #endif
@@ -925,7 +906,7 @@ static void __init create_mapping(struct map_desc *md)
 		return;
 	}
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
@@ -938,6 +919,31 @@ static void __init create_mapping(struct map_desc *md)
 }
 
 /*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections and
+ * supersections.
+ */
+static void __init create_mapping(struct map_desc *md)
+{
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
+	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
+		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	__create_mapping(&init_mm, md);
+}
+
+/*
  * Create the architecture specific mappings
  */
 void __init iotable_init(struct map_desc *io_desc, int nr)
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

In order to be able to reuse the core mapping logic of create_mapping
for mapping the UEFI Runtime Services into a private set of page tables,
split it off from create_mapping() into a separate function
__create_mapping which we will wire up in a subsequent patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/mmu.c | 56 +++++++++++---------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index de19f90221e2..3100de92148b 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -818,7 +818,8 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 }
 
 #ifndef CONFIG_ARM_LPAE
-static void __init create_36bit_mapping(struct map_desc *md,
+static void __init create_36bit_mapping(struct mm_struct *mm,
+					struct map_desc *md,
 					const struct mem_type *type)
 {
 	unsigned long addr, length, end;
@@ -859,7 +860,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
 	 */
 	phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		pud_t *pud = pud_offset(pgd, addr);
@@ -876,33 +877,13 @@ static void __init create_36bit_mapping(struct map_desc *md,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'.  We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections and
- * supersections.
- */
-static void __init create_mapping(struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
 	const struct mem_type *type;
 	pgd_t *pgd;
 
-	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-		pr_warn("BUG: not creating mapping for 0x%08llx@0x%08lx in user region\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-		return;
-	}
-
-	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
-	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
-	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
-		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
-			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
-	}
-
 	type = &mem_types[md->type];
 
 #ifndef CONFIG_ARM_LPAE
@@ -910,7 +891,7 @@ static void __init create_mapping(struct map_desc *md)
 	 * Catch 36-bit addresses
 	 */
 	if (md->pfn >= 0x100000) {
-		create_36bit_mapping(md, type);
+		create_36bit_mapping(mm, md, type);
 		return;
 	}
 #endif
@@ -925,7 +906,7 @@ static void __init create_mapping(struct map_desc *md)
 		return;
 	}
 
-	pgd = pgd_offset_k(addr);
+	pgd = pgd_offset(mm, addr);
 	end = addr + length;
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
@@ -938,6 +919,31 @@ static void __init create_mapping(struct map_desc *md)
 }
 
 /*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections and
+ * supersections.
+ */
+static void __init create_mapping(struct map_desc *md)
+{
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		pr_warn("BUG: not creating mapping for 0x%08llx@0x%08lx in user region\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
+	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
+		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
+			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	__create_mapping(&init_mm, md);
+}
+
+/*
  * Create the architecture specific mappings
  */
 void __init iotable_init(struct map_desc *io_desc, int nr)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 08/12] ARM: factor out allocation routine from __create_mapping()
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

To allow __create_mapping() to be used for populating UEFI Runtime
Services page tables, factor out the allocation routine 'early_alloc'
and pass it down as a function pointer into alloc_init_[pud|pmd|pte].
This way, new users of __create_mapping() can supply another allocation
function.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/mm/mmu.c | 34 +++++++++++++-------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 3100de92148b..87dc49dbe231 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,21 +724,30 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
-static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
+static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
+				unsigned long prot,
+				void *(*alloc)(unsigned long sz))
 {
 	if (pmd_none(*pmd)) {
-		pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+		pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
 		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));
 	return pte_offset_kernel(pmd, addr);
 }
 
+static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
+				      unsigned long prot)
+{
+	return pte_alloc(pmd, addr, prot, early_alloc);
+}
+
 static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
-	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
+	pte_t *pte = pte_alloc(pmd, addr, type->prot_l1, alloc);
 	do {
 		set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
 		pfn++;
@@ -774,7 +783,8 @@ static void __init __map_init_section(pmd_t *pmd, unsigned long addr,
 
 static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 				      unsigned long end, phys_addr_t phys,
-				      const struct mem_type *type)
+				      const struct mem_type *type,
+				      void *(*alloc)(unsigned long sz))
 {
 	pmd_t *pmd = pmd_offset(pud, addr);
 	unsigned long next;
@@ -795,7 +805,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 			__map_init_section(pmd, addr, next, phys, type);
 		} else {
 			alloc_init_pte(pmd, addr, next,
-						__phys_to_pfn(phys), type);
+				       __phys_to_pfn(phys), type, alloc);
 		}
 
 		phys += next - addr;
@@ -805,14 +815,15 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 				  unsigned long end, phys_addr_t phys,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_pmd(pud, addr, next, phys, type);
+		alloc_init_pmd(pud, addr, next, phys, type, alloc);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
@@ -877,7 +888,8 @@ static void __init create_36bit_mapping(struct mm_struct *mm,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md,
+				    void *(*alloc)(unsigned long sz))
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
@@ -911,7 +923,7 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
 
-		alloc_init_pud(pgd, addr, next, phys, type);
+		alloc_init_pud(pgd, addr, next, phys, type, alloc);
 
 		phys += next - addr;
 		addr = next;
@@ -940,7 +952,7 @@ static void __init create_mapping(struct map_desc *md)
 			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
 	}
 
-	__create_mapping(&init_mm, md);
+	__create_mapping(&init_mm, md, early_alloc);
 }
 
 /*
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 08/12] ARM: factor out allocation routine from __create_mapping()
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

To allow __create_mapping() to be used for populating UEFI Runtime
Services page tables, factor out the allocation routine 'early_alloc'
and pass it down as a function pointer into alloc_init_[pud|pmd|pte].
This way, new users of __create_mapping() can supply another allocation
function.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/mmu.c | 34 +++++++++++++-------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 3100de92148b..87dc49dbe231 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,21 +724,30 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
-static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
+static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
+				unsigned long prot,
+				void *(*alloc)(unsigned long sz))
 {
 	if (pmd_none(*pmd)) {
-		pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+		pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
 		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));
 	return pte_offset_kernel(pmd, addr);
 }
 
+static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
+				      unsigned long prot)
+{
+	return pte_alloc(pmd, addr, prot, early_alloc);
+}
+
 static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
-	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
+	pte_t *pte = pte_alloc(pmd, addr, type->prot_l1, alloc);
 	do {
 		set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
 		pfn++;
@@ -774,7 +783,8 @@ static void __init __map_init_section(pmd_t *pmd, unsigned long addr,
 
 static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 				      unsigned long end, phys_addr_t phys,
-				      const struct mem_type *type)
+				      const struct mem_type *type,
+				      void *(*alloc)(unsigned long sz))
 {
 	pmd_t *pmd = pmd_offset(pud, addr);
 	unsigned long next;
@@ -795,7 +805,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 			__map_init_section(pmd, addr, next, phys, type);
 		} else {
 			alloc_init_pte(pmd, addr, next,
-						__phys_to_pfn(phys), type);
+				       __phys_to_pfn(phys), type, alloc);
 		}
 
 		phys += next - addr;
@@ -805,14 +815,15 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 				  unsigned long end, phys_addr_t phys,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_pmd(pud, addr, next, phys, type);
+		alloc_init_pmd(pud, addr, next, phys, type, alloc);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
@@ -877,7 +888,8 @@ static void __init create_36bit_mapping(struct mm_struct *mm,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md,
+				    void *(*alloc)(unsigned long sz))
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
@@ -911,7 +923,7 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
 
-		alloc_init_pud(pgd, addr, next, phys, type);
+		alloc_init_pud(pgd, addr, next, phys, type, alloc);
 
 		phys += next - addr;
 		addr = next;
@@ -940,7 +952,7 @@ static void __init create_mapping(struct map_desc *md)
 			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
 	}
 
-	__create_mapping(&init_mm, md);
+	__create_mapping(&init_mm, md, early_alloc);
 }
 
 /*
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 08/12] ARM: factor out allocation routine from __create_mapping()
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

To allow __create_mapping() to be used for populating UEFI Runtime
Services page tables, factor out the allocation routine 'early_alloc'
and pass it down as a function pointer into alloc_init_[pud|pmd|pte].
This way, new users of __create_mapping() can supply another allocation
function.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/mmu.c | 34 +++++++++++++-------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 3100de92148b..87dc49dbe231 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,21 +724,30 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
-static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
+static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
+				unsigned long prot,
+				void *(*alloc)(unsigned long sz))
 {
 	if (pmd_none(*pmd)) {
-		pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+		pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
 		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));
 	return pte_offset_kernel(pmd, addr);
 }
 
+static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
+				      unsigned long prot)
+{
+	return pte_alloc(pmd, addr, prot, early_alloc);
+}
+
 static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
-	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
+	pte_t *pte = pte_alloc(pmd, addr, type->prot_l1, alloc);
 	do {
 		set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
 		pfn++;
@@ -774,7 +783,8 @@ static void __init __map_init_section(pmd_t *pmd, unsigned long addr,
 
 static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 				      unsigned long end, phys_addr_t phys,
-				      const struct mem_type *type)
+				      const struct mem_type *type,
+				      void *(*alloc)(unsigned long sz))
 {
 	pmd_t *pmd = pmd_offset(pud, addr);
 	unsigned long next;
@@ -795,7 +805,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 			__map_init_section(pmd, addr, next, phys, type);
 		} else {
 			alloc_init_pte(pmd, addr, next,
-						__phys_to_pfn(phys), type);
+				       __phys_to_pfn(phys), type, alloc);
 		}
 
 		phys += next - addr;
@@ -805,14 +815,15 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 				  unsigned long end, phys_addr_t phys,
-				  const struct mem_type *type)
+				  const struct mem_type *type,
+				  void *(*alloc)(unsigned long sz))
 {
 	pud_t *pud = pud_offset(pgd, addr);
 	unsigned long next;
 
 	do {
 		next = pud_addr_end(addr, end);
-		alloc_init_pmd(pud, addr, next, phys, type);
+		alloc_init_pmd(pud, addr, next, phys, type, alloc);
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
 }
@@ -877,7 +888,8 @@ static void __init create_36bit_mapping(struct mm_struct *mm,
 }
 #endif	/* !CONFIG_ARM_LPAE */
 
-static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
+static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md,
+				    void *(*alloc)(unsigned long sz))
 {
 	unsigned long addr, length, end;
 	phys_addr_t phys;
@@ -911,7 +923,7 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md)
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
 
-		alloc_init_pud(pgd, addr, next, phys, type);
+		alloc_init_pud(pgd, addr, next, phys, type, alloc);
 
 		phys += next - addr;
 		addr = next;
@@ -940,7 +952,7 @@ static void __init create_mapping(struct map_desc *md)
 			(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
 	}
 
-	__create_mapping(&init_mm, md);
+	__create_mapping(&init_mm, md, early_alloc);
 }
 
 /*
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 09/12] ARM: implement create_mapping_late() for EFI use
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

This implements create_mapping_late(), which we will use to populate
the UEFI Runtime Services page tables.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/include/asm/mach/map.h |  1 +
 arch/arm/mm/mmu.c               | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index f98c7f32c9c8..14fe67bd0272 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -42,6 +42,7 @@ enum {
 extern void iotable_init(struct map_desc *, int);
 extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
 				  void *caller);
+extern void create_mapping_late(struct mm_struct *mm, struct map_desc *md);
 
 #ifdef CONFIG_DEBUG_LL
 extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 87dc49dbe231..0b7b61e31bc3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,6 +724,14 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
+static void *__init late_alloc(unsigned long sz)
+{
+	void *ptr = (void *)__get_free_pages(PGALLOC_GFP, get_order(sz));
+
+	BUG_ON(!ptr);
+	return ptr;
+}
+
 static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
 				unsigned long prot,
 				void *(*alloc)(unsigned long sz))
@@ -955,6 +963,17 @@ static void __init create_mapping(struct map_desc *md)
 	__create_mapping(&init_mm, md, early_alloc);
 }
 
+void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md)
+{
+#ifdef CONFIG_ARM_LPAE
+	pud_t *pud = pud_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
+	if (WARN_ON(!pud))
+		return;
+	pmd_alloc(mm, pud, 0);
+#endif
+	__create_mapping(mm, md, late_alloc);
+}
+
 /*
  * Create the architecture specific mappings
  */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 09/12] ARM: implement create_mapping_late() for EFI use
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This implements create_mapping_late(), which we will use to populate
the UEFI Runtime Services page tables.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/include/asm/mach/map.h |  1 +
 arch/arm/mm/mmu.c               | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index f98c7f32c9c8..14fe67bd0272 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -42,6 +42,7 @@ enum {
 extern void iotable_init(struct map_desc *, int);
 extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
 				  void *caller);
+extern void create_mapping_late(struct mm_struct *mm, struct map_desc *md);
 
 #ifdef CONFIG_DEBUG_LL
 extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 87dc49dbe231..0b7b61e31bc3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,6 +724,14 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
+static void *__init late_alloc(unsigned long sz)
+{
+	void *ptr = (void *)__get_free_pages(PGALLOC_GFP, get_order(sz));
+
+	BUG_ON(!ptr);
+	return ptr;
+}
+
 static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
 				unsigned long prot,
 				void *(*alloc)(unsigned long sz))
@@ -955,6 +963,17 @@ static void __init create_mapping(struct map_desc *md)
 	__create_mapping(&init_mm, md, early_alloc);
 }
 
+void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md)
+{
+#ifdef CONFIG_ARM_LPAE
+	pud_t *pud = pud_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
+	if (WARN_ON(!pud))
+		return;
+	pmd_alloc(mm, pud, 0);
+#endif
+	__create_mapping(mm, md, late_alloc);
+}
+
 /*
  * Create the architecture specific mappings
  */
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 09/12] ARM: implement create_mapping_late() for EFI use
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This implements create_mapping_late(), which we will use to populate
the UEFI Runtime Services page tables.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/include/asm/mach/map.h |  1 +
 arch/arm/mm/mmu.c               | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index f98c7f32c9c8..14fe67bd0272 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -42,6 +42,7 @@ enum {
 extern void iotable_init(struct map_desc *, int);
 extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
 				  void *caller);
+extern void create_mapping_late(struct mm_struct *mm, struct map_desc *md);
 
 #ifdef CONFIG_DEBUG_LL
 extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 87dc49dbe231..0b7b61e31bc3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -724,6 +724,14 @@ static void __init *early_alloc(unsigned long sz)
 	return early_alloc_aligned(sz, sz);
 }
 
+static void *__init late_alloc(unsigned long sz)
+{
+	void *ptr = (void *)__get_free_pages(PGALLOC_GFP, get_order(sz));
+
+	BUG_ON(!ptr);
+	return ptr;
+}
+
 static pte_t * __init pte_alloc(pmd_t *pmd, unsigned long addr,
 				unsigned long prot,
 				void *(*alloc)(unsigned long sz))
@@ -955,6 +963,17 @@ static void __init create_mapping(struct map_desc *md)
 	__create_mapping(&init_mm, md, early_alloc);
 }
 
+void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md)
+{
+#ifdef CONFIG_ARM_LPAE
+	pud_t *pud = pud_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
+	if (WARN_ON(!pud))
+		return;
+	pmd_alloc(mm, pud, 0);
+#endif
+	__create_mapping(mm, md, late_alloc);
+}
+
 /*
  * Create the architecture specific mappings
  */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/mm/init.c | 5 ++++-
 arch/arm/mm/mmu.c  | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8a63b4cdc0f2..16104b1e2661 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -191,7 +191,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(__pfn_to_phys(pfn));
+	return memblock_is_map_memory(__pfn_to_phys(pfn));
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
@@ -432,6 +432,9 @@ static void __init free_highpages(void)
 		if (end <= max_low)
 			continue;
 
+		if (memblock_is_nomap(mem))
+			continue;
+
 		/* Truncate partial highmem entries */
 		if (start < max_low)
 			start = max_low;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 0b7b61e31bc3..094e550144b3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1429,6 +1429,9 @@ static void __init map_lowmem(void)
 		phys_addr_t end = start + reg->size;
 		struct map_desc map;
 
+		if (memblock_is_nomap(reg))
+			continue;
+
 		if (end > arm_lowmem_limit)
 			end = arm_lowmem_limit;
 		if (start >= end)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/init.c | 5 ++++-
 arch/arm/mm/mmu.c  | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8a63b4cdc0f2..16104b1e2661 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -191,7 +191,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(__pfn_to_phys(pfn));
+	return memblock_is_map_memory(__pfn_to_phys(pfn));
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
@@ -432,6 +432,9 @@ static void __init free_highpages(void)
 		if (end <= max_low)
 			continue;
 
+		if (memblock_is_nomap(mem))
+			continue;
+
 		/* Truncate partial highmem entries */
 		if (start < max_low)
 			start = max_low;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 0b7b61e31bc3..094e550144b3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1429,6 +1429,9 @@ static void __init map_lowmem(void)
 		phys_addr_t end = start + reg->size;
 		struct map_desc map;
 
+		if (memblock_is_nomap(reg))
+			continue;
+
 		if (end > arm_lowmem_limit)
 			end = arm_lowmem_limit;
 		if (start >= end)
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Take the new memblock attribute MEMBLOCK_NOMAP into account when
deciding whether a certain region is or should be covered by the
kernel direct mapping.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/init.c | 5 ++++-
 arch/arm/mm/mmu.c  | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8a63b4cdc0f2..16104b1e2661 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -191,7 +191,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-	return memblock_is_memory(__pfn_to_phys(pfn));
+	return memblock_is_map_memory(__pfn_to_phys(pfn));
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
@@ -432,6 +432,9 @@ static void __init free_highpages(void)
 		if (end <= max_low)
 			continue;
 
+		if (memblock_is_nomap(mem))
+			continue;
+
 		/* Truncate partial highmem entries */
 		if (start < max_low)
 			start = max_low;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 0b7b61e31bc3..094e550144b3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1429,6 +1429,9 @@ static void __init map_lowmem(void)
 		phys_addr_t end = start + reg->size;
 		struct map_desc map;
 
+		if (memblock_is_nomap(reg))
+			continue;
+
 		if (end > arm_lowmem_limit)
 			end = arm_lowmem_limit;
 		if (start >= end)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

This adds support to the kernel proper for booting via UEFI. It shares
most of the code with arm64, so this patch mostly just wires it up for
use with ARM.

Note that this does not include the EFI stub, it is added in a subsequent
patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/include/asm/efi.h    | 67 ++++++++++++++++++++
 arch/arm/kernel/Makefile      |  1 +
 arch/arm/kernel/efi.c         | 38 +++++++++++
 arch/arm/kernel/setup.c       |  3 +
 drivers/firmware/efi/Makefile |  1 +
 5 files changed, 110 insertions(+)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
new file mode 100644
index 000000000000..96cac28a6a24
--- /dev/null
+++ b/arch/arm/include/asm/efi.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.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.
+ */
+
+#ifndef __ASM_ARM_EFI_H
+#define __ASM_ARM_EFI_H
+
+#include <asm/cacheflush.h>
+#include <asm/cachetype.h>
+#include <asm/early_ioremap.h>
+#include <asm/fixmap.h>
+#include <asm/highmem.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_EFI
+void efi_init(void);
+
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
+#define efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+	efi_status_t __s;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__s = __f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+	__s;								\
+})
+
+#define __efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+})
+
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
+		__check_vmalloc_seq(mm);
+
+	cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_vivt_asid_tagged())
+		__flush_icache_all();
+}
+
+void efi_virtmap_load(void);
+void efi_virtmap_unload(void);
+
+#else
+#define efi_init()
+#endif /* CONFIG_EFI */
+
+#endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index af9e59bf3831..c90f4a70d646 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -77,6 +77,7 @@ CFLAGS_pj4-cp0.o		:= -marm
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 obj-$(CONFIG_VDSO)		+= vdso.o
+obj-$(CONFIG_EFI)		+= efi.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
new file mode 100644
index 000000000000..743806dfdacc
--- /dev/null
+++ b/arch/arm/kernel/efi.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.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 <asm/efi.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	struct map_desc desc = {
+		.virtual	= md->virt_addr,
+		.pfn		= __phys_to_pfn(md->phys_addr),
+		.length		= md->num_pages * EFI_PAGE_SIZE,
+	};
+
+	/*
+	 * Order is important here: memory regions may have all of the
+	 * bits below set (and usually do), so we check them in order of
+	 * preference.
+	 */
+	if (md->attribute & EFI_MEMORY_WB)
+		desc.type = MT_MEMORY_RWX;
+	else if (md->attribute & EFI_MEMORY_WT)
+		desc.type = MT_MEMORY_RWX_NONCACHED;
+	else if (md->attribute & EFI_MEMORY_WC)
+		desc.type = MT_DEVICE_WC;
+	else
+		desc.type = MT_DEVICE;
+
+	create_mapping_late(mm, &desc);
+	return 0;
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 5df2bca57c42..b341b1c3b2fa 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -7,6 +7,7 @@
  * 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/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -37,6 +38,7 @@
 #include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/efi.h>
 #include <asm/elf.h>
 #include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
@@ -966,6 +968,7 @@ void __init setup_arch(char **cmdline_p)
 	early_paging_init(mdesc);
 #endif
 	setup_dma_zone(mdesc);
+	efi_init();
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index f292917b00e7..62e654f255f4 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -20,4 +20,5 @@ obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM)			+= $(arm-obj-y)
 obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

This adds support to the kernel proper for booting via UEFI. It shares
most of the code with arm64, so this patch mostly just wires it up for
use with ARM.

Note that this does not include the EFI stub, it is added in a subsequent
patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/include/asm/efi.h    | 67 ++++++++++++++++++++
 arch/arm/kernel/Makefile      |  1 +
 arch/arm/kernel/efi.c         | 38 +++++++++++
 arch/arm/kernel/setup.c       |  3 +
 drivers/firmware/efi/Makefile |  1 +
 5 files changed, 110 insertions(+)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
new file mode 100644
index 000000000000..96cac28a6a24
--- /dev/null
+++ b/arch/arm/include/asm/efi.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <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.
+ */
+
+#ifndef __ASM_ARM_EFI_H
+#define __ASM_ARM_EFI_H
+
+#include <asm/cacheflush.h>
+#include <asm/cachetype.h>
+#include <asm/early_ioremap.h>
+#include <asm/fixmap.h>
+#include <asm/highmem.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_EFI
+void efi_init(void);
+
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
+#define efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+	efi_status_t __s;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__s = __f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+	__s;								\
+})
+
+#define __efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+})
+
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
+		__check_vmalloc_seq(mm);
+
+	cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_vivt_asid_tagged())
+		__flush_icache_all();
+}
+
+void efi_virtmap_load(void);
+void efi_virtmap_unload(void);
+
+#else
+#define efi_init()
+#endif /* CONFIG_EFI */
+
+#endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index af9e59bf3831..c90f4a70d646 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -77,6 +77,7 @@ CFLAGS_pj4-cp0.o		:= -marm
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 obj-$(CONFIG_VDSO)		+= vdso.o
+obj-$(CONFIG_EFI)		+= efi.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
new file mode 100644
index 000000000000..743806dfdacc
--- /dev/null
+++ b/arch/arm/kernel/efi.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <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 <asm/efi.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	struct map_desc desc = {
+		.virtual	= md->virt_addr,
+		.pfn		= __phys_to_pfn(md->phys_addr),
+		.length		= md->num_pages * EFI_PAGE_SIZE,
+	};
+
+	/*
+	 * Order is important here: memory regions may have all of the
+	 * bits below set (and usually do), so we check them in order of
+	 * preference.
+	 */
+	if (md->attribute & EFI_MEMORY_WB)
+		desc.type = MT_MEMORY_RWX;
+	else if (md->attribute & EFI_MEMORY_WT)
+		desc.type = MT_MEMORY_RWX_NONCACHED;
+	else if (md->attribute & EFI_MEMORY_WC)
+		desc.type = MT_DEVICE_WC;
+	else
+		desc.type = MT_DEVICE;
+
+	create_mapping_late(mm, &desc);
+	return 0;
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 5df2bca57c42..b341b1c3b2fa 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -7,6 +7,7 @@
  * 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/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -37,6 +38,7 @@
 #include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/efi.h>
 #include <asm/elf.h>
 #include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
@@ -966,6 +968,7 @@ void __init setup_arch(char **cmdline_p)
 	early_paging_init(mdesc);
 #endif
 	setup_dma_zone(mdesc);
+	efi_init();
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index f292917b00e7..62e654f255f4 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -20,4 +20,5 @@ obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM)			+= $(arm-obj-y)
 obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

This adds support to the kernel proper for booting via UEFI. It shares
most of the code with arm64, so this patch mostly just wires it up for
use with ARM.

Note that this does not include the EFI stub, it is added in a subsequent
patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/include/asm/efi.h    | 67 ++++++++++++++++++++
 arch/arm/kernel/Makefile      |  1 +
 arch/arm/kernel/efi.c         | 38 +++++++++++
 arch/arm/kernel/setup.c       |  3 +
 drivers/firmware/efi/Makefile |  1 +
 5 files changed, 110 insertions(+)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
new file mode 100644
index 000000000000..96cac28a6a24
--- /dev/null
+++ b/arch/arm/include/asm/efi.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <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.
+ */
+
+#ifndef __ASM_ARM_EFI_H
+#define __ASM_ARM_EFI_H
+
+#include <asm/cacheflush.h>
+#include <asm/cachetype.h>
+#include <asm/early_ioremap.h>
+#include <asm/fixmap.h>
+#include <asm/highmem.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_EFI
+void efi_init(void);
+
+int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+
+#define efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+	efi_status_t __s;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__s = __f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+	__s;								\
+})
+
+#define __efi_call_virt(f, ...)						\
+({									\
+	efi_##f##_t *__f;						\
+									\
+	efi_virtmap_load();						\
+	__f = efi.systab->runtime->f;					\
+	__f(__VA_ARGS__);						\
+	efi_virtmap_unload();						\
+})
+
+static inline void efi_set_pgd(struct mm_struct *mm)
+{
+	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
+		__check_vmalloc_seq(mm);
+
+	cpu_switch_mm(mm->pgd, mm);
+
+	flush_tlb_all();
+	if (icache_is_vivt_asid_tagged())
+		__flush_icache_all();
+}
+
+void efi_virtmap_load(void);
+void efi_virtmap_unload(void);
+
+#else
+#define efi_init()
+#endif /* CONFIG_EFI */
+
+#endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index af9e59bf3831..c90f4a70d646 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -77,6 +77,7 @@ CFLAGS_pj4-cp0.o		:= -marm
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 obj-$(CONFIG_VDSO)		+= vdso.o
+obj-$(CONFIG_EFI)		+= efi.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
new file mode 100644
index 000000000000..743806dfdacc
--- /dev/null
+++ b/arch/arm/kernel/efi.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd <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 <asm/efi.h>
+#include <asm/mach/map.h>
+#include <asm/mmu_context.h>
+
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	struct map_desc desc = {
+		.virtual	= md->virt_addr,
+		.pfn		= __phys_to_pfn(md->phys_addr),
+		.length		= md->num_pages * EFI_PAGE_SIZE,
+	};
+
+	/*
+	 * Order is important here: memory regions may have all of the
+	 * bits below set (and usually do), so we check them in order of
+	 * preference.
+	 */
+	if (md->attribute & EFI_MEMORY_WB)
+		desc.type = MT_MEMORY_RWX;
+	else if (md->attribute & EFI_MEMORY_WT)
+		desc.type = MT_MEMORY_RWX_NONCACHED;
+	else if (md->attribute & EFI_MEMORY_WC)
+		desc.type = MT_DEVICE_WC;
+	else
+		desc.type = MT_DEVICE;
+
+	create_mapping_late(mm, &desc);
+	return 0;
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 5df2bca57c42..b341b1c3b2fa 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -7,6 +7,7 @@
  * 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/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -37,6 +38,7 @@
 #include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/efi.h>
 #include <asm/elf.h>
 #include <asm/early_ioremap.h>
 #include <asm/fixmap.h>
@@ -966,6 +968,7 @@ void __init setup_arch(char **cmdline_p)
 	early_paging_init(mdesc);
 #endif
 	setup_dma_zone(mdesc);
+	efi_init();
 	sanity_check_meminfo();
 	arm_memblock_init(mdesc);
 
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index f292917b00e7..62e654f255f4 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -20,4 +20,5 @@ obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
+obj-$(CONFIG_ARM)			+= $(arm-obj-y)
 obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 12/12] ARM: add UEFI stub support
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:32     ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A
  Cc: msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Ard Biesheuvel

From: Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patch adds EFI stub support for the ARM Linux kernel.

The EFI stub operates similarly to the x86 and arm64 stubs: it is a
shim between the EFI firmware and the normal zImage entry point, and
sets up the environment that the zImage is expecting. This includes
optionally loading the initrd and device tree from the system partition
based on the kernel command line.

Signed-off-by: Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/Kconfig                          |  19 +++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++++++++++++++
 arch/arm/boot/compressed/head.S           |  54 +++++++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 ++
 arch/arm/include/asm/efi.h                |  23 ++++
 drivers/firmware/efi/libstub/Makefile     |   9 ++
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++++++++++
 9 files changed, 331 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7e338228cc8d..0d84e04cfe48 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2041,6 +2041,25 @@ config AUTO_ZRELADDR
 	  0xf8000000. This assumes the zImage being placed in the first 128MB
 	  from start of memory.
 
+config EFI_STUB
+	bool
+
+config EFI
+	bool "UEFI runtime support"
+	depends on OF && !CPU_BIG_ENDIAN && MMU && AUTO_ZRELADDR && !XIP_KERNEL
+	select UCS2_STRING
+	select EFI_PARAMS_FROM_FDT
+	select EFI_STUB
+	select EFI_ARMSTUB
+	select EFI_RUNTIME_WRAPPERS
+	---help---
+	  This option provides support for runtime services provided
+	  by UEFI firmware (such as non-volatile variables, realtime
+	  clock, and platform reset). A UEFI stub is also provided to
+	  allow the kernel to be booted as an EFI application. This
+	  is only useful for kernels that may run on systems that have
+	  UEFI firmware.
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 3f9a9ebc77c3..4c23a68a0917 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -167,9 +167,11 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
 	false; \
 fi
 
+efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 		$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
-		$(bswapsdi2) FORCE
+		$(bswapsdi2) $(efi-obj-y) FORCE
 	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
new file mode 100644
index 000000000000..9d5dc4fda3c1
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2013-2015 Linaro Ltd
+ * Authors: Roy Franz <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *          Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.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.
+ */
+
+		.macro	__nop
+#ifdef CONFIG_EFI_STUB
+		@ This is almost but not quite a NOP, since it does clobber the
+		@ condition flags. But it is the best we can do for EFI, since
+		@ PE/COFF expects the magic string "MZ" at offset 0, while the
+		@ ARM/Linux boot protocol expects an executable instruction
+		@ there.
+		.inst	'M' | ('Z' << 8) | (0x1310 << 16)   @ tstne r0, #0x4d000
+#else
+		mov	r0, r0
+#endif
+		.endm
+
+		.macro	__EFI_HEADER
+#ifdef CONFIG_EFI_STUB
+		b	__efi_start
+
+		.set	start_offset, __efi_start - start
+		.org	start + 0x3c
+		@
+		@ The PE header can be anywhere in the file, but for
+		@ simplicity we keep it together with the MSDOS header
+		@ The offset to the PE/COFF header needs to be at offset
+		@ 0x3C in the MSDOS header.
+		@ The only 2 fields of the MSDOS header that are used are this
+		@ PE/COFF offset, and the "MZ" bytes at offset 0x0.
+		@
+		.long	pe_header - start	@ Offset to the PE header.
+
+pe_header:
+		.ascii	"PE\0\0"
+
+coff_header:
+		.short	0x01c2			@ ARM or Thumb
+		.short	2			@ nr_sections
+		.long	0 			@ TimeDateStamp
+		.long	0			@ PointerToSymbolTable
+		.long	1			@ NumberOfSymbols
+		.short	section_table - optional_header
+						@ SizeOfOptionalHeader
+		.short	0x306			@ Characteristics.
+						@ IMAGE_FILE_32BIT_MACHINE |
+						@ IMAGE_FILE_DEBUG_STRIPPED |
+						@ IMAGE_FILE_EXECUTABLE_IMAGE |
+						@ IMAGE_FILE_LINE_NUMS_STRIPPED
+
+optional_header:
+		.short	0x10b			@ PE32 format
+		.byte	0x02			@ MajorLinkerVersion
+		.byte	0x14			@ MinorLinkerVersion
+		.long	_end - __efi_start	@ SizeOfCode
+		.long	0			@ SizeOfInitializedData
+		.long	0			@ SizeOfUninitializedData
+		.long	efi_stub_entry - start	@ AddressOfEntryPoint
+		.long	start_offset		@ BaseOfCode
+		.long	0			@ data
+
+extra_header_fields:
+		.long	0			@ ImageBase
+		.long	0x200			@ SectionAlignment
+		.long	0x200			@ FileAlignment
+		.short	0			@ MajorOperatingSystemVersion
+		.short	0			@ MinorOperatingSystemVersion
+		.short	0			@ MajorImageVersion
+		.short	0			@ MinorImageVersion
+		.short	0			@ MajorSubsystemVersion
+		.short	0			@ MinorSubsystemVersion
+		.long	0			@ Win32VersionValue
+
+		.long	_end - start		@ SizeOfImage
+		.long	start_offset		@ SizeOfHeaders
+		.long	0			@ CheckSum
+		.short	0xa			@ Subsystem (EFI application)
+		.short	0			@ DllCharacteristics
+		.long	0			@ SizeOfStackReserve
+		.long	0			@ SizeOfStackCommit
+		.long	0			@ SizeOfHeapReserve
+		.long	0			@ SizeOfHeapCommit
+		.long	0			@ LoaderFlags
+		.long	0x6			@ NumberOfRvaAndSizes
+
+		.quad	0			@ ExportTable
+		.quad	0			@ ImportTable
+		.quad	0			@ ResourceTable
+		.quad	0			@ ExceptionTable
+		.quad	0			@ CertificationTable
+		.quad	0			@ BaseRelocationTable
+
+section_table:
+		@
+		@ The EFI application loader requires a relocation section
+		@ because EFI applications must be relocatable. This is a
+		@ dummy section as far as we are concerned.
+		@
+		.ascii	".reloc\0\0"
+		.long	0			@ VirtualSize
+		.long	0			@ VirtualAddress
+		.long	0			@ SizeOfRawData
+		.long	0			@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0x42100040		@ Characteristics
+
+		.ascii	".text\0\0\0"
+		.long	_end - __efi_start	@ VirtualSize
+		.long	__efi_start		@ VirtualAddress
+		.long	_edata - __efi_start	@ SizeOfRawData
+		.long	__efi_start		@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0xe0500020		@ Characteristics
+
+		.align	9
+__efi_start:
+#endif
+		.endm
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 06e983f59980..af11c2f8f3b7 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -12,6 +12,8 @@
 #include <asm/assembler.h>
 #include <asm/v7m.h>
 
+#include "efi-header.S"
+
  AR_CLASS(	.arch	armv7-a	)
  M_CLASS(	.arch	armv7-m	)
 
@@ -126,7 +128,7 @@
 start:
 		.type	start,#function
 		.rept	7
-		mov	r0, r0
+		__nop
 		.endr
    ARM(		mov	r0, r0		)
    ARM(		b	1f		)
@@ -139,7 +141,8 @@ start:
 		.word	0x04030201	@ endianness flag
 
  THUMB(		.thumb			)
-1:
+1:		__EFI_HEADER
+
  ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
  AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
@@ -1353,6 +1356,53 @@ __enter_kernel:
 
 reloc_code_end:
 
+#ifdef CONFIG_EFI_STUB
+		.align	2
+_start:		.long	start - .
+
+ENTRY(efi_stub_entry)
+		@ allocate space on stack for passing current zImage address
+		@ and for the EFI stub to return of new entry point of
+		@ zImage, as EFI stub may copy the kernel. Pointer address
+		@ is passed in r2. r0 and r1 are passed through from the
+		@ EFI firmware to efi_entry
+		adr	ip, _start
+		ldr	r3, [ip]
+		add	r3, r3, ip
+		stmfd	sp!, {r3, lr}
+		mov	r2, sp			@ pass zImage address in r2
+		bl	efi_entry
+
+		@ Check for error return from EFI stub. r0 has FDT address
+		@ or error code.
+		cmn	r0, #1
+		beq	efi_load_fail
+
+		@ Preserve return value of efi_entry() in r4
+		mov	r4, r0
+		bl	cache_clean_flush
+		bl	cache_off
+
+		@ Set parameters for booting zImage according to boot protocol
+		@ put FDT address in r2, it was returned by efi_entry()
+		@ r1 is the machine type, and r0 needs to be 0
+		mov	r0, #0
+		mov	r1, #0xFFFFFFFF
+		mov	r2, r4
+
+		@ Branch to (possibly) relocated zImage that is in [sp]
+		ldr	lr, [sp]
+		ldr	ip, =start_offset
+		add	lr, lr, ip
+		mov	pc, lr				@ no mode switch
+
+efi_load_fail:
+		@ Return EFI_LOAD_ERROR to EFI firmware on error.
+		ldr	r0, =0x80000001
+		ldmfd	sp!, {ip, pc}
+ENDPROC(efi_stub_entry)
+#endif
+
 		.align
 		.section ".stack", "aw", %nobits
 .L_user_stack:	.space	4096
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 2b60b843ac5e..81c493156ce8 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -48,6 +48,13 @@ SECTIONS
     *(.rodata)
     *(.rodata.*)
   }
+  .data : {
+    /*
+     * The EFI stub always executes from RAM, and runs strictly before the
+     * decompressor, so we can make an exception for its r/w data, and keep it
+     */
+    *(.data.efistub)
+  }
   .piggydata : {
     *(.piggydata)
   }
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 96cac28a6a24..9897235e9186 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -64,4 +64,27 @@ void efi_virtmap_unload(void);
 #define efi_init()
 #endif /* CONFIG_EFI */
 
+/* arch specific definitions used by the stub code */
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
+/*
+ * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
+ * so we will reserve that amount of memory. We have no easy way to tell what
+ * the actuall size of code + data the uncompressed kernel will use.
+ * If this is insufficient, the decompressor will relocate itself out of the
+ * way before performing the decompression.
+ */
+#define MAX_UNCOMP_KERNEL_SIZE	SZ_32M
+
+/*
+ * The kernel zImage should preferably be located between 32 MB and 128 MB
+ * from the base of DRAM. The min address leaves space for a maximal size
+ * uncompressed image, and the max address is due to how the zImage decompressor
+ * picks a destination address.
+ */
+#define ZIMAGE_OFFSET_LIMIT	SZ_128M
+#define MIN_ZIMAGE_OFFSET	MAX_UNCOMP_KERNEL_SIZE
+#define MAX_FDT_OFFSET		ZIMAGE_OFFSET_LIMIT
+
 #endif /* _ASM_ARM_EFI_H */
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 3c0467d3688c..8cf9ccbf42d5 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -34,6 +34,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
+lib-$(CONFIG_ARM)		+= arm32-stub.o
 lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
@@ -67,3 +68,11 @@ quiet_cmd_stubcopy = STUBCPY $@
 		     $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y)	\
 		     && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \
 			 rm -f $@; /bin/false); else /bin/false; fi
+
+#
+# ARM discards the .data section because it disallows r/w data in the
+# decompressor. So move our .data to .data.efistub, which is preserved
+# explicitly by the decompressor linker script.
+#
+STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub
+STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 950c87f5d279..3397902e4040 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -303,8 +303,10 @@ fail:
  * The value chosen is the largest non-zero power of 2 suitable for this purpose
  * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
  * be mapped efficiently.
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
+ * map everything below 1 GB.
  */
-#define EFI_RT_VIRTUAL_BASE	0x40000000
+#define EFI_RT_VIRTUAL_BASE	SZ_512M
 
 static int cmp_mem_desc(const void *l, const void *r)
 {
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
new file mode 100644
index 000000000000..958075a72d72
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 Linaro Ltd;  <roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.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 <asm/efi.h>
+
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+				 unsigned long *image_addr,
+				 unsigned long *image_size,
+				 unsigned long *reserve_addr,
+				 unsigned long *reserve_size,
+				 unsigned long dram_base,
+				 efi_loaded_image_t *image)
+{
+	unsigned long nr_pages;
+	efi_status_t status;
+	/* Use alloc_addr to tranlsate between types */
+	efi_physical_addr_t alloc_addr;
+
+	/*
+	 * Verify that the DRAM base address is compatible with the ARM
+	 * boot protocol, which determines the base of DRAM by masking
+	 * off the low 27 bits of the address at which the zImage is
+	 * loaded. These assumptions are made by the decompressor,
+	 * before any memory map is available.
+	 */
+	dram_base = round_up(dram_base, SZ_128M);
+
+	/*
+	 * Reserve memory for the uncompressed kernel image. This is
+	 * all that prevents any future allocations from conflicting
+	 * with the kernel. Since we can't tell from the compressed
+	 * image how much DRAM the kernel actually uses (due to BSS
+	 * size uncertainty) we allocate the maximum possible size.
+	 * Do this very early, as prints can cause memory allocations
+	 * that may conflict with this.
+	 */
+	alloc_addr = dram_base;
+	*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+	nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS,
+						     EFI_LOADER_DATA,
+						     nr_pages, &alloc_addr);
+	if (status != EFI_SUCCESS) {
+		*reserve_size = 0;
+		pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
+		return status;
+	}
+	*reserve_addr = alloc_addr;
+
+	/*
+	 * Relocate the zImage, if required. ARM doesn't have a
+	 * preferred address, so we set it to 0, as we want to allocate
+	 * as low in memory as possible.
+	 */
+	*image_size = image->image_size;
+	status = efi_relocate_kernel(sys_table, image_addr, *image_size,
+				     *image_size, 0, 0);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		return status;
+	}
+
+	/*
+	 * Check to see if we were able to allocate memory low enough
+	 * in memory. The kernel determines the base of DRAM from the
+	 * address at which the zImage is loaded.
+	 */
+	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+		pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		efi_free(sys_table, *image_size, *image_addr);
+		*image_size = 0;
+		return EFI_LOAD_ERROR;
+	}
+	return EFI_SUCCESS;
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 12/12] ARM: add UEFI stub support
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz
  Cc: msalter, ryan.harkin, akpm, linux-mm, Ard Biesheuvel

From: Roy Franz <roy.franz@linaro.org>

This patch adds EFI stub support for the ARM Linux kernel.

The EFI stub operates similarly to the x86 and arm64 stubs: it is a
shim between the EFI firmware and the normal zImage entry point, and
sets up the environment that the zImage is expecting. This includes
optionally loading the initrd and device tree from the system partition
based on the kernel command line.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/Kconfig                          |  19 +++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++++++++++++++
 arch/arm/boot/compressed/head.S           |  54 +++++++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 ++
 arch/arm/include/asm/efi.h                |  23 ++++
 drivers/firmware/efi/libstub/Makefile     |   9 ++
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++++++++++
 9 files changed, 331 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7e338228cc8d..0d84e04cfe48 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2041,6 +2041,25 @@ config AUTO_ZRELADDR
 	  0xf8000000. This assumes the zImage being placed in the first 128MB
 	  from start of memory.
 
+config EFI_STUB
+	bool
+
+config EFI
+	bool "UEFI runtime support"
+	depends on OF && !CPU_BIG_ENDIAN && MMU && AUTO_ZRELADDR && !XIP_KERNEL
+	select UCS2_STRING
+	select EFI_PARAMS_FROM_FDT
+	select EFI_STUB
+	select EFI_ARMSTUB
+	select EFI_RUNTIME_WRAPPERS
+	---help---
+	  This option provides support for runtime services provided
+	  by UEFI firmware (such as non-volatile variables, realtime
+	  clock, and platform reset). A UEFI stub is also provided to
+	  allow the kernel to be booted as an EFI application. This
+	  is only useful for kernels that may run on systems that have
+	  UEFI firmware.
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 3f9a9ebc77c3..4c23a68a0917 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -167,9 +167,11 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
 	false; \
 fi
 
+efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 		$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
-		$(bswapsdi2) FORCE
+		$(bswapsdi2) $(efi-obj-y) FORCE
 	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
new file mode 100644
index 000000000000..9d5dc4fda3c1
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2013-2015 Linaro Ltd
+ * Authors: Roy Franz <roy.franz@linaro.org>
+ *          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.
+ */
+
+		.macro	__nop
+#ifdef CONFIG_EFI_STUB
+		@ This is almost but not quite a NOP, since it does clobber the
+		@ condition flags. But it is the best we can do for EFI, since
+		@ PE/COFF expects the magic string "MZ" at offset 0, while the
+		@ ARM/Linux boot protocol expects an executable instruction
+		@ there.
+		.inst	'M' | ('Z' << 8) | (0x1310 << 16)   @ tstne r0, #0x4d000
+#else
+		mov	r0, r0
+#endif
+		.endm
+
+		.macro	__EFI_HEADER
+#ifdef CONFIG_EFI_STUB
+		b	__efi_start
+
+		.set	start_offset, __efi_start - start
+		.org	start + 0x3c
+		@
+		@ The PE header can be anywhere in the file, but for
+		@ simplicity we keep it together with the MSDOS header
+		@ The offset to the PE/COFF header needs to be at offset
+		@ 0x3C in the MSDOS header.
+		@ The only 2 fields of the MSDOS header that are used are this
+		@ PE/COFF offset, and the "MZ" bytes at offset 0x0.
+		@
+		.long	pe_header - start	@ Offset to the PE header.
+
+pe_header:
+		.ascii	"PE\0\0"
+
+coff_header:
+		.short	0x01c2			@ ARM or Thumb
+		.short	2			@ nr_sections
+		.long	0 			@ TimeDateStamp
+		.long	0			@ PointerToSymbolTable
+		.long	1			@ NumberOfSymbols
+		.short	section_table - optional_header
+						@ SizeOfOptionalHeader
+		.short	0x306			@ Characteristics.
+						@ IMAGE_FILE_32BIT_MACHINE |
+						@ IMAGE_FILE_DEBUG_STRIPPED |
+						@ IMAGE_FILE_EXECUTABLE_IMAGE |
+						@ IMAGE_FILE_LINE_NUMS_STRIPPED
+
+optional_header:
+		.short	0x10b			@ PE32 format
+		.byte	0x02			@ MajorLinkerVersion
+		.byte	0x14			@ MinorLinkerVersion
+		.long	_end - __efi_start	@ SizeOfCode
+		.long	0			@ SizeOfInitializedData
+		.long	0			@ SizeOfUninitializedData
+		.long	efi_stub_entry - start	@ AddressOfEntryPoint
+		.long	start_offset		@ BaseOfCode
+		.long	0			@ data
+
+extra_header_fields:
+		.long	0			@ ImageBase
+		.long	0x200			@ SectionAlignment
+		.long	0x200			@ FileAlignment
+		.short	0			@ MajorOperatingSystemVersion
+		.short	0			@ MinorOperatingSystemVersion
+		.short	0			@ MajorImageVersion
+		.short	0			@ MinorImageVersion
+		.short	0			@ MajorSubsystemVersion
+		.short	0			@ MinorSubsystemVersion
+		.long	0			@ Win32VersionValue
+
+		.long	_end - start		@ SizeOfImage
+		.long	start_offset		@ SizeOfHeaders
+		.long	0			@ CheckSum
+		.short	0xa			@ Subsystem (EFI application)
+		.short	0			@ DllCharacteristics
+		.long	0			@ SizeOfStackReserve
+		.long	0			@ SizeOfStackCommit
+		.long	0			@ SizeOfHeapReserve
+		.long	0			@ SizeOfHeapCommit
+		.long	0			@ LoaderFlags
+		.long	0x6			@ NumberOfRvaAndSizes
+
+		.quad	0			@ ExportTable
+		.quad	0			@ ImportTable
+		.quad	0			@ ResourceTable
+		.quad	0			@ ExceptionTable
+		.quad	0			@ CertificationTable
+		.quad	0			@ BaseRelocationTable
+
+section_table:
+		@
+		@ The EFI application loader requires a relocation section
+		@ because EFI applications must be relocatable. This is a
+		@ dummy section as far as we are concerned.
+		@
+		.ascii	".reloc\0\0"
+		.long	0			@ VirtualSize
+		.long	0			@ VirtualAddress
+		.long	0			@ SizeOfRawData
+		.long	0			@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0x42100040		@ Characteristics
+
+		.ascii	".text\0\0\0"
+		.long	_end - __efi_start	@ VirtualSize
+		.long	__efi_start		@ VirtualAddress
+		.long	_edata - __efi_start	@ SizeOfRawData
+		.long	__efi_start		@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0xe0500020		@ Characteristics
+
+		.align	9
+__efi_start:
+#endif
+		.endm
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 06e983f59980..af11c2f8f3b7 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -12,6 +12,8 @@
 #include <asm/assembler.h>
 #include <asm/v7m.h>
 
+#include "efi-header.S"
+
  AR_CLASS(	.arch	armv7-a	)
  M_CLASS(	.arch	armv7-m	)
 
@@ -126,7 +128,7 @@
 start:
 		.type	start,#function
 		.rept	7
-		mov	r0, r0
+		__nop
 		.endr
    ARM(		mov	r0, r0		)
    ARM(		b	1f		)
@@ -139,7 +141,8 @@ start:
 		.word	0x04030201	@ endianness flag
 
  THUMB(		.thumb			)
-1:
+1:		__EFI_HEADER
+
  ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
  AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
@@ -1353,6 +1356,53 @@ __enter_kernel:
 
 reloc_code_end:
 
+#ifdef CONFIG_EFI_STUB
+		.align	2
+_start:		.long	start - .
+
+ENTRY(efi_stub_entry)
+		@ allocate space on stack for passing current zImage address
+		@ and for the EFI stub to return of new entry point of
+		@ zImage, as EFI stub may copy the kernel. Pointer address
+		@ is passed in r2. r0 and r1 are passed through from the
+		@ EFI firmware to efi_entry
+		adr	ip, _start
+		ldr	r3, [ip]
+		add	r3, r3, ip
+		stmfd	sp!, {r3, lr}
+		mov	r2, sp			@ pass zImage address in r2
+		bl	efi_entry
+
+		@ Check for error return from EFI stub. r0 has FDT address
+		@ or error code.
+		cmn	r0, #1
+		beq	efi_load_fail
+
+		@ Preserve return value of efi_entry() in r4
+		mov	r4, r0
+		bl	cache_clean_flush
+		bl	cache_off
+
+		@ Set parameters for booting zImage according to boot protocol
+		@ put FDT address in r2, it was returned by efi_entry()
+		@ r1 is the machine type, and r0 needs to be 0
+		mov	r0, #0
+		mov	r1, #0xFFFFFFFF
+		mov	r2, r4
+
+		@ Branch to (possibly) relocated zImage that is in [sp]
+		ldr	lr, [sp]
+		ldr	ip, =start_offset
+		add	lr, lr, ip
+		mov	pc, lr				@ no mode switch
+
+efi_load_fail:
+		@ Return EFI_LOAD_ERROR to EFI firmware on error.
+		ldr	r0, =0x80000001
+		ldmfd	sp!, {ip, pc}
+ENDPROC(efi_stub_entry)
+#endif
+
 		.align
 		.section ".stack", "aw", %nobits
 .L_user_stack:	.space	4096
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 2b60b843ac5e..81c493156ce8 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -48,6 +48,13 @@ SECTIONS
     *(.rodata)
     *(.rodata.*)
   }
+  .data : {
+    /*
+     * The EFI stub always executes from RAM, and runs strictly before the
+     * decompressor, so we can make an exception for its r/w data, and keep it
+     */
+    *(.data.efistub)
+  }
   .piggydata : {
     *(.piggydata)
   }
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 96cac28a6a24..9897235e9186 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -64,4 +64,27 @@ void efi_virtmap_unload(void);
 #define efi_init()
 #endif /* CONFIG_EFI */
 
+/* arch specific definitions used by the stub code */
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
+/*
+ * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
+ * so we will reserve that amount of memory. We have no easy way to tell what
+ * the actuall size of code + data the uncompressed kernel will use.
+ * If this is insufficient, the decompressor will relocate itself out of the
+ * way before performing the decompression.
+ */
+#define MAX_UNCOMP_KERNEL_SIZE	SZ_32M
+
+/*
+ * The kernel zImage should preferably be located between 32 MB and 128 MB
+ * from the base of DRAM. The min address leaves space for a maximal size
+ * uncompressed image, and the max address is due to how the zImage decompressor
+ * picks a destination address.
+ */
+#define ZIMAGE_OFFSET_LIMIT	SZ_128M
+#define MIN_ZIMAGE_OFFSET	MAX_UNCOMP_KERNEL_SIZE
+#define MAX_FDT_OFFSET		ZIMAGE_OFFSET_LIMIT
+
 #endif /* _ASM_ARM_EFI_H */
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 3c0467d3688c..8cf9ccbf42d5 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -34,6 +34,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
+lib-$(CONFIG_ARM)		+= arm32-stub.o
 lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
@@ -67,3 +68,11 @@ quiet_cmd_stubcopy = STUBCPY $@
 		     $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y)	\
 		     && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \
 			 rm -f $@; /bin/false); else /bin/false; fi
+
+#
+# ARM discards the .data section because it disallows r/w data in the
+# decompressor. So move our .data to .data.efistub, which is preserved
+# explicitly by the decompressor linker script.
+#
+STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub
+STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 950c87f5d279..3397902e4040 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -303,8 +303,10 @@ fail:
  * The value chosen is the largest non-zero power of 2 suitable for this purpose
  * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
  * be mapped efficiently.
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
+ * map everything below 1 GB.
  */
-#define EFI_RT_VIRTUAL_BASE	0x40000000
+#define EFI_RT_VIRTUAL_BASE	SZ_512M
 
 static int cmp_mem_desc(const void *l, const void *r)
 {
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
new file mode 100644
index 000000000000..958075a72d72
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 Linaro Ltd;  <roy.franz@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 <asm/efi.h>
+
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+				 unsigned long *image_addr,
+				 unsigned long *image_size,
+				 unsigned long *reserve_addr,
+				 unsigned long *reserve_size,
+				 unsigned long dram_base,
+				 efi_loaded_image_t *image)
+{
+	unsigned long nr_pages;
+	efi_status_t status;
+	/* Use alloc_addr to tranlsate between types */
+	efi_physical_addr_t alloc_addr;
+
+	/*
+	 * Verify that the DRAM base address is compatible with the ARM
+	 * boot protocol, which determines the base of DRAM by masking
+	 * off the low 27 bits of the address at which the zImage is
+	 * loaded. These assumptions are made by the decompressor,
+	 * before any memory map is available.
+	 */
+	dram_base = round_up(dram_base, SZ_128M);
+
+	/*
+	 * Reserve memory for the uncompressed kernel image. This is
+	 * all that prevents any future allocations from conflicting
+	 * with the kernel. Since we can't tell from the compressed
+	 * image how much DRAM the kernel actually uses (due to BSS
+	 * size uncertainty) we allocate the maximum possible size.
+	 * Do this very early, as prints can cause memory allocations
+	 * that may conflict with this.
+	 */
+	alloc_addr = dram_base;
+	*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+	nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS,
+						     EFI_LOADER_DATA,
+						     nr_pages, &alloc_addr);
+	if (status != EFI_SUCCESS) {
+		*reserve_size = 0;
+		pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
+		return status;
+	}
+	*reserve_addr = alloc_addr;
+
+	/*
+	 * Relocate the zImage, if required. ARM doesn't have a
+	 * preferred address, so we set it to 0, as we want to allocate
+	 * as low in memory as possible.
+	 */
+	*image_size = image->image_size;
+	status = efi_relocate_kernel(sys_table, image_addr, *image_size,
+				     *image_size, 0, 0);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		return status;
+	}
+
+	/*
+	 * Check to see if we were able to allocate memory low enough
+	 * in memory. The kernel determines the base of DRAM from the
+	 * address at which the zImage is loaded.
+	 */
+	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+		pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		efi_free(sys_table, *image_size, *image_addr);
+		*image_size = 0;
+		return EFI_LOAD_ERROR;
+	}
+	return EFI_SUCCESS;
+}
-- 
1.9.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* [PATCH v2 12/12] ARM: add UEFI stub support
@ 2015-11-16 18:32     ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Roy Franz <roy.franz@linaro.org>

This patch adds EFI stub support for the ARM Linux kernel.

The EFI stub operates similarly to the x86 and arm64 stubs: it is a
shim between the EFI firmware and the normal zImage entry point, and
sets up the environment that the zImage is expecting. This includes
optionally loading the initrd and device tree from the system partition
based on the kernel command line.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/Kconfig                          |  19 +++
 arch/arm/boot/compressed/Makefile         |   4 +-
 arch/arm/boot/compressed/efi-header.S     | 130 ++++++++++++++++++++
 arch/arm/boot/compressed/head.S           |  54 +++++++-
 arch/arm/boot/compressed/vmlinux.lds.S    |   7 ++
 arch/arm/include/asm/efi.h                |  23 ++++
 drivers/firmware/efi/libstub/Makefile     |   9 ++
 drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
 drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++++++++++
 9 files changed, 331 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7e338228cc8d..0d84e04cfe48 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2041,6 +2041,25 @@ config AUTO_ZRELADDR
 	  0xf8000000. This assumes the zImage being placed in the first 128MB
 	  from start of memory.
 
+config EFI_STUB
+	bool
+
+config EFI
+	bool "UEFI runtime support"
+	depends on OF && !CPU_BIG_ENDIAN && MMU && AUTO_ZRELADDR && !XIP_KERNEL
+	select UCS2_STRING
+	select EFI_PARAMS_FROM_FDT
+	select EFI_STUB
+	select EFI_ARMSTUB
+	select EFI_RUNTIME_WRAPPERS
+	---help---
+	  This option provides support for runtime services provided
+	  by UEFI firmware (such as non-volatile variables, realtime
+	  clock, and platform reset). A UEFI stub is also provided to
+	  allow the kernel to be booted as an EFI application. This
+	  is only useful for kernels that may run on systems that have
+	  UEFI firmware.
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 3f9a9ebc77c3..4c23a68a0917 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -167,9 +167,11 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
 	false; \
 fi
 
+efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 		$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
-		$(bswapsdi2) FORCE
+		$(bswapsdi2) $(efi-obj-y) FORCE
 	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
new file mode 100644
index 000000000000..9d5dc4fda3c1
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2013-2015 Linaro Ltd
+ * Authors: Roy Franz <roy.franz@linaro.org>
+ *          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.
+ */
+
+		.macro	__nop
+#ifdef CONFIG_EFI_STUB
+		@ This is almost but not quite a NOP, since it does clobber the
+		@ condition flags. But it is the best we can do for EFI, since
+		@ PE/COFF expects the magic string "MZ" at offset 0, while the
+		@ ARM/Linux boot protocol expects an executable instruction
+		@ there.
+		.inst	'M' | ('Z' << 8) | (0x1310 << 16)   @ tstne r0, #0x4d000
+#else
+		mov	r0, r0
+#endif
+		.endm
+
+		.macro	__EFI_HEADER
+#ifdef CONFIG_EFI_STUB
+		b	__efi_start
+
+		.set	start_offset, __efi_start - start
+		.org	start + 0x3c
+		@
+		@ The PE header can be anywhere in the file, but for
+		@ simplicity we keep it together with the MSDOS header
+		@ The offset to the PE/COFF header needs to be at offset
+		@ 0x3C in the MSDOS header.
+		@ The only 2 fields of the MSDOS header that are used are this
+		@ PE/COFF offset, and the "MZ" bytes@offset 0x0.
+		@
+		.long	pe_header - start	@ Offset to the PE header.
+
+pe_header:
+		.ascii	"PE\0\0"
+
+coff_header:
+		.short	0x01c2			@ ARM or Thumb
+		.short	2			@ nr_sections
+		.long	0 			@ TimeDateStamp
+		.long	0			@ PointerToSymbolTable
+		.long	1			@ NumberOfSymbols
+		.short	section_table - optional_header
+						@ SizeOfOptionalHeader
+		.short	0x306			@ Characteristics.
+						@ IMAGE_FILE_32BIT_MACHINE |
+						@ IMAGE_FILE_DEBUG_STRIPPED |
+						@ IMAGE_FILE_EXECUTABLE_IMAGE |
+						@ IMAGE_FILE_LINE_NUMS_STRIPPED
+
+optional_header:
+		.short	0x10b			@ PE32 format
+		.byte	0x02			@ MajorLinkerVersion
+		.byte	0x14			@ MinorLinkerVersion
+		.long	_end - __efi_start	@ SizeOfCode
+		.long	0			@ SizeOfInitializedData
+		.long	0			@ SizeOfUninitializedData
+		.long	efi_stub_entry - start	@ AddressOfEntryPoint
+		.long	start_offset		@ BaseOfCode
+		.long	0			@ data
+
+extra_header_fields:
+		.long	0			@ ImageBase
+		.long	0x200			@ SectionAlignment
+		.long	0x200			@ FileAlignment
+		.short	0			@ MajorOperatingSystemVersion
+		.short	0			@ MinorOperatingSystemVersion
+		.short	0			@ MajorImageVersion
+		.short	0			@ MinorImageVersion
+		.short	0			@ MajorSubsystemVersion
+		.short	0			@ MinorSubsystemVersion
+		.long	0			@ Win32VersionValue
+
+		.long	_end - start		@ SizeOfImage
+		.long	start_offset		@ SizeOfHeaders
+		.long	0			@ CheckSum
+		.short	0xa			@ Subsystem (EFI application)
+		.short	0			@ DllCharacteristics
+		.long	0			@ SizeOfStackReserve
+		.long	0			@ SizeOfStackCommit
+		.long	0			@ SizeOfHeapReserve
+		.long	0			@ SizeOfHeapCommit
+		.long	0			@ LoaderFlags
+		.long	0x6			@ NumberOfRvaAndSizes
+
+		.quad	0			@ ExportTable
+		.quad	0			@ ImportTable
+		.quad	0			@ ResourceTable
+		.quad	0			@ ExceptionTable
+		.quad	0			@ CertificationTable
+		.quad	0			@ BaseRelocationTable
+
+section_table:
+		@
+		@ The EFI application loader requires a relocation section
+		@ because EFI applications must be relocatable. This is a
+		@ dummy section as far as we are concerned.
+		@
+		.ascii	".reloc\0\0"
+		.long	0			@ VirtualSize
+		.long	0			@ VirtualAddress
+		.long	0			@ SizeOfRawData
+		.long	0			@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0x42100040		@ Characteristics
+
+		.ascii	".text\0\0\0"
+		.long	_end - __efi_start	@ VirtualSize
+		.long	__efi_start		@ VirtualAddress
+		.long	_edata - __efi_start	@ SizeOfRawData
+		.long	__efi_start		@ PointerToRawData
+		.long	0			@ PointerToRelocations
+		.long	0			@ PointerToLineNumbers
+		.short	0			@ NumberOfRelocations
+		.short	0			@ NumberOfLineNumbers
+		.long	0xe0500020		@ Characteristics
+
+		.align	9
+__efi_start:
+#endif
+		.endm
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 06e983f59980..af11c2f8f3b7 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -12,6 +12,8 @@
 #include <asm/assembler.h>
 #include <asm/v7m.h>
 
+#include "efi-header.S"
+
  AR_CLASS(	.arch	armv7-a	)
  M_CLASS(	.arch	armv7-m	)
 
@@ -126,7 +128,7 @@
 start:
 		.type	start,#function
 		.rept	7
-		mov	r0, r0
+		__nop
 		.endr
    ARM(		mov	r0, r0		)
    ARM(		b	1f		)
@@ -139,7 +141,8 @@ start:
 		.word	0x04030201	@ endianness flag
 
  THUMB(		.thumb			)
-1:
+1:		__EFI_HEADER
+
  ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
  AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
@@ -1353,6 +1356,53 @@ __enter_kernel:
 
 reloc_code_end:
 
+#ifdef CONFIG_EFI_STUB
+		.align	2
+_start:		.long	start - .
+
+ENTRY(efi_stub_entry)
+		@ allocate space on stack for passing current zImage address
+		@ and for the EFI stub to return of new entry point of
+		@ zImage, as EFI stub may copy the kernel. Pointer address
+		@ is passed in r2. r0 and r1 are passed through from the
+		@ EFI firmware to efi_entry
+		adr	ip, _start
+		ldr	r3, [ip]
+		add	r3, r3, ip
+		stmfd	sp!, {r3, lr}
+		mov	r2, sp			@ pass zImage address in r2
+		bl	efi_entry
+
+		@ Check for error return from EFI stub. r0 has FDT address
+		@ or error code.
+		cmn	r0, #1
+		beq	efi_load_fail
+
+		@ Preserve return value of efi_entry() in r4
+		mov	r4, r0
+		bl	cache_clean_flush
+		bl	cache_off
+
+		@ Set parameters for booting zImage according to boot protocol
+		@ put FDT address in r2, it was returned by efi_entry()
+		@ r1 is the machine type, and r0 needs to be 0
+		mov	r0, #0
+		mov	r1, #0xFFFFFFFF
+		mov	r2, r4
+
+		@ Branch to (possibly) relocated zImage that is in [sp]
+		ldr	lr, [sp]
+		ldr	ip, =start_offset
+		add	lr, lr, ip
+		mov	pc, lr				@ no mode switch
+
+efi_load_fail:
+		@ Return EFI_LOAD_ERROR to EFI firmware on error.
+		ldr	r0, =0x80000001
+		ldmfd	sp!, {ip, pc}
+ENDPROC(efi_stub_entry)
+#endif
+
 		.align
 		.section ".stack", "aw", %nobits
 .L_user_stack:	.space	4096
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 2b60b843ac5e..81c493156ce8 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -48,6 +48,13 @@ SECTIONS
     *(.rodata)
     *(.rodata.*)
   }
+  .data : {
+    /*
+     * The EFI stub always executes from RAM, and runs strictly before the
+     * decompressor, so we can make an exception for its r/w data, and keep it
+     */
+    *(.data.efistub)
+  }
   .piggydata : {
     *(.piggydata)
   }
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 96cac28a6a24..9897235e9186 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -64,4 +64,27 @@ void efi_virtmap_unload(void);
 #define efi_init()
 #endif /* CONFIG_EFI */
 
+/* arch specific definitions used by the stub code */
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
+/*
+ * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
+ * so we will reserve that amount of memory. We have no easy way to tell what
+ * the actuall size of code + data the uncompressed kernel will use.
+ * If this is insufficient, the decompressor will relocate itself out of the
+ * way before performing the decompression.
+ */
+#define MAX_UNCOMP_KERNEL_SIZE	SZ_32M
+
+/*
+ * The kernel zImage should preferably be located between 32 MB and 128 MB
+ * from the base of DRAM. The min address leaves space for a maximal size
+ * uncompressed image, and the max address is due to how the zImage decompressor
+ * picks a destination address.
+ */
+#define ZIMAGE_OFFSET_LIMIT	SZ_128M
+#define MIN_ZIMAGE_OFFSET	MAX_UNCOMP_KERNEL_SIZE
+#define MAX_FDT_OFFSET		ZIMAGE_OFFSET_LIMIT
+
 #endif /* _ASM_ARM_EFI_H */
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 3c0467d3688c..8cf9ccbf42d5 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -34,6 +34,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
+lib-$(CONFIG_ARM)		+= arm32-stub.o
 lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
@@ -67,3 +68,11 @@ quiet_cmd_stubcopy = STUBCPY $@
 		     $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y)	\
 		     && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \
 			 rm -f $@; /bin/false); else /bin/false; fi
+
+#
+# ARM discards the .data section because it disallows r/w data in the
+# decompressor. So move our .data to .data.efistub, which is preserved
+# explicitly by the decompressor linker script.
+#
+STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub
+STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 950c87f5d279..3397902e4040 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -303,8 +303,10 @@ fail:
  * The value chosen is the largest non-zero power of 2 suitable for this purpose
  * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
  * be mapped efficiently.
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
+ * map everything below 1 GB.
  */
-#define EFI_RT_VIRTUAL_BASE	0x40000000
+#define EFI_RT_VIRTUAL_BASE	SZ_512M
 
 static int cmp_mem_desc(const void *l, const void *r)
 {
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
new file mode 100644
index 000000000000..958075a72d72
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 Linaro Ltd;  <roy.franz@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 <asm/efi.h>
+
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+				 unsigned long *image_addr,
+				 unsigned long *image_size,
+				 unsigned long *reserve_addr,
+				 unsigned long *reserve_size,
+				 unsigned long dram_base,
+				 efi_loaded_image_t *image)
+{
+	unsigned long nr_pages;
+	efi_status_t status;
+	/* Use alloc_addr to tranlsate between types */
+	efi_physical_addr_t alloc_addr;
+
+	/*
+	 * Verify that the DRAM base address is compatible with the ARM
+	 * boot protocol, which determines the base of DRAM by masking
+	 * off the low 27 bits of the address at which the zImage is
+	 * loaded. These assumptions are made by the decompressor,
+	 * before any memory map is available.
+	 */
+	dram_base = round_up(dram_base, SZ_128M);
+
+	/*
+	 * Reserve memory for the uncompressed kernel image. This is
+	 * all that prevents any future allocations from conflicting
+	 * with the kernel. Since we can't tell from the compressed
+	 * image how much DRAM the kernel actually uses (due to BSS
+	 * size uncertainty) we allocate the maximum possible size.
+	 * Do this very early, as prints can cause memory allocations
+	 * that may conflict with this.
+	 */
+	alloc_addr = dram_base;
+	*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+	nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS,
+						     EFI_LOADER_DATA,
+						     nr_pages, &alloc_addr);
+	if (status != EFI_SUCCESS) {
+		*reserve_size = 0;
+		pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
+		return status;
+	}
+	*reserve_addr = alloc_addr;
+
+	/*
+	 * Relocate the zImage, if required. ARM doesn't have a
+	 * preferred address, so we set it to 0, as we want to allocate
+	 * as low in memory as possible.
+	 */
+	*image_size = image->image_size;
+	status = efi_relocate_kernel(sys_table, image_addr, *image_size,
+				     *image_size, 0, 0);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err(sys_table, "Failed to relocate kernel.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		return status;
+	}
+
+	/*
+	 * Check to see if we were able to allocate memory low enough
+	 * in memory. The kernel determines the base of DRAM from the
+	 * address at which the zImage is loaded.
+	 */
+	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+		pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
+		efi_free(sys_table, *reserve_size, *reserve_addr);
+		*reserve_size = 0;
+		efi_free(sys_table, *image_size, *image_addr);
+		*image_size = 0;
+		return EFI_LOAD_ERROR;
+	}
+	return EFI_SUCCESS;
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:32   ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:48       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:48 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A, msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
> +/*
> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
> + * non-early mapping of the UEFI system table and virtual mappings for all
> + * EFI_MEMORY_RUNTIME regions.
> + */
> +static int __init arm64_enable_runtime_services(void)
> +{
> +	u64 mapsize;
> +
> +	if (!efi_enabled(EFI_BOOT)) {
> +		pr_info("EFI services will not be available.\n");
> +		return -1;
> +	}
> +
> +	if (efi_runtime_disabled()) {
> +		pr_info("EFI runtime services will be disabled.\n");
> +		return -1;
> +	}
> +
> +	pr_info("Remapping and enabling EFI services.\n");
> +
> +	mapsize = memmap.map_end - memmap.map;
> +	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> +						   mapsize);
> +	if (!memmap.map) {
> +		pr_err("Failed to remap EFI memory map\n");
> +		return -1;
> +	}
> +	memmap.map_end = memmap.map + mapsize;
> +	efi.memmap = &memmap;
> +
> +	efi.systab = (__force void *)ioremap_cache(efi_system_table,
> +						   sizeof(efi_system_table_t));
> +	if (!efi.systab) {
> +		pr_err("Failed to remap EFI System Table\n");
> +		return -1;
> +	}
> +	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +
> +	if (!efi_virtmap_init()) {
> +		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
> +		return -1;
> +	}
> +
> +	/* Set up runtime services function pointers */
> +	efi_native_runtime_setup();
> +	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +
> +	efi.runtime_version = efi.systab->hdr.revision;
> +
> +	return 0;
> +}
> +early_initcall(arm64_enable_runtime_services);

The above ought to be fixed - initcalls return negative errno numbers,
so returning -1 from them is really not acceptable.  (The original code
was doing the same - so it should be fixed as a separate patch.)

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:48       ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:48 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
> +/*
> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
> + * non-early mapping of the UEFI system table and virtual mappings for all
> + * EFI_MEMORY_RUNTIME regions.
> + */
> +static int __init arm64_enable_runtime_services(void)
> +{
> +	u64 mapsize;
> +
> +	if (!efi_enabled(EFI_BOOT)) {
> +		pr_info("EFI services will not be available.\n");
> +		return -1;
> +	}
> +
> +	if (efi_runtime_disabled()) {
> +		pr_info("EFI runtime services will be disabled.\n");
> +		return -1;
> +	}
> +
> +	pr_info("Remapping and enabling EFI services.\n");
> +
> +	mapsize = memmap.map_end - memmap.map;
> +	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> +						   mapsize);
> +	if (!memmap.map) {
> +		pr_err("Failed to remap EFI memory map\n");
> +		return -1;
> +	}
> +	memmap.map_end = memmap.map + mapsize;
> +	efi.memmap = &memmap;
> +
> +	efi.systab = (__force void *)ioremap_cache(efi_system_table,
> +						   sizeof(efi_system_table_t));
> +	if (!efi.systab) {
> +		pr_err("Failed to remap EFI System Table\n");
> +		return -1;
> +	}
> +	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +
> +	if (!efi_virtmap_init()) {
> +		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
> +		return -1;
> +	}
> +
> +	/* Set up runtime services function pointers */
> +	efi_native_runtime_setup();
> +	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +
> +	efi.runtime_version = efi.systab->hdr.revision;
> +
> +	return 0;
> +}
> +early_initcall(arm64_enable_runtime_services);

The above ought to be fixed - initcalls return negative errno numbers,
so returning -1 from them is really not acceptable.  (The original code
was doing the same - so it should be fixed as a separate patch.)

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:48       ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
> +/*
> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
> + * non-early mapping of the UEFI system table and virtual mappings for all
> + * EFI_MEMORY_RUNTIME regions.
> + */
> +static int __init arm64_enable_runtime_services(void)
> +{
> +	u64 mapsize;
> +
> +	if (!efi_enabled(EFI_BOOT)) {
> +		pr_info("EFI services will not be available.\n");
> +		return -1;
> +	}
> +
> +	if (efi_runtime_disabled()) {
> +		pr_info("EFI runtime services will be disabled.\n");
> +		return -1;
> +	}
> +
> +	pr_info("Remapping and enabling EFI services.\n");
> +
> +	mapsize = memmap.map_end - memmap.map;
> +	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> +						   mapsize);
> +	if (!memmap.map) {
> +		pr_err("Failed to remap EFI memory map\n");
> +		return -1;
> +	}
> +	memmap.map_end = memmap.map + mapsize;
> +	efi.memmap = &memmap;
> +
> +	efi.systab = (__force void *)ioremap_cache(efi_system_table,
> +						   sizeof(efi_system_table_t));
> +	if (!efi.systab) {
> +		pr_err("Failed to remap EFI System Table\n");
> +		return -1;
> +	}
> +	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +
> +	if (!efi_virtmap_init()) {
> +		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
> +		return -1;
> +	}
> +
> +	/* Set up runtime services function pointers */
> +	efi_native_runtime_setup();
> +	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +
> +	efi.runtime_version = efi.systab->hdr.revision;
> +
> +	return 0;
> +}
> +early_initcall(arm64_enable_runtime_services);

The above ought to be fixed - initcalls return negative errno numbers,
so returning -1 from them is really not acceptable.  (The original code
was doing the same - so it should be fixed as a separate patch.)

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:32     ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:49         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A, msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> index e62ee5df96ca..ad11ba6964f6 100644
> --- a/drivers/firmware/efi/arm-runtime.c
> +++ b/drivers/firmware/efi/arm-runtime.c
> @@ -23,18 +23,15 @@
>  
>  #include <asm/cacheflush.h>
>  #include <asm/efi.h>
> -#include <asm/tlbflush.h>
> -#include <asm/mmu_context.h>
> +#include <asm/io.h>

Shouldn't this be linux/io.h ?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:49         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> index e62ee5df96ca..ad11ba6964f6 100644
> --- a/drivers/firmware/efi/arm-runtime.c
> +++ b/drivers/firmware/efi/arm-runtime.c
> @@ -23,18 +23,15 @@
>  
>  #include <asm/cacheflush.h>
>  #include <asm/efi.h>
> -#include <asm/tlbflush.h>
> -#include <asm/mmu_context.h>
> +#include <asm/io.h>

Shouldn't this be linux/io.h ?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-16 18:49         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> index e62ee5df96ca..ad11ba6964f6 100644
> --- a/drivers/firmware/efi/arm-runtime.c
> +++ b/drivers/firmware/efi/arm-runtime.c
> @@ -23,18 +23,15 @@
>  
>  #include <asm/cacheflush.h>
>  #include <asm/efi.h>
> -#include <asm/tlbflush.h>
> -#include <asm/mmu_context.h>
> +#include <asm/io.h>

Shouldn't this be linux/io.h ?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
  2015-11-16 18:32     ` Ard Biesheuvel
@ 2015-11-16 18:55       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:55 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:32PM +0100, Ard Biesheuvel wrote:
> In order to be able to reuse the core mapping logic of create_mapping
> for mapping the UEFI Runtime Services into a private set of page tables,
> split it off from create_mapping() into a separate function
> __create_mapping which we will wire up in a subsequent patch.

I'm slightly worried about this.  Generally, these functions setup
global mappings.  If you're wanting to have a private set of page
tables for UEFI, and those private page tables contain global
mappings which are different from the mappings in the kernel's page
tables, then you need careful break-TLBflush-make handling when
switching from the kernel's page tables to the private UEFI ones,
and vice versa.

Has this aspect been considered?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 18:55       ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:32PM +0100, Ard Biesheuvel wrote:
> In order to be able to reuse the core mapping logic of create_mapping
> for mapping the UEFI Runtime Services into a private set of page tables,
> split it off from create_mapping() into a separate function
> __create_mapping which we will wire up in a subsequent patch.

I'm slightly worried about this.  Generally, these functions setup
global mappings.  If you're wanting to have a private set of page
tables for UEFI, and those private page tables contain global
mappings which are different from the mappings in the kernel's page
tables, then you need careful break-TLBflush-make handling when
switching from the kernel's page tables to the private UEFI ones,
and vice versa.

Has this aspect been considered?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  2015-11-16 18:32   ` Ard Biesheuvel
  (?)
@ 2015-11-16 18:58       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:58 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A, msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 07:32:26PM +0100, Ard Biesheuvel wrote:
> This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
> to make it usable as an indicator that some parts of normal memory
> should not be covered by the kernel direct mapping. It is up to the
> arch to actually honor the attribute when laying out this mapping,
> but the memblock code itself is modified to disregard these regions
> for allocations and other general use.

What does NOMAP mean for the rest of the kernel?  Does this mean the
memory is never handed over to the kernel page allocators for kernel
use - in a similar way to what we do with arm_memblock_steal() ?

> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  include/linux/memblock.h |  8 ++++++
>  mm/memblock.c            | 28 ++++++++++++++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 24daf8fc4d7c..fec66f86eeff 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -25,6 +25,7 @@ enum {
>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
>  	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
> +	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>  };
>  
>  struct memblock_region {
> @@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
>  int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> +int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
>  	return m->flags & MEMBLOCK_MIRROR;
>  }
>  
> +static inline bool memblock_is_nomap(struct memblock_region *m)
> +{
> +	return m->flags & MEMBLOCK_NOMAP;
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
>  			    unsigned long  *end_pfn);
> @@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  int memblock_is_memory(phys_addr_t addr);
> +int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
>  int memblock_is_reserved(phys_addr_t addr);
>  bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index d300f1329814..07ff069fef25 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
>  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
>  }
>  
> +/**
> + * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
> +}
>  
>  /**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
> @@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
>  	return memblock_search(&memblock.memory, addr) != -1;
>  }
>  
> +int __init_memblock memblock_is_map_memory(phys_addr_t addr)
> +{
> +	int i = memblock_search(&memblock.memory, addr);
> +
> +	if (i == -1)
> +		return false;
> +	return !memblock_is_nomap(&memblock.memory.regions[i]);
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
>  			 unsigned long *start_pfn, unsigned long *end_pfn)
> -- 
> 1.9.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 18:58       ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:58 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:26PM +0100, Ard Biesheuvel wrote:
> This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
> to make it usable as an indicator that some parts of normal memory
> should not be covered by the kernel direct mapping. It is up to the
> arch to actually honor the attribute when laying out this mapping,
> but the memblock code itself is modified to disregard these regions
> for allocations and other general use.

What does NOMAP mean for the rest of the kernel?  Does this mean the
memory is never handed over to the kernel page allocators for kernel
use - in a similar way to what we do with arm_memblock_steal() ?

> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  include/linux/memblock.h |  8 ++++++
>  mm/memblock.c            | 28 ++++++++++++++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 24daf8fc4d7c..fec66f86eeff 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -25,6 +25,7 @@ enum {
>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
>  	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
> +	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>  };
>  
>  struct memblock_region {
> @@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
>  int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> +int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
>  	return m->flags & MEMBLOCK_MIRROR;
>  }
>  
> +static inline bool memblock_is_nomap(struct memblock_region *m)
> +{
> +	return m->flags & MEMBLOCK_NOMAP;
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
>  			    unsigned long  *end_pfn);
> @@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  int memblock_is_memory(phys_addr_t addr);
> +int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
>  int memblock_is_reserved(phys_addr_t addr);
>  bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index d300f1329814..07ff069fef25 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
>  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
>  }
>  
> +/**
> + * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
> +}
>  
>  /**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
> @@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
>  	return memblock_search(&memblock.memory, addr) != -1;
>  }
>  
> +int __init_memblock memblock_is_map_memory(phys_addr_t addr)
> +{
> +	int i = memblock_search(&memblock.memory, addr);
> +
> +	if (i == -1)
> +		return false;
> +	return !memblock_is_nomap(&memblock.memory.regions[i]);
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
>  			 unsigned long *start_pfn, unsigned long *end_pfn)
> -- 
> 1.9.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 18:58       ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 18:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:26PM +0100, Ard Biesheuvel wrote:
> This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
> to make it usable as an indicator that some parts of normal memory
> should not be covered by the kernel direct mapping. It is up to the
> arch to actually honor the attribute when laying out this mapping,
> but the memblock code itself is modified to disregard these regions
> for allocations and other general use.

What does NOMAP mean for the rest of the kernel?  Does this mean the
memory is never handed over to the kernel page allocators for kernel
use - in a similar way to what we do with arm_memblock_steal() ?

> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  include/linux/memblock.h |  8 ++++++
>  mm/memblock.c            | 28 ++++++++++++++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 24daf8fc4d7c..fec66f86eeff 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -25,6 +25,7 @@ enum {
>  	MEMBLOCK_NONE		= 0x0,	/* No special request */
>  	MEMBLOCK_HOTPLUG	= 0x1,	/* hotpluggable region */
>  	MEMBLOCK_MIRROR		= 0x2,	/* mirrored region */
> +	MEMBLOCK_NOMAP		= 0x4,	/* don't add to kernel direct mapping */
>  };
>  
>  struct memblock_region {
> @@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
>  int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> +int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
>  	return m->flags & MEMBLOCK_MIRROR;
>  }
>  
> +static inline bool memblock_is_nomap(struct memblock_region *m)
> +{
> +	return m->flags & MEMBLOCK_NOMAP;
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
>  			    unsigned long  *end_pfn);
> @@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  int memblock_is_memory(phys_addr_t addr);
> +int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
>  int memblock_is_reserved(phys_addr_t addr);
>  bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index d300f1329814..07ff069fef25 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
>  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
>  }
>  
> +/**
> + * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
> +}
>  
>  /**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
> @@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
>  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>  			continue;
>  
> +		/* skip nomap memory unless we were asked for it explicitly */
> +		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
> +			continue;
> +
>  		if (!type_b) {
>  			if (out_start)
>  				*out_start = m_start;
> @@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
>  	return memblock_search(&memblock.memory, addr) != -1;
>  }
>  
> +int __init_memblock memblock_is_map_memory(phys_addr_t addr)
> +{
> +	int i = memblock_search(&memblock.memory, addr);
> +
> +	if (i == -1)
> +		return false;
> +	return !memblock_is_nomap(&memblock.memory.regions[i]);
> +}
> +
>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
>  			 unsigned long *start_pfn, unsigned long *end_pfn)
> -- 
> 1.9.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
  2015-11-16 18:32     ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:00         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:00 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A, msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 07:32:35PM +0100, Ard Biesheuvel wrote:
> Take the new memblock attribute MEMBLOCK_NOMAP into account when
> deciding whether a certain region is or should be covered by the
> kernel direct mapping.

It's probably worth looking at this as a replacement to the way
arm_memblock_steal() works, provided NOMAP doesn't result in the
memory being passed to the kernel allocators.  Thoughts?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 19:00         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:00 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:35PM +0100, Ard Biesheuvel wrote:
> Take the new memblock attribute MEMBLOCK_NOMAP into account when
> deciding whether a certain region is or should be covered by the
> kernel direct mapping.

It's probably worth looking at this as a replacement to the way
arm_memblock_steal() works, provided NOMAP doesn't result in the
memory being passed to the kernel allocators.  Thoughts?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 19:00         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:35PM +0100, Ard Biesheuvel wrote:
> Take the new memblock attribute MEMBLOCK_NOMAP into account when
> deciding whether a certain region is or should be covered by the
> kernel direct mapping.

It's probably worth looking at this as a replacement to the way
arm_memblock_steal() works, provided NOMAP doesn't result in the
memory being passed to the kernel allocators.  Thoughts?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
  2015-11-16 18:55       ` Russell King - ARM Linux
  (?)
@ 2015-11-16 19:01           ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On 16 November 2015 at 19:55, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Mon, Nov 16, 2015 at 07:32:32PM +0100, Ard Biesheuvel wrote:
>> In order to be able to reuse the core mapping logic of create_mapping
>> for mapping the UEFI Runtime Services into a private set of page tables,
>> split it off from create_mapping() into a separate function
>> __create_mapping which we will wire up in a subsequent patch.
>
> I'm slightly worried about this.  Generally, these functions setup
> global mappings.  If you're wanting to have a private set of page
> tables for UEFI, and those private page tables contain global
> mappings which are different from the mappings in the kernel's page
> tables, then you need careful break-TLBflush-make handling when
> switching from the kernel's page tables to the private UEFI ones,
> and vice versa.
>
> Has this aspect been considered?
>

Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
reused as we do for ordinary userland page tables. The switch to the
UEFI page tables performs a full TLB flush. What it does not do is
break before make, as far as I can tell, so any pointers regarding how
to implement that would be appreciated (this is implemented in 11/12)

-- 
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 19:01           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 19:55, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:32PM +0100, Ard Biesheuvel wrote:
>> In order to be able to reuse the core mapping logic of create_mapping
>> for mapping the UEFI Runtime Services into a private set of page tables,
>> split it off from create_mapping() into a separate function
>> __create_mapping which we will wire up in a subsequent patch.
>
> I'm slightly worried about this.  Generally, these functions setup
> global mappings.  If you're wanting to have a private set of page
> tables for UEFI, and those private page tables contain global
> mappings which are different from the mappings in the kernel's page
> tables, then you need careful break-TLBflush-make handling when
> switching from the kernel's page tables to the private UEFI ones,
> and vice versa.
>
> Has this aspect been considered?
>

Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
reused as we do for ordinary userland page tables. The switch to the
UEFI page tables performs a full TLB flush. What it does not do is
break before make, as far as I can tell, so any pointers regarding how
to implement that would be appreciated (this is implemented in 11/12)

-- 
Ard.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 19:01           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 19:55, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:32PM +0100, Ard Biesheuvel wrote:
>> In order to be able to reuse the core mapping logic of create_mapping
>> for mapping the UEFI Runtime Services into a private set of page tables,
>> split it off from create_mapping() into a separate function
>> __create_mapping which we will wire up in a subsequent patch.
>
> I'm slightly worried about this.  Generally, these functions setup
> global mappings.  If you're wanting to have a private set of page
> tables for UEFI, and those private page tables contain global
> mappings which are different from the mappings in the kernel's page
> tables, then you need careful break-TLBflush-make handling when
> switching from the kernel's page tables to the private UEFI ones,
> and vice versa.
>
> Has this aspect been considered?
>

Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
reused as we do for ordinary userland page tables. The switch to the
UEFI page tables performs a full TLB flush. What it does not do is
break before make, as far as I can tell, so any pointers regarding how
to implement that would be appreciated (this is implemented in 11/12)

-- 
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
  2015-11-16 18:32     ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:01         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:01 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, will.deacon-5wv7dgnIgG8,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, leif.lindholm-QSEj5FYQhm4dnm+yROfE0A,
	roy.franz-QSEj5FYQhm4dnm+yROfE0A, msalter-H+wXaHxf7aLQT0dZR+AlfA,
	ryan.harkin-QSEj5FYQhm4dnm+yROfE0A,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 07:32:36PM +0100, Ard Biesheuvel wrote:
> +static inline void efi_set_pgd(struct mm_struct *mm)
> +{
> +	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
> +		__check_vmalloc_seq(mm);
> +
> +	cpu_switch_mm(mm->pgd, mm);
> +
> +	flush_tlb_all();
> +	if (icache_is_vivt_asid_tagged())
> +		__flush_icache_all();
> +}

I don't think that's sufficient.  There's a gap between switching the mm
and flushing the TLBs where we could have different global TLB entries
from those in the page tables - and that can cause problems with CPUs
which speculatively prefetch.  Some CPUs raise exceptions for this...

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 19:01         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:01 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, Nov 16, 2015 at 07:32:36PM +0100, Ard Biesheuvel wrote:
> +static inline void efi_set_pgd(struct mm_struct *mm)
> +{
> +	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
> +		__check_vmalloc_seq(mm);
> +
> +	cpu_switch_mm(mm->pgd, mm);
> +
> +	flush_tlb_all();
> +	if (icache_is_vivt_asid_tagged())
> +		__flush_icache_all();
> +}

I don't think that's sufficient.  There's a gap between switching the mm
and flushing the TLBs where we could have different global TLB entries
from those in the page tables - and that can cause problems with CPUs
which speculatively prefetch.  Some CPUs raise exceptions for this...

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 19:01         ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 07:32:36PM +0100, Ard Biesheuvel wrote:
> +static inline void efi_set_pgd(struct mm_struct *mm)
> +{
> +	if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
> +		__check_vmalloc_seq(mm);
> +
> +	cpu_switch_mm(mm->pgd, mm);
> +
> +	flush_tlb_all();
> +	if (icache_is_vivt_asid_tagged())
> +		__flush_icache_all();
> +}

I don't think that's sufficient.  There's a gap between switching the mm
and flushing the TLBs where we could have different global TLB entries
from those in the page tables - and that can cause problems with CPUs
which speculatively prefetch.  Some CPUs raise exceptions for this...

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
  2015-11-16 19:00         ` Russell King - ARM Linux
@ 2015-11-16 19:02           ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:02 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 20:00, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:35PM +0100, Ard Biesheuvel wrote:
>> Take the new memblock attribute MEMBLOCK_NOMAP into account when
>> deciding whether a certain region is or should be covered by the
>> kernel direct mapping.
>
> It's probably worth looking at this as a replacement to the way
> arm_memblock_steal() works, provided NOMAP doesn't result in the
> memory being passed to the kernel allocators.  Thoughts?
>

Yes. The primary reason for NOMAP is that the memory is not removed,
so we don't lose the annotation that it is memory (which might be
useful, for instance, for /dev/mem attribute handling)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping
@ 2015-11-16 19:02           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 20:00, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:35PM +0100, Ard Biesheuvel wrote:
>> Take the new memblock attribute MEMBLOCK_NOMAP into account when
>> deciding whether a certain region is or should be covered by the
>> kernel direct mapping.
>
> It's probably worth looking at this as a replacement to the way
> arm_memblock_steal() works, provided NOMAP doesn't result in the
> memory being passed to the kernel allocators.  Thoughts?
>

Yes. The primary reason for NOMAP is that the memory is not removed,
so we don't lose the annotation that it is memory (which might be
useful, for instance, for /dev/mem attribute handling)

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
  2015-11-16 19:01         ` Russell King - ARM Linux
@ 2015-11-16 19:04           ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:04 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 20:01, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:36PM +0100, Ard Biesheuvel wrote:
>> +static inline void efi_set_pgd(struct mm_struct *mm)
>> +{
>> +     if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
>> +             __check_vmalloc_seq(mm);
>> +
>> +     cpu_switch_mm(mm->pgd, mm);
>> +
>> +     flush_tlb_all();
>> +     if (icache_is_vivt_asid_tagged())
>> +             __flush_icache_all();
>> +}
>
> I don't think that's sufficient.  There's a gap between switching the mm
> and flushing the TLBs where we could have different global TLB entries
> from those in the page tables - and that can cause problems with CPUs
> which speculatively prefetch.  Some CPUs raise exceptions for this...
>

OK. So you mean set TTBR to the zero page, perform the TLB flush and
only then switch to the new page tables?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 19:04           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 20:01, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:36PM +0100, Ard Biesheuvel wrote:
>> +static inline void efi_set_pgd(struct mm_struct *mm)
>> +{
>> +     if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
>> +             __check_vmalloc_seq(mm);
>> +
>> +     cpu_switch_mm(mm->pgd, mm);
>> +
>> +     flush_tlb_all();
>> +     if (icache_is_vivt_asid_tagged())
>> +             __flush_icache_all();
>> +}
>
> I don't think that's sufficient.  There's a gap between switching the mm
> and flushing the TLBs where we could have different global TLB entries
> from those in the page tables - and that can cause problems with CPUs
> which speculatively prefetch.  Some CPUs raise exceptions for this...
>

OK. So you mean set TTBR to the zero page, perform the TLB flush and
only then switch to the new page tables?

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  2015-11-16 18:58       ` Russell King - ARM Linux
@ 2015-11-16 19:09         ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:09 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 19:58, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:26PM +0100, Ard Biesheuvel wrote:
>> This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
>> to make it usable as an indicator that some parts of normal memory
>> should not be covered by the kernel direct mapping. It is up to the
>> arch to actually honor the attribute when laying out this mapping,
>> but the memblock code itself is modified to disregard these regions
>> for allocations and other general use.
>
> What does NOMAP mean for the rest of the kernel?  Does this mean the
> memory is never handed over to the kernel page allocators for kernel
> use - in a similar way to what we do with arm_memblock_steal() ?
>

The main difference is that memblock_is_memory() still returns true
for the region. This is useful in some cases, e.g., to decide which
attributes to use when mapping.

>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  include/linux/memblock.h |  8 ++++++
>>  mm/memblock.c            | 28 ++++++++++++++++++++
>>  2 files changed, 36 insertions(+)
>>
>> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>> index 24daf8fc4d7c..fec66f86eeff 100644
>> --- a/include/linux/memblock.h
>> +++ b/include/linux/memblock.h
>> @@ -25,6 +25,7 @@ enum {
>>       MEMBLOCK_NONE           = 0x0,  /* No special request */
>>       MEMBLOCK_HOTPLUG        = 0x1,  /* hotpluggable region */
>>       MEMBLOCK_MIRROR         = 0x2,  /* mirrored region */
>> +     MEMBLOCK_NOMAP          = 0x4,  /* don't add to kernel direct mapping */
>>  };
>>
>>  struct memblock_region {
>> @@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
>>  int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
>> +int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
>>  ulong choose_memblock_flags(void);
>>
>>  /* Low level functions */
>> @@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
>>       return m->flags & MEMBLOCK_MIRROR;
>>  }
>>
>> +static inline bool memblock_is_nomap(struct memblock_region *m)
>> +{
>> +     return m->flags & MEMBLOCK_NOMAP;
>> +}
>> +
>>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>>  int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
>>                           unsigned long  *end_pfn);
>> @@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>>  phys_addr_t memblock_end_of_DRAM(void);
>>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>>  int memblock_is_memory(phys_addr_t addr);
>> +int memblock_is_map_memory(phys_addr_t addr);
>>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
>>  int memblock_is_reserved(phys_addr_t addr);
>>  bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
>> diff --git a/mm/memblock.c b/mm/memblock.c
>> index d300f1329814..07ff069fef25 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
>>       return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
>>  }
>>
>> +/**
>> + * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
>> + * @base: the base phys addr of the region
>> + * @size: the size of the region
>> + *
>> + * Return 0 on success, -errno on failure.
>> + */
>> +int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
>> +{
>> +     return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
>> +}
>>
>>  /**
>>   * __next_reserved_mem_region - next function for for_each_reserved_region()
>> @@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
>>               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>>                       continue;
>>
>> +             /* skip nomap memory unless we were asked for it explicitly */
>> +             if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
>> +                     continue;
>> +
>>               if (!type_b) {
>>                       if (out_start)
>>                               *out_start = m_start;
>> @@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
>>               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>>                       continue;
>>
>> +             /* skip nomap memory unless we were asked for it explicitly */
>> +             if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
>> +                     continue;
>> +
>>               if (!type_b) {
>>                       if (out_start)
>>                               *out_start = m_start;
>> @@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
>>       return memblock_search(&memblock.memory, addr) != -1;
>>  }
>>
>> +int __init_memblock memblock_is_map_memory(phys_addr_t addr)
>> +{
>> +     int i = memblock_search(&memblock.memory, addr);
>> +
>> +     if (i == -1)
>> +             return false;
>> +     return !memblock_is_nomap(&memblock.memory.regions[i]);
>> +}
>> +
>>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>>  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
>>                        unsigned long *start_pfn, unsigned long *end_pfn)
>> --
>> 1.9.1
>>
>
> --
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 19:09         ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 19:58, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:26PM +0100, Ard Biesheuvel wrote:
>> This introduces the MEMBLOCK_NOMAP attribute and the required plumbing
>> to make it usable as an indicator that some parts of normal memory
>> should not be covered by the kernel direct mapping. It is up to the
>> arch to actually honor the attribute when laying out this mapping,
>> but the memblock code itself is modified to disregard these regions
>> for allocations and other general use.
>
> What does NOMAP mean for the rest of the kernel?  Does this mean the
> memory is never handed over to the kernel page allocators for kernel
> use - in a similar way to what we do with arm_memblock_steal() ?
>

The main difference is that memblock_is_memory() still returns true
for the region. This is useful in some cases, e.g., to decide which
attributes to use when mapping.

>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  include/linux/memblock.h |  8 ++++++
>>  mm/memblock.c            | 28 ++++++++++++++++++++
>>  2 files changed, 36 insertions(+)
>>
>> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
>> index 24daf8fc4d7c..fec66f86eeff 100644
>> --- a/include/linux/memblock.h
>> +++ b/include/linux/memblock.h
>> @@ -25,6 +25,7 @@ enum {
>>       MEMBLOCK_NONE           = 0x0,  /* No special request */
>>       MEMBLOCK_HOTPLUG        = 0x1,  /* hotpluggable region */
>>       MEMBLOCK_MIRROR         = 0x2,  /* mirrored region */
>> +     MEMBLOCK_NOMAP          = 0x4,  /* don't add to kernel direct mapping */
>>  };
>>
>>  struct memblock_region {
>> @@ -82,6 +83,7 @@ bool memblock_overlaps_region(struct memblock_type *type,
>>  int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
>> +int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
>>  ulong choose_memblock_flags(void);
>>
>>  /* Low level functions */
>> @@ -184,6 +186,11 @@ static inline bool memblock_is_mirror(struct memblock_region *m)
>>       return m->flags & MEMBLOCK_MIRROR;
>>  }
>>
>> +static inline bool memblock_is_nomap(struct memblock_region *m)
>> +{
>> +     return m->flags & MEMBLOCK_NOMAP;
>> +}
>> +
>>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>>  int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
>>                           unsigned long  *end_pfn);
>> @@ -319,6 +326,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>>  phys_addr_t memblock_end_of_DRAM(void);
>>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>>  int memblock_is_memory(phys_addr_t addr);
>> +int memblock_is_map_memory(phys_addr_t addr);
>>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
>>  int memblock_is_reserved(phys_addr_t addr);
>>  bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
>> diff --git a/mm/memblock.c b/mm/memblock.c
>> index d300f1329814..07ff069fef25 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -822,6 +822,17 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
>>       return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
>>  }
>>
>> +/**
>> + * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
>> + * @base: the base phys addr of the region
>> + * @size: the size of the region
>> + *
>> + * Return 0 on success, -errno on failure.
>> + */
>> +int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
>> +{
>> +     return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
>> +}
>>
>>  /**
>>   * __next_reserved_mem_region - next function for for_each_reserved_region()
>> @@ -913,6 +924,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
>>               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>>                       continue;
>>
>> +             /* skip nomap memory unless we were asked for it explicitly */
>> +             if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
>> +                     continue;
>> +
>>               if (!type_b) {
>>                       if (out_start)
>>                               *out_start = m_start;
>> @@ -1022,6 +1037,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
>>               if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
>>                       continue;
>>
>> +             /* skip nomap memory unless we were asked for it explicitly */
>> +             if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
>> +                     continue;
>> +
>>               if (!type_b) {
>>                       if (out_start)
>>                               *out_start = m_start;
>> @@ -1519,6 +1538,15 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
>>       return memblock_search(&memblock.memory, addr) != -1;
>>  }
>>
>> +int __init_memblock memblock_is_map_memory(phys_addr_t addr)
>> +{
>> +     int i = memblock_search(&memblock.memory, addr);
>> +
>> +     if (i == -1)
>> +             return false;
>> +     return !memblock_is_nomap(&memblock.memory.regions[i]);
>> +}
>> +
>>  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
>>  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
>>                        unsigned long *start_pfn, unsigned long *end_pfn)
>> --
>> 1.9.1
>>
>
> --
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
  2015-11-16 19:01           ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:45               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:45 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 08:01:03PM +0100, Ard Biesheuvel wrote:
> On 16 November 2015 at 19:55, Russell King - ARM Linux
> <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> > I'm slightly worried about this.  Generally, these functions setup
> > global mappings.  If you're wanting to have a private set of page
> > tables for UEFI, and those private page tables contain global
> > mappings which are different from the mappings in the kernel's page
> > tables, then you need careful break-TLBflush-make handling when
> > switching from the kernel's page tables to the private UEFI ones,
> > and vice versa.
> >
> > Has this aspect been considered?
> 
> Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
> reused as we do for ordinary userland page tables. The switch to the
> UEFI page tables performs a full TLB flush. What it does not do is
> break before make, as far as I can tell, so any pointers regarding how
> to implement that would be appreciated (this is implemented in 11/12)

What matters is whether they are global mappings or not.  If they are,
when the TLB can contain conflicting entries.  If they are non-global
mappings, they will be tagged with the ASID which makes them unique
to each mm.

The simple solution is to ensure that they're non-global, and then you
don't need to even worry about flushing the TLB when switching.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 19:45               ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:45 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On Mon, Nov 16, 2015 at 08:01:03PM +0100, Ard Biesheuvel wrote:
> On 16 November 2015 at 19:55, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > I'm slightly worried about this.  Generally, these functions setup
> > global mappings.  If you're wanting to have a private set of page
> > tables for UEFI, and those private page tables contain global
> > mappings which are different from the mappings in the kernel's page
> > tables, then you need careful break-TLBflush-make handling when
> > switching from the kernel's page tables to the private UEFI ones,
> > and vice versa.
> >
> > Has this aspect been considered?
> 
> Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
> reused as we do for ordinary userland page tables. The switch to the
> UEFI page tables performs a full TLB flush. What it does not do is
> break before make, as far as I can tell, so any pointers regarding how
> to implement that would be appreciated (this is implemented in 11/12)

What matters is whether they are global mappings or not.  If they are,
when the TLB can contain conflicting entries.  If they are non-global
mappings, they will be tagged with the ASID which makes them unique
to each mm.

The simple solution is to ensure that they're non-global, and then you
don't need to even worry about flushing the TLB when switching.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping
@ 2015-11-16 19:45               ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 08:01:03PM +0100, Ard Biesheuvel wrote:
> On 16 November 2015 at 19:55, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > I'm slightly worried about this.  Generally, these functions setup
> > global mappings.  If you're wanting to have a private set of page
> > tables for UEFI, and those private page tables contain global
> > mappings which are different from the mappings in the kernel's page
> > tables, then you need careful break-TLBflush-make handling when
> > switching from the kernel's page tables to the private UEFI ones,
> > and vice versa.
> >
> > Has this aspect been considered?
> 
> Yes. The UEFI mappings are all below 1 GB, and the top kernel end is
> reused as we do for ordinary userland page tables. The switch to the
> UEFI page tables performs a full TLB flush. What it does not do is
> break before make, as far as I can tell, so any pointers regarding how
> to implement that would be appreciated (this is implemented in 11/12)

What matters is whether they are global mappings or not.  If they are,
when the TLB can contain conflicting entries.  If they are non-global
mappings, they will be tagged with the ASID which makes them unique
to each mm.

The simple solution is to ensure that they're non-global, and then you
don't need to even worry about flushing the TLB when switching.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
  2015-11-16 19:04           ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:48               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:48 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
> OK. So you mean set TTBR to the zero page, perform the TLB flush and
> only then switch to the new page tables?

Not quite.

If you have global mappings below TASK_SIZE, you would need this
sequence when switching either to or from the UEFI page tables:

- switch to another set of page tables which only map kernel space
  with nothing at all in userspace.
- flush the TLB.
- switch to your target page tables.

As I say in response to one of your other patches, it's probably
much easier to avoid any global mappings below TASK_SIZE.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 19:48               ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:48 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
> OK. So you mean set TTBR to the zero page, perform the TLB flush and
> only then switch to the new page tables?

Not quite.

If you have global mappings below TASK_SIZE, you would need this
sequence when switching either to or from the UEFI page tables:

- switch to another set of page tables which only map kernel space
  with nothing at all in userspace.
- flush the TLB.
- switch to your target page tables.

As I say in response to one of your other patches, it's probably
much easier to avoid any global mappings below TASK_SIZE.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-16 19:48               ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
> OK. So you mean set TTBR to the zero page, perform the TLB flush and
> only then switch to the new page tables?

Not quite.

If you have global mappings below TASK_SIZE, you would need this
sequence when switching either to or from the UEFI page tables:

- switch to another set of page tables which only map kernel space
  with nothing at all in userspace.
- flush the TLB.
- switch to your target page tables.

As I say in response to one of your other patches, it's probably
much easier to avoid any global mappings below TASK_SIZE.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  2015-11-16 19:09         ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:49             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
> The main difference is that memblock_is_memory() still returns true
> for the region. This is useful in some cases, e.g., to decide which
> attributes to use when mapping.

Ok, so we'd need to switch to using memblock_is_map_memory() instead
for pfn_valid() then.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 19:49             ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
> The main difference is that memblock_is_memory() still returns true
> for the region. This is useful in some cases, e.g., to decide which
> attributes to use when mapping.

Ok, so we'd need to switch to using memblock_is_map_memory() instead
for pfn_valid() then.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 19:49             ` Russell King - ARM Linux
  0 siblings, 0 replies; 94+ messages in thread
From: Russell King - ARM Linux @ 2015-11-16 19:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
> The main difference is that memblock_is_memory() still returns true
> for the region. This is useful in some cases, e.g., to decide which
> attributes to use when mapping.

Ok, so we'd need to switch to using memblock_is_map_memory() instead
for pfn_valid() then.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
  2015-11-16 18:32 ` Ard Biesheuvel
  (?)
@ 2015-11-16 19:50     ` Ryan Harkin
  -1 siblings, 0 replies; 94+ messages in thread
From: Ryan Harkin @ 2015-11-16 19:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

Hi Ard,

On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> This series adds support for booting the 32-bit ARM kernel directly from
> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
> code, and the differences (primarily the PE/COFF header and entry point and
> the efi_create_mapping() implementation) are split out into arm64 and ARM
> versions.
>
> Changes since v1:
> - The primary difference between this version and the first one is that all
>   prerequisites have either been merged, dropped for now (early FDT handling)
>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>   on top of v4.4-rc1 directly.
> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>   better in the next version of the spec.
>
> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
> code. Its purpose is to annotate memory regions as normal memory even if they
> are removed from the kernel direct mapping.
>
> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>
> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
> used by runtime services from the kernel direct mapping
>
> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>
> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>
> Patch #6 enables the generic early_ioremap and early_memremap implementations
> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>
> Patch #7 splits off the core functionality of create_mapping() into a new
> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>
> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
> using another (late) allocator.
>
> Patch #9 implements create_mapping_late() that uses a late allocator.
>
> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>
> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
> memory map and map the runtime services.
>
> Patch #12 ties together all of the above, by implementing the UEFI stub, and
> introducing the Kconfig symbols that allow all of this to be built.
>
> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
> https://wiki.linaro.org/LEG/UEFIforQEMU
>
> Ard Biesheuvel (11):
>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>   ARM: add support for generic early_ioremap/early_memremap
>   ARM: split off core mapping logic from create_mapping
>   ARM: factor out allocation routine from __create_mapping()
>   ARM: implement create_mapping_late() for EFI use
>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>   ARM: wire up UEFI init and runtime support
>
> Roy Franz (1):
>   ARM: add UEFI stub support
>
>  arch/arm/Kconfig                          |  20 ++
>  arch/arm/boot/compressed/Makefile         |   4 +-
>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>  arch/arm/boot/compressed/head.S           |  54 +++-
>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>  arch/arm/include/asm/Kbuild               |   1 +
>  arch/arm/include/asm/efi.h                |  90 ++++++
>  arch/arm/include/asm/fixmap.h             |  29 +-
>  arch/arm/include/asm/mach/map.h           |   1 +
>  arch/arm/kernel/Makefile                  |   1 +
>  arch/arm/kernel/efi.c                     |  38 +++
>  arch/arm/kernel/setup.c                   |  10 +-
>  arch/arm/mm/init.c                        |   5 +-
>  arch/arm/mm/ioremap.c                     |   9 +
>  arch/arm/mm/mmu.c                         | 110 ++++---
>  arch/arm64/include/asm/efi.h              |  16 +
>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>  arch/arm64/mm/init.c                      |   2 +-
>  arch/arm64/mm/mmu.c                       |   2 +
>  drivers/firmware/efi/Makefile             |   4 +
>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>  drivers/firmware/efi/efi.c                |   2 +
>  drivers/firmware/efi/libstub/Makefile     |   9 +
>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>  include/linux/memblock.h                  |   8 +
>  mm/memblock.c                             |  28 ++
>  28 files changed, 975 insertions(+), 356 deletions(-)
>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>  create mode 100644 arch/arm/include/asm/efi.h
>  create mode 100644 arch/arm/kernel/efi.c
>  create mode 100644 drivers/firmware/efi/arm-init.c
>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>
> --
> 1.9.1
>

I've tested this series against 4.4-rc1 on Versatile Express TC2,
booting both as a "regular" kernel and as a EFI Stub on BusyBox and
OpenEmbedded.  So if it helps any, you can add my:

Tested-by: Ryan Harkin <ryan.harkin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

I'm afraid I'm not knowledgeable enough to review the code.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-16 19:50     ` Ryan Harkin
  0 siblings, 0 replies; 94+ messages in thread
From: Ryan Harkin @ 2015-11-16 19:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, akpm, linux-mm

Hi Ard,

On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This series adds support for booting the 32-bit ARM kernel directly from
> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
> code, and the differences (primarily the PE/COFF header and entry point and
> the efi_create_mapping() implementation) are split out into arm64 and ARM
> versions.
>
> Changes since v1:
> - The primary difference between this version and the first one is that all
>   prerequisites have either been merged, dropped for now (early FDT handling)
>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>   on top of v4.4-rc1 directly.
> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>   better in the next version of the spec.
>
> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
> code. Its purpose is to annotate memory regions as normal memory even if they
> are removed from the kernel direct mapping.
>
> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>
> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
> used by runtime services from the kernel direct mapping
>
> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>
> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>
> Patch #6 enables the generic early_ioremap and early_memremap implementations
> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>
> Patch #7 splits off the core functionality of create_mapping() into a new
> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>
> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
> using another (late) allocator.
>
> Patch #9 implements create_mapping_late() that uses a late allocator.
>
> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>
> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
> memory map and map the runtime services.
>
> Patch #12 ties together all of the above, by implementing the UEFI stub, and
> introducing the Kconfig symbols that allow all of this to be built.
>
> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
> https://wiki.linaro.org/LEG/UEFIforQEMU
>
> Ard Biesheuvel (11):
>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>   ARM: add support for generic early_ioremap/early_memremap
>   ARM: split off core mapping logic from create_mapping
>   ARM: factor out allocation routine from __create_mapping()
>   ARM: implement create_mapping_late() for EFI use
>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>   ARM: wire up UEFI init and runtime support
>
> Roy Franz (1):
>   ARM: add UEFI stub support
>
>  arch/arm/Kconfig                          |  20 ++
>  arch/arm/boot/compressed/Makefile         |   4 +-
>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>  arch/arm/boot/compressed/head.S           |  54 +++-
>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>  arch/arm/include/asm/Kbuild               |   1 +
>  arch/arm/include/asm/efi.h                |  90 ++++++
>  arch/arm/include/asm/fixmap.h             |  29 +-
>  arch/arm/include/asm/mach/map.h           |   1 +
>  arch/arm/kernel/Makefile                  |   1 +
>  arch/arm/kernel/efi.c                     |  38 +++
>  arch/arm/kernel/setup.c                   |  10 +-
>  arch/arm/mm/init.c                        |   5 +-
>  arch/arm/mm/ioremap.c                     |   9 +
>  arch/arm/mm/mmu.c                         | 110 ++++---
>  arch/arm64/include/asm/efi.h              |  16 +
>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>  arch/arm64/mm/init.c                      |   2 +-
>  arch/arm64/mm/mmu.c                       |   2 +
>  drivers/firmware/efi/Makefile             |   4 +
>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>  drivers/firmware/efi/efi.c                |   2 +
>  drivers/firmware/efi/libstub/Makefile     |   9 +
>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>  include/linux/memblock.h                  |   8 +
>  mm/memblock.c                             |  28 ++
>  28 files changed, 975 insertions(+), 356 deletions(-)
>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>  create mode 100644 arch/arm/include/asm/efi.h
>  create mode 100644 arch/arm/kernel/efi.c
>  create mode 100644 drivers/firmware/efi/arm-init.c
>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>
> --
> 1.9.1
>

I've tested this series against 4.4-rc1 on Versatile Express TC2,
booting both as a "regular" kernel and as a EFI Stub on BusyBox and
OpenEmbedded.  So if it helps any, you can add my:

Tested-by: Ryan Harkin <ryan.harkin@linaro.org>

I'm afraid I'm not knowledgeable enough to review the code.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-16 19:50     ` Ryan Harkin
  0 siblings, 0 replies; 94+ messages in thread
From: Ryan Harkin @ 2015-11-16 19:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ard,

On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This series adds support for booting the 32-bit ARM kernel directly from
> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
> code, and the differences (primarily the PE/COFF header and entry point and
> the efi_create_mapping() implementation) are split out into arm64 and ARM
> versions.
>
> Changes since v1:
> - The primary difference between this version and the first one is that all
>   prerequisites have either been merged, dropped for now (early FDT handling)
>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>   on top of v4.4-rc1 directly.
> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>   better in the next version of the spec.
>
> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
> code. Its purpose is to annotate memory regions as normal memory even if they
> are removed from the kernel direct mapping.
>
> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>
> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
> used by runtime services from the kernel direct mapping
>
> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>
> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>
> Patch #6 enables the generic early_ioremap and early_memremap implementations
> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>
> Patch #7 splits off the core functionality of create_mapping() into a new
> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>
> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
> using another (late) allocator.
>
> Patch #9 implements create_mapping_late() that uses a late allocator.
>
> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>
> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
> memory map and map the runtime services.
>
> Patch #12 ties together all of the above, by implementing the UEFI stub, and
> introducing the Kconfig symbols that allow all of this to be built.
>
> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
> https://wiki.linaro.org/LEG/UEFIforQEMU
>
> Ard Biesheuvel (11):
>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>   ARM: add support for generic early_ioremap/early_memremap
>   ARM: split off core mapping logic from create_mapping
>   ARM: factor out allocation routine from __create_mapping()
>   ARM: implement create_mapping_late() for EFI use
>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>   ARM: wire up UEFI init and runtime support
>
> Roy Franz (1):
>   ARM: add UEFI stub support
>
>  arch/arm/Kconfig                          |  20 ++
>  arch/arm/boot/compressed/Makefile         |   4 +-
>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>  arch/arm/boot/compressed/head.S           |  54 +++-
>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>  arch/arm/include/asm/Kbuild               |   1 +
>  arch/arm/include/asm/efi.h                |  90 ++++++
>  arch/arm/include/asm/fixmap.h             |  29 +-
>  arch/arm/include/asm/mach/map.h           |   1 +
>  arch/arm/kernel/Makefile                  |   1 +
>  arch/arm/kernel/efi.c                     |  38 +++
>  arch/arm/kernel/setup.c                   |  10 +-
>  arch/arm/mm/init.c                        |   5 +-
>  arch/arm/mm/ioremap.c                     |   9 +
>  arch/arm/mm/mmu.c                         | 110 ++++---
>  arch/arm64/include/asm/efi.h              |  16 +
>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>  arch/arm64/mm/init.c                      |   2 +-
>  arch/arm64/mm/mmu.c                       |   2 +
>  drivers/firmware/efi/Makefile             |   4 +
>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>  drivers/firmware/efi/efi.c                |   2 +
>  drivers/firmware/efi/libstub/Makefile     |   9 +
>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>  include/linux/memblock.h                  |   8 +
>  mm/memblock.c                             |  28 ++
>  28 files changed, 975 insertions(+), 356 deletions(-)
>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>  create mode 100644 arch/arm/include/asm/efi.h
>  create mode 100644 arch/arm/kernel/efi.c
>  create mode 100644 drivers/firmware/efi/arm-init.c
>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>
> --
> 1.9.1
>

I've tested this series against 4.4-rc1 on Versatile Express TC2,
booting both as a "regular" kernel and as a EFI Stub on BusyBox and
OpenEmbedded.  So if it helps any, you can add my:

Tested-by: Ryan Harkin <ryan.harkin@linaro.org>

I'm afraid I'm not knowledgeable enough to review the code.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
  2015-11-16 19:49             ` Russell King - ARM Linux
  (?)
@ 2015-11-16 20:33                 ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 20:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg



> On 16 nov. 2015, at 20:49, Russell King - ARM Linux <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> 
>> On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
>> The main difference is that memblock_is_memory() still returns true
>> for the region. This is useful in some cases, e.g., to decide which
>> attributes to use when mapping.
> 
> Ok, so we'd need to switch to using memblock_is_map_memory() instead
> for pfn_valid() then.

Indeed, as is implemented by 10/12

> -- 
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 20:33                 ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 20:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm



> On 16 nov. 2015, at 20:49, Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
>> On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
>> The main difference is that memblock_is_memory() still returns true
>> for the region. This is useful in some cases, e.g., to decide which
>> attributes to use when mapping.
> 
> Ok, so we'd need to switch to using memblock_is_map_memory() instead
> for pfn_valid() then.

Indeed, as is implemented by 10/12

> -- 
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
@ 2015-11-16 20:33                 ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-16 20:33 UTC (permalink / raw)
  To: linux-arm-kernel



> On 16 nov. 2015, at 20:49, Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
>> On Mon, Nov 16, 2015 at 08:09:38PM +0100, Ard Biesheuvel wrote:
>> The main difference is that memblock_is_memory() still returns true
>> for the region. This is useful in some cases, e.g., to decide which
>> attributes to use when mapping.
> 
> Ok, so we'd need to switch to using memblock_is_map_memory() instead
> for pfn_valid() then.

Indeed, as is implemented by 10/12

> -- 
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
  2015-11-16 19:48               ` Russell King - ARM Linux
  (?)
@ 2015-11-17  5:33                   ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  5:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On 16 November 2015 at 20:48, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
>> OK. So you mean set TTBR to the zero page, perform the TLB flush and
>> only then switch to the new page tables?
>
> Not quite.
>
> If you have global mappings below TASK_SIZE, you would need this
> sequence when switching either to or from the UEFI page tables:
>
> - switch to another set of page tables which only map kernel space
>   with nothing at all in userspace.
> - flush the TLB.
> - switch to your target page tables.
>

Doh. I am so used to always having two TTBR's available, but indeed,
we shouldn't pull the rug from under our feet.

> As I say in response to one of your other patches, it's probably
> much easier to avoid any global mappings below TASK_SIZE.

Let me look into that.

Thanks,
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-17  5:33                   ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  5:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 20:48, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
>> OK. So you mean set TTBR to the zero page, perform the TLB flush and
>> only then switch to the new page tables?
>
> Not quite.
>
> If you have global mappings below TASK_SIZE, you would need this
> sequence when switching either to or from the UEFI page tables:
>
> - switch to another set of page tables which only map kernel space
>   with nothing at all in userspace.
> - flush the TLB.
> - switch to your target page tables.
>

Doh. I am so used to always having two TTBR's available, but indeed,
we shouldn't pull the rug from under our feet.

> As I say in response to one of your other patches, it's probably
> much easier to avoid any global mappings below TASK_SIZE.

Let me look into that.

Thanks,
Ard.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 11/12] ARM: wire up UEFI init and runtime support
@ 2015-11-17  5:33                   ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  5:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 20:48, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 08:04:00PM +0100, Ard Biesheuvel wrote:
>> OK. So you mean set TTBR to the zero page, perform the TLB flush and
>> only then switch to the new page tables?
>
> Not quite.
>
> If you have global mappings below TASK_SIZE, you would need this
> sequence when switching either to or from the UEFI page tables:
>
> - switch to another set of page tables which only map kernel space
>   with nothing at all in userspace.
> - flush the TLB.
> - switch to your target page tables.
>

Doh. I am so used to always having two TTBR's available, but indeed,
we shouldn't pull the rug from under our feet.

> As I say in response to one of your other patches, it's probably
> much easier to avoid any global mappings below TASK_SIZE.

Let me look into that.

Thanks,
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:49         ` Russell King - ARM Linux
  (?)
@ 2015-11-17  9:18             ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On 16 November 2015 at 19:49, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
>> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
>> index e62ee5df96ca..ad11ba6964f6 100644
>> --- a/drivers/firmware/efi/arm-runtime.c
>> +++ b/drivers/firmware/efi/arm-runtime.c
>> @@ -23,18 +23,15 @@
>>
>>  #include <asm/cacheflush.h>
>>  #include <asm/efi.h>
>> -#include <asm/tlbflush.h>
>> -#include <asm/mmu_context.h>
>> +#include <asm/io.h>
>
> Shouldn't this be linux/io.h ?
>

Yes. Will change it for v3

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-17  9:18             ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 19:49, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
>> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
>> index e62ee5df96ca..ad11ba6964f6 100644
>> --- a/drivers/firmware/efi/arm-runtime.c
>> +++ b/drivers/firmware/efi/arm-runtime.c
>> @@ -23,18 +23,15 @@
>>
>>  #include <asm/cacheflush.h>
>>  #include <asm/efi.h>
>> -#include <asm/tlbflush.h>
>> -#include <asm/mmu_context.h>
>> +#include <asm/io.h>
>
> Shouldn't this be linux/io.h ?
>

Yes. Will change it for v3

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-17  9:18             ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 19:49, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:30PM +0100, Ard Biesheuvel wrote:
>> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
>> index e62ee5df96ca..ad11ba6964f6 100644
>> --- a/drivers/firmware/efi/arm-runtime.c
>> +++ b/drivers/firmware/efi/arm-runtime.c
>> @@ -23,18 +23,15 @@
>>
>>  #include <asm/cacheflush.h>
>>  #include <asm/efi.h>
>> -#include <asm/tlbflush.h>
>> -#include <asm/mmu_context.h>
>> +#include <asm/io.h>
>
> Shouldn't this be linux/io.h ?
>

Yes. Will change it for v3

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:48       ` Russell King - ARM Linux
  (?)
@ 2015-11-17  9:21           ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:21 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On 16 November 2015 at 19:48, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
>> +/*
>> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
>> + * non-early mapping of the UEFI system table and virtual mappings for all
>> + * EFI_MEMORY_RUNTIME regions.
>> + */
>> +static int __init arm64_enable_runtime_services(void)
>> +{
>> +     u64 mapsize;
>> +
>> +     if (!efi_enabled(EFI_BOOT)) {
>> +             pr_info("EFI services will not be available.\n");
>> +             return -1;
>> +     }
>> +
>> +     if (efi_runtime_disabled()) {
>> +             pr_info("EFI runtime services will be disabled.\n");
>> +             return -1;
>> +     }
>> +
>> +     pr_info("Remapping and enabling EFI services.\n");
>> +
>> +     mapsize = memmap.map_end - memmap.map;
>> +     memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
>> +                                                mapsize);
>> +     if (!memmap.map) {
>> +             pr_err("Failed to remap EFI memory map\n");
>> +             return -1;
>> +     }
>> +     memmap.map_end = memmap.map + mapsize;
>> +     efi.memmap = &memmap;
>> +
>> +     efi.systab = (__force void *)ioremap_cache(efi_system_table,
>> +                                                sizeof(efi_system_table_t));
>> +     if (!efi.systab) {
>> +             pr_err("Failed to remap EFI System Table\n");
>> +             return -1;
>> +     }
>> +     set_bit(EFI_SYSTEM_TABLES, &efi.flags);
>> +
>> +     if (!efi_virtmap_init()) {
>> +             pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
>> +             return -1;
>> +     }
>> +
>> +     /* Set up runtime services function pointers */
>> +     efi_native_runtime_setup();
>> +     set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
>> +
>> +     efi.runtime_version = efi.systab->hdr.revision;
>> +
>> +     return 0;
>> +}
>> +early_initcall(arm64_enable_runtime_services);
>
> The above ought to be fixed - initcalls return negative errno numbers,
> so returning -1 from them is really not acceptable.  (The original code
> was doing the same - so it should be fixed as a separate patch.)
>

Indeed. I will add a patch to v3 to address this.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-17  9:21           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:21 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-efi, Matt Fleming, Will Deacon,
	Grant Likely, Catalin Marinas, Mark Rutland, Leif Lindholm,
	Roy Franz, Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

On 16 November 2015 at 19:48, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
>> +/*
>> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
>> + * non-early mapping of the UEFI system table and virtual mappings for all
>> + * EFI_MEMORY_RUNTIME regions.
>> + */
>> +static int __init arm64_enable_runtime_services(void)
>> +{
>> +     u64 mapsize;
>> +
>> +     if (!efi_enabled(EFI_BOOT)) {
>> +             pr_info("EFI services will not be available.\n");
>> +             return -1;
>> +     }
>> +
>> +     if (efi_runtime_disabled()) {
>> +             pr_info("EFI runtime services will be disabled.\n");
>> +             return -1;
>> +     }
>> +
>> +     pr_info("Remapping and enabling EFI services.\n");
>> +
>> +     mapsize = memmap.map_end - memmap.map;
>> +     memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
>> +                                                mapsize);
>> +     if (!memmap.map) {
>> +             pr_err("Failed to remap EFI memory map\n");
>> +             return -1;
>> +     }
>> +     memmap.map_end = memmap.map + mapsize;
>> +     efi.memmap = &memmap;
>> +
>> +     efi.systab = (__force void *)ioremap_cache(efi_system_table,
>> +                                                sizeof(efi_system_table_t));
>> +     if (!efi.systab) {
>> +             pr_err("Failed to remap EFI System Table\n");
>> +             return -1;
>> +     }
>> +     set_bit(EFI_SYSTEM_TABLES, &efi.flags);
>> +
>> +     if (!efi_virtmap_init()) {
>> +             pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
>> +             return -1;
>> +     }
>> +
>> +     /* Set up runtime services function pointers */
>> +     efi_native_runtime_setup();
>> +     set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
>> +
>> +     efi.runtime_version = efi.systab->hdr.revision;
>> +
>> +     return 0;
>> +}
>> +early_initcall(arm64_enable_runtime_services);
>
> The above ought to be fixed - initcalls return negative errno numbers,
> so returning -1 from them is really not acceptable.  (The original code
> was doing the same - so it should be fixed as a separate patch.)
>

Indeed. I will add a patch to v3 to address this.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-17  9:21           ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 19:48, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Nov 16, 2015 at 07:32:29PM +0100, Ard Biesheuvel wrote:
>> +/*
>> + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
>> + * non-early mapping of the UEFI system table and virtual mappings for all
>> + * EFI_MEMORY_RUNTIME regions.
>> + */
>> +static int __init arm64_enable_runtime_services(void)
>> +{
>> +     u64 mapsize;
>> +
>> +     if (!efi_enabled(EFI_BOOT)) {
>> +             pr_info("EFI services will not be available.\n");
>> +             return -1;
>> +     }
>> +
>> +     if (efi_runtime_disabled()) {
>> +             pr_info("EFI runtime services will be disabled.\n");
>> +             return -1;
>> +     }
>> +
>> +     pr_info("Remapping and enabling EFI services.\n");
>> +
>> +     mapsize = memmap.map_end - memmap.map;
>> +     memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
>> +                                                mapsize);
>> +     if (!memmap.map) {
>> +             pr_err("Failed to remap EFI memory map\n");
>> +             return -1;
>> +     }
>> +     memmap.map_end = memmap.map + mapsize;
>> +     efi.memmap = &memmap;
>> +
>> +     efi.systab = (__force void *)ioremap_cache(efi_system_table,
>> +                                                sizeof(efi_system_table_t));
>> +     if (!efi.systab) {
>> +             pr_err("Failed to remap EFI System Table\n");
>> +             return -1;
>> +     }
>> +     set_bit(EFI_SYSTEM_TABLES, &efi.flags);
>> +
>> +     if (!efi_virtmap_init()) {
>> +             pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
>> +             return -1;
>> +     }
>> +
>> +     /* Set up runtime services function pointers */
>> +     efi_native_runtime_setup();
>> +     set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
>> +
>> +     efi.runtime_version = efi.systab->hdr.revision;
>> +
>> +     return 0;
>> +}
>> +early_initcall(arm64_enable_runtime_services);
>
> The above ought to be fixed - initcalls return negative errno numbers,
> so returning -1 from them is really not acceptable.  (The original code
> was doing the same - so it should be fixed as a separate patch.)
>

Indeed. I will add a patch to v3 to address this.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
  2015-11-16 19:50     ` Ryan Harkin
  (?)
@ 2015-11-17  9:26         ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:26 UTC (permalink / raw)
  To: Ryan Harkin
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Andrew Morton, linux-mm-Bw31MaZKKs3YtjvyW6yDsg

On 16 November 2015 at 20:50, Ryan Harkin <ryan.harkin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Hi Ard,
>
> On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> This series adds support for booting the 32-bit ARM kernel directly from
>> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
>> code, and the differences (primarily the PE/COFF header and entry point and
>> the efi_create_mapping() implementation) are split out into arm64 and ARM
>> versions.
>>
>> Changes since v1:
>> - The primary difference between this version and the first one is that all
>>   prerequisites have either been merged, dropped for now (early FDT handling)
>>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>>   on top of v4.4-rc1 directly.
>> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>>   better in the next version of the spec.
>>
>> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
>> code. Its purpose is to annotate memory regions as normal memory even if they
>> are removed from the kernel direct mapping.
>>
>> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>>
>> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
>> used by runtime services from the kernel direct mapping
>>
>> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
>> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>>
>> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
>> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>>
>> Patch #6 enables the generic early_ioremap and early_memremap implementations
>> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>>
>> Patch #7 splits off the core functionality of create_mapping() into a new
>> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>>
>> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
>> using another (late) allocator.
>>
>> Patch #9 implements create_mapping_late() that uses a late allocator.
>>
>> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>>
>> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
>> memory map and map the runtime services.
>>
>> Patch #12 ties together all of the above, by implementing the UEFI stub, and
>> introducing the Kconfig symbols that allow all of this to be built.
>>
>> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>
>> Ard Biesheuvel (11):
>>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>>   ARM: add support for generic early_ioremap/early_memremap
>>   ARM: split off core mapping logic from create_mapping
>>   ARM: factor out allocation routine from __create_mapping()
>>   ARM: implement create_mapping_late() for EFI use
>>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>>   ARM: wire up UEFI init and runtime support
>>
>> Roy Franz (1):
>>   ARM: add UEFI stub support
>>
>>  arch/arm/Kconfig                          |  20 ++
>>  arch/arm/boot/compressed/Makefile         |   4 +-
>>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>>  arch/arm/boot/compressed/head.S           |  54 +++-
>>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>>  arch/arm/include/asm/Kbuild               |   1 +
>>  arch/arm/include/asm/efi.h                |  90 ++++++
>>  arch/arm/include/asm/fixmap.h             |  29 +-
>>  arch/arm/include/asm/mach/map.h           |   1 +
>>  arch/arm/kernel/Makefile                  |   1 +
>>  arch/arm/kernel/efi.c                     |  38 +++
>>  arch/arm/kernel/setup.c                   |  10 +-
>>  arch/arm/mm/init.c                        |   5 +-
>>  arch/arm/mm/ioremap.c                     |   9 +
>>  arch/arm/mm/mmu.c                         | 110 ++++---
>>  arch/arm64/include/asm/efi.h              |  16 +
>>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>>  arch/arm64/mm/init.c                      |   2 +-
>>  arch/arm64/mm/mmu.c                       |   2 +
>>  drivers/firmware/efi/Makefile             |   4 +
>>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>>  drivers/firmware/efi/efi.c                |   2 +
>>  drivers/firmware/efi/libstub/Makefile     |   9 +
>>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>>  include/linux/memblock.h                  |   8 +
>>  mm/memblock.c                             |  28 ++
>>  28 files changed, 975 insertions(+), 356 deletions(-)
>>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>>  create mode 100644 arch/arm/include/asm/efi.h
>>  create mode 100644 arch/arm/kernel/efi.c
>>  create mode 100644 drivers/firmware/efi/arm-init.c
>>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>>
>> --
>> 1.9.1
>>
>
> I've tested this series against 4.4-rc1 on Versatile Express TC2,
> booting both as a "regular" kernel and as a EFI Stub on BusyBox and
> OpenEmbedded.  So if it helps any, you can add my:
>
> Tested-by: Ryan Harkin <ryan.harkin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>

Thanks Ryan!

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-17  9:26         ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:26 UTC (permalink / raw)
  To: Ryan Harkin
  Cc: linux-arm-kernel, linux-efi, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Andrew Morton, linux-mm

On 16 November 2015 at 20:50, Ryan Harkin <ryan.harkin@linaro.org> wrote:
> Hi Ard,
>
> On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> This series adds support for booting the 32-bit ARM kernel directly from
>> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
>> code, and the differences (primarily the PE/COFF header and entry point and
>> the efi_create_mapping() implementation) are split out into arm64 and ARM
>> versions.
>>
>> Changes since v1:
>> - The primary difference between this version and the first one is that all
>>   prerequisites have either been merged, dropped for now (early FDT handling)
>>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>>   on top of v4.4-rc1 directly.
>> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>>   better in the next version of the spec.
>>
>> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
>> code. Its purpose is to annotate memory regions as normal memory even if they
>> are removed from the kernel direct mapping.
>>
>> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>>
>> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
>> used by runtime services from the kernel direct mapping
>>
>> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
>> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>>
>> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
>> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>>
>> Patch #6 enables the generic early_ioremap and early_memremap implementations
>> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>>
>> Patch #7 splits off the core functionality of create_mapping() into a new
>> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>>
>> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
>> using another (late) allocator.
>>
>> Patch #9 implements create_mapping_late() that uses a late allocator.
>>
>> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>>
>> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
>> memory map and map the runtime services.
>>
>> Patch #12 ties together all of the above, by implementing the UEFI stub, and
>> introducing the Kconfig symbols that allow all of this to be built.
>>
>> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>
>> Ard Biesheuvel (11):
>>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>>   ARM: add support for generic early_ioremap/early_memremap
>>   ARM: split off core mapping logic from create_mapping
>>   ARM: factor out allocation routine from __create_mapping()
>>   ARM: implement create_mapping_late() for EFI use
>>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>>   ARM: wire up UEFI init and runtime support
>>
>> Roy Franz (1):
>>   ARM: add UEFI stub support
>>
>>  arch/arm/Kconfig                          |  20 ++
>>  arch/arm/boot/compressed/Makefile         |   4 +-
>>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>>  arch/arm/boot/compressed/head.S           |  54 +++-
>>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>>  arch/arm/include/asm/Kbuild               |   1 +
>>  arch/arm/include/asm/efi.h                |  90 ++++++
>>  arch/arm/include/asm/fixmap.h             |  29 +-
>>  arch/arm/include/asm/mach/map.h           |   1 +
>>  arch/arm/kernel/Makefile                  |   1 +
>>  arch/arm/kernel/efi.c                     |  38 +++
>>  arch/arm/kernel/setup.c                   |  10 +-
>>  arch/arm/mm/init.c                        |   5 +-
>>  arch/arm/mm/ioremap.c                     |   9 +
>>  arch/arm/mm/mmu.c                         | 110 ++++---
>>  arch/arm64/include/asm/efi.h              |  16 +
>>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>>  arch/arm64/mm/init.c                      |   2 +-
>>  arch/arm64/mm/mmu.c                       |   2 +
>>  drivers/firmware/efi/Makefile             |   4 +
>>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>>  drivers/firmware/efi/efi.c                |   2 +
>>  drivers/firmware/efi/libstub/Makefile     |   9 +
>>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>>  include/linux/memblock.h                  |   8 +
>>  mm/memblock.c                             |  28 ++
>>  28 files changed, 975 insertions(+), 356 deletions(-)
>>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>>  create mode 100644 arch/arm/include/asm/efi.h
>>  create mode 100644 arch/arm/kernel/efi.c
>>  create mode 100644 drivers/firmware/efi/arm-init.c
>>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>>
>> --
>> 1.9.1
>>
>
> I've tested this series against 4.4-rc1 on Versatile Express TC2,
> booting both as a "regular" kernel and as a EFI Stub on BusyBox and
> OpenEmbedded.  So if it helps any, you can add my:
>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
>

Thanks Ryan!

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM
@ 2015-11-17  9:26         ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-17  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 November 2015 at 20:50, Ryan Harkin <ryan.harkin@linaro.org> wrote:
> Hi Ard,
>
> On 16 November 2015 at 18:32, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> This series adds support for booting the 32-bit ARM kernel directly from
>> UEFI firmware using a builtin UEFI stub. It mostly reuses refactored arm64
>> code, and the differences (primarily the PE/COFF header and entry point and
>> the efi_create_mapping() implementation) are split out into arm64 and ARM
>> versions.
>>
>> Changes since v1:
>> - The primary difference between this version and the first one is that all
>>   prerequisites have either been merged, dropped for now (early FDT handling)
>>   or folded into this series (MEMBLOCK_NOMAP). IOW, this series can be applied
>>   on top of v4.4-rc1 directly.
>> - Dropped handling of UEFI permission bits. The reason is that the UEFIv2.5
>>   approach (EFI_PROPERTIES_TABLE) is flawed, and will be replaced by something
>>   better in the next version of the spec.
>>
>> Patch #1 adds support for the MEMBLOCK_NOMAP attribute to the generic memblock
>> code. Its purpose is to annotate memory regions as normal memory even if they
>> are removed from the kernel direct mapping.
>>
>> Patch #2 implements MEMBLOCK_NOMAP support for arm64
>>
>> Patch #3 updates the EFI init code to remove UEFI reserved regions and regions
>> used by runtime services from the kernel direct mapping
>>
>> Patch #4 splits off most of arch/arm64/kernel/efi.c into arch agnostic files
>> arm-init.c and arm-runtime.c under drivers/firmware/efi.
>>
>> Patch #5 refactors the code split off in patch #1 to isolate the arm64 specific
>> pieces, and change a couple of arm64-isms that ARM handles slightly differently.
>>
>> Patch #6 enables the generic early_ioremap and early_memremap implementations
>> for ARM. It reuses the kmap fixmap region, which is not used that early anyway.
>>
>> Patch #7 splits off the core functionality of create_mapping() into a new
>> function __create_mapping() that we can reuse for mapping UEFI runtime regions.
>>
>> Patch #8 factors out the early_alloc() routine so we can invoke __create_mapping
>> using another (late) allocator.
>>
>> Patch #9 implements create_mapping_late() that uses a late allocator.
>>
>> Patch #10 implements MEMBLOCK_NOMAP support for ARM
>>
>> Patch #11 implements the UEFI support in the kernel proper to probe the UEFI
>> memory map and map the runtime services.
>>
>> Patch #12 ties together all of the above, by implementing the UEFI stub, and
>> introducing the Kconfig symbols that allow all of this to be built.
>>
>> Instructions how to build and run the 32-bit ARM UEFI firmware can be found here:
>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>
>> Ard Biesheuvel (11):
>>   mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table
>>   arm64: only consider memblocks with NOMAP cleared for linear mapping
>>   arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP
>>   arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
>>   arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
>>   ARM: add support for generic early_ioremap/early_memremap
>>   ARM: split off core mapping logic from create_mapping
>>   ARM: factor out allocation routine from __create_mapping()
>>   ARM: implement create_mapping_late() for EFI use
>>   ARM: only consider memblocks with NOMAP cleared for linear mapping
>>   ARM: wire up UEFI init and runtime support
>>
>> Roy Franz (1):
>>   ARM: add UEFI stub support
>>
>>  arch/arm/Kconfig                          |  20 ++
>>  arch/arm/boot/compressed/Makefile         |   4 +-
>>  arch/arm/boot/compressed/efi-header.S     | 130 ++++++++
>>  arch/arm/boot/compressed/head.S           |  54 +++-
>>  arch/arm/boot/compressed/vmlinux.lds.S    |   7 +
>>  arch/arm/include/asm/Kbuild               |   1 +
>>  arch/arm/include/asm/efi.h                |  90 ++++++
>>  arch/arm/include/asm/fixmap.h             |  29 +-
>>  arch/arm/include/asm/mach/map.h           |   1 +
>>  arch/arm/kernel/Makefile                  |   1 +
>>  arch/arm/kernel/efi.c                     |  38 +++
>>  arch/arm/kernel/setup.c                   |  10 +-
>>  arch/arm/mm/init.c                        |   5 +-
>>  arch/arm/mm/ioremap.c                     |   9 +
>>  arch/arm/mm/mmu.c                         | 110 ++++---
>>  arch/arm64/include/asm/efi.h              |  16 +
>>  arch/arm64/kernel/efi.c                   | 331 ++------------------
>>  arch/arm64/mm/init.c                      |   2 +-
>>  arch/arm64/mm/mmu.c                       |   2 +
>>  drivers/firmware/efi/Makefile             |   4 +
>>  drivers/firmware/efi/arm-init.c           | 197 ++++++++++++
>>  drivers/firmware/efi/arm-runtime.c        | 134 ++++++++
>>  drivers/firmware/efi/efi.c                |   2 +
>>  drivers/firmware/efi/libstub/Makefile     |   9 +
>>  drivers/firmware/efi/libstub/arm-stub.c   |   4 +-
>>  drivers/firmware/efi/libstub/arm32-stub.c |  85 +++++
>>  include/linux/memblock.h                  |   8 +
>>  mm/memblock.c                             |  28 ++
>>  28 files changed, 975 insertions(+), 356 deletions(-)
>>  create mode 100644 arch/arm/boot/compressed/efi-header.S
>>  create mode 100644 arch/arm/include/asm/efi.h
>>  create mode 100644 arch/arm/kernel/efi.c
>>  create mode 100644 drivers/firmware/efi/arm-init.c
>>  create mode 100644 drivers/firmware/efi/arm-runtime.c
>>  create mode 100644 drivers/firmware/efi/libstub/arm32-stub.c
>>
>> --
>> 1.9.1
>>
>
> I've tested this series against 4.4-rc1 on Versatile Express TC2,
> booting both as a "regular" kernel and as a EFI Stub on BusyBox and
> OpenEmbedded.  So if it helps any, you can add my:
>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
>

Thanks Ryan!

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  2015-11-16 18:32   ` Ard Biesheuvel
@ 2015-11-19 22:34     ` Matt Fleming
  -1 siblings, 0 replies; 94+ messages in thread
From: Matt Fleming @ 2015-11-19 22:34 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-efi, matt.fleming, linux, will.deacon,
	grant.likely, catalin.marinas, mark.rutland, leif.lindholm,
	roy.franz, msalter, ryan.harkin, akpm, linux-mm

On Mon, 16 Nov, at 07:32:29PM, Ard Biesheuvel wrote:
> +
> +	pr_info("EFI v%u.%.02u by %s\n",
> +		efi.systab->hdr.revision >> 16,
> +		efi.systab->hdr.revision & 0xffff, vendor);
> +
> +	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
> +	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
> +				       table_size);

You should probably check the return value of early_memremap().

> +
> +	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
> +					 sizeof(efi_config_table_64_t), NULL);
> +
> +	early_memunmap(config_tables, table_size);
> +out:
> +	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
> +	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:
> +	case EFI_PERSISTENT_MEMORY:
> +		return 0;
> +	default:
> +		break;
> +	}
> +	return is_normal_ram(md);
> +}
> +
> +static __init void reserve_regions(void)
> +{
> +	efi_memory_desc_t *md;
> +	u64 paddr, npages, size;
> +
> +	if (efi_enabled(EFI_DBG))
> +		pr_info("Processing EFI memory map:\n");
> +
> +	for_each_efi_memory_desc(&memmap, md) {
> +		paddr = md->phys_addr;
> +		npages = md->num_pages;
> +
> +		if (efi_enabled(EFI_DBG)) {
> +			char buf[64];
> +
> +			pr_info("  0x%012llx-0x%012llx %s",
> +				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
> +				efi_md_typeattr_format(buf, sizeof(buf), md));
> +		}
> +
> +		memrange_efi_to_native(&paddr, &npages);
> +		size = npages << PAGE_SHIFT;

The use of EFI_PAGE_SHIFT and PAGE_SHIFT seem to get mingled in this
code. What's the correct constant to use throughout, because it
doesn't look like PAGE_SHIFT == EFI_PAGE_SHIFT always?

> +
> +		if (is_normal_ram(md))
> +			early_init_dt_add_memory_arch(paddr, size);
> +
> +		if (is_reserve_region(md)) {
> +			memblock_mark_nomap(paddr, size);

Hmm.. I was going to point out the fact that you're not checking the
return value of memblock_mark_nomap() which can fail if you run out of
memory when resizing the memblock arrays, until I realised that you
haven't called memblock_allow_resize() yet. Oh well.

> +			if (efi_enabled(EFI_DBG))
> +				pr_cont("*");
> +		}
> +
> +		if (efi_enabled(EFI_DBG))
> +			pr_cont("\n");
> +	}
> +
> +	set_bit(EFI_MEMMAP, &efi.flags);
> +}
> +
> +void __init efi_init(void)
> +{
> +	struct efi_fdt_params params;
> +
> +	/* Grab UEFI information placed in FDT by stub */
> +	if (!efi_get_fdt_params(&params))
> +		return;
> +
> +	efi_system_table = params.system_table;
> +
> +	memmap.phys_map = params.mmap;
> +	memmap.map = early_memremap(params.mmap, params.mmap_size);

Better check the return value?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-19 22:34     ` Matt Fleming
  0 siblings, 0 replies; 94+ messages in thread
From: Matt Fleming @ 2015-11-19 22:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 16 Nov, at 07:32:29PM, Ard Biesheuvel wrote:
> +
> +	pr_info("EFI v%u.%.02u by %s\n",
> +		efi.systab->hdr.revision >> 16,
> +		efi.systab->hdr.revision & 0xffff, vendor);
> +
> +	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
> +	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
> +				       table_size);

You should probably check the return value of early_memremap().

> +
> +	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
> +					 sizeof(efi_config_table_64_t), NULL);
> +
> +	early_memunmap(config_tables, table_size);
> +out:
> +	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
> +	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:
> +	case EFI_PERSISTENT_MEMORY:
> +		return 0;
> +	default:
> +		break;
> +	}
> +	return is_normal_ram(md);
> +}
> +
> +static __init void reserve_regions(void)
> +{
> +	efi_memory_desc_t *md;
> +	u64 paddr, npages, size;
> +
> +	if (efi_enabled(EFI_DBG))
> +		pr_info("Processing EFI memory map:\n");
> +
> +	for_each_efi_memory_desc(&memmap, md) {
> +		paddr = md->phys_addr;
> +		npages = md->num_pages;
> +
> +		if (efi_enabled(EFI_DBG)) {
> +			char buf[64];
> +
> +			pr_info("  0x%012llx-0x%012llx %s",
> +				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
> +				efi_md_typeattr_format(buf, sizeof(buf), md));
> +		}
> +
> +		memrange_efi_to_native(&paddr, &npages);
> +		size = npages << PAGE_SHIFT;

The use of EFI_PAGE_SHIFT and PAGE_SHIFT seem to get mingled in this
code. What's the correct constant to use throughout, because it
doesn't look like PAGE_SHIFT == EFI_PAGE_SHIFT always?

> +
> +		if (is_normal_ram(md))
> +			early_init_dt_add_memory_arch(paddr, size);
> +
> +		if (is_reserve_region(md)) {
> +			memblock_mark_nomap(paddr, size);

Hmm.. I was going to point out the fact that you're not checking the
return value of memblock_mark_nomap() which can fail if you run out of
memory when resizing the memblock arrays, until I realised that you
haven't called memblock_allow_resize() yet. Oh well.

> +			if (efi_enabled(EFI_DBG))
> +				pr_cont("*");
> +		}
> +
> +		if (efi_enabled(EFI_DBG))
> +			pr_cont("\n");
> +	}
> +
> +	set_bit(EFI_MEMMAP, &efi.flags);
> +}
> +
> +void __init efi_init(void)
> +{
> +	struct efi_fdt_params params;
> +
> +	/* Grab UEFI information placed in FDT by stub */
> +	if (!efi_get_fdt_params(&params))
> +		return;
> +
> +	efi_system_table = params.system_table;
> +
> +	memmap.phys_map = params.mmap;
> +	memmap.map = early_memremap(params.mmap, params.mmap_size);

Better check the return value?

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
  2015-11-19 22:34     ` Matt Fleming
  (?)
@ 2015-11-20  6:31         ` Ard Biesheuvel
  -1 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-20  6:31 UTC (permalink / raw)
  To: Matt Fleming
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg

Hi Matt,

Thanks for taking a look. Note that this patch only moves code from
one file to the other, and I am reluctant to fix bugs at the same
time. Most of your comments deserve a followup however, so I will make
sure this gets addressed at some point.


On 19 November 2015 at 23:34, Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org> wrote:
> On Mon, 16 Nov, at 07:32:29PM, Ard Biesheuvel wrote:
>> +
>> +     pr_info("EFI v%u.%.02u by %s\n",
>> +             efi.systab->hdr.revision >> 16,
>> +             efi.systab->hdr.revision & 0xffff, vendor);
>> +
>> +     table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
>> +     config_tables = early_memremap(efi_to_phys(efi.systab->tables),
>> +                                    table_size);
>
> You should probably check the return value of early_memremap().
>

Indeed.

>> +
>> +     retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
>> +                                      sizeof(efi_config_table_64_t), NULL);
>> +
>> +     early_memunmap(config_tables, table_size);
>> +out:
>> +     early_memunmap(efi.systab,  sizeof(efi_system_table_t));
>> +     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:
>> +     case EFI_PERSISTENT_MEMORY:
>> +             return 0;
>> +     default:
>> +             break;
>> +     }
>> +     return is_normal_ram(md);
>> +}
>> +
>> +static __init void reserve_regions(void)
>> +{
>> +     efi_memory_desc_t *md;
>> +     u64 paddr, npages, size;
>> +
>> +     if (efi_enabled(EFI_DBG))
>> +             pr_info("Processing EFI memory map:\n");
>> +
>> +     for_each_efi_memory_desc(&memmap, md) {
>> +             paddr = md->phys_addr;
>> +             npages = md->num_pages;
>> +
>> +             if (efi_enabled(EFI_DBG)) {
>> +                     char buf[64];
>> +
>> +                     pr_info("  0x%012llx-0x%012llx %s",
>> +                             paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
>> +                             efi_md_typeattr_format(buf, sizeof(buf), md));
>> +             }
>> +
>> +             memrange_efi_to_native(&paddr, &npages);
>> +             size = npages << PAGE_SHIFT;
>
> The use of EFI_PAGE_SHIFT and PAGE_SHIFT seem to get mingled in this
> code. What's the correct constant to use throughout, because it
> doesn't look like PAGE_SHIFT == EFI_PAGE_SHIFT always?
>

No, this is correct (although confusing). npages has been converted to
native page size, so PAGE_SHIFT is appropriate here

>> +
>> +             if (is_normal_ram(md))
>> +                     early_init_dt_add_memory_arch(paddr, size);
>> +
>> +             if (is_reserve_region(md)) {
>> +                     memblock_mark_nomap(paddr, size);
>
> Hmm.. I was going to point out the fact that you're not checking the
> return value of memblock_mark_nomap() which can fail if you run out of
> memory when resizing the memblock arrays, until I realised that you
> haven't called memblock_allow_resize() yet. Oh well.
>

Hmm, right. I wasn't even aware that memblock could resize itself in
the first place.

>> +                     if (efi_enabled(EFI_DBG))
>> +                             pr_cont("*");
>> +             }
>> +
>> +             if (efi_enabled(EFI_DBG))
>> +                     pr_cont("\n");
>> +     }
>> +
>> +     set_bit(EFI_MEMMAP, &efi.flags);
>> +}
>> +
>> +void __init efi_init(void)
>> +{
>> +     struct efi_fdt_params params;
>> +
>> +     /* Grab UEFI information placed in FDT by stub */
>> +     if (!efi_get_fdt_params(&params))
>> +             return;
>> +
>> +     efi_system_table = params.system_table;
>> +
>> +     memmap.phys_map = params.mmap;
>> +     memmap.map = early_memremap(params.mmap, params.mmap_size);
>
> Better check the return value?

Yep,

Thanks,
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

* Re: [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-20  6:31         ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-20  6:31 UTC (permalink / raw)
  To: Matt Fleming
  Cc: linux-arm-kernel, linux-efi, Matt Fleming,
	Russell King - ARM Linux, Will Deacon, Grant Likely,
	Catalin Marinas, Mark Rutland, Leif Lindholm, Roy Franz,
	Mark Salter, Ryan Harkin, Andrew Morton, linux-mm

Hi Matt,

Thanks for taking a look. Note that this patch only moves code from
one file to the other, and I am reluctant to fix bugs at the same
time. Most of your comments deserve a followup however, so I will make
sure this gets addressed at some point.


On 19 November 2015 at 23:34, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Mon, 16 Nov, at 07:32:29PM, Ard Biesheuvel wrote:
>> +
>> +     pr_info("EFI v%u.%.02u by %s\n",
>> +             efi.systab->hdr.revision >> 16,
>> +             efi.systab->hdr.revision & 0xffff, vendor);
>> +
>> +     table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
>> +     config_tables = early_memremap(efi_to_phys(efi.systab->tables),
>> +                                    table_size);
>
> You should probably check the return value of early_memremap().
>

Indeed.

>> +
>> +     retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
>> +                                      sizeof(efi_config_table_64_t), NULL);
>> +
>> +     early_memunmap(config_tables, table_size);
>> +out:
>> +     early_memunmap(efi.systab,  sizeof(efi_system_table_t));
>> +     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:
>> +     case EFI_PERSISTENT_MEMORY:
>> +             return 0;
>> +     default:
>> +             break;
>> +     }
>> +     return is_normal_ram(md);
>> +}
>> +
>> +static __init void reserve_regions(void)
>> +{
>> +     efi_memory_desc_t *md;
>> +     u64 paddr, npages, size;
>> +
>> +     if (efi_enabled(EFI_DBG))
>> +             pr_info("Processing EFI memory map:\n");
>> +
>> +     for_each_efi_memory_desc(&memmap, md) {
>> +             paddr = md->phys_addr;
>> +             npages = md->num_pages;
>> +
>> +             if (efi_enabled(EFI_DBG)) {
>> +                     char buf[64];
>> +
>> +                     pr_info("  0x%012llx-0x%012llx %s",
>> +                             paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
>> +                             efi_md_typeattr_format(buf, sizeof(buf), md));
>> +             }
>> +
>> +             memrange_efi_to_native(&paddr, &npages);
>> +             size = npages << PAGE_SHIFT;
>
> The use of EFI_PAGE_SHIFT and PAGE_SHIFT seem to get mingled in this
> code. What's the correct constant to use throughout, because it
> doesn't look like PAGE_SHIFT == EFI_PAGE_SHIFT always?
>

No, this is correct (although confusing). npages has been converted to
native page size, so PAGE_SHIFT is appropriate here

>> +
>> +             if (is_normal_ram(md))
>> +                     early_init_dt_add_memory_arch(paddr, size);
>> +
>> +             if (is_reserve_region(md)) {
>> +                     memblock_mark_nomap(paddr, size);
>
> Hmm.. I was going to point out the fact that you're not checking the
> return value of memblock_mark_nomap() which can fail if you run out of
> memory when resizing the memblock arrays, until I realised that you
> haven't called memblock_allow_resize() yet. Oh well.
>

Hmm, right. I wasn't even aware that memblock could resize itself in
the first place.

>> +                     if (efi_enabled(EFI_DBG))
>> +                             pr_cont("*");
>> +             }
>> +
>> +             if (efi_enabled(EFI_DBG))
>> +                     pr_cont("\n");
>> +     }
>> +
>> +     set_bit(EFI_MEMMAP, &efi.flags);
>> +}
>> +
>> +void __init efi_init(void)
>> +{
>> +     struct efi_fdt_params params;
>> +
>> +     /* Grab UEFI information placed in FDT by stub */
>> +     if (!efi_get_fdt_params(&params))
>> +             return;
>> +
>> +     efi_system_table = params.system_table;
>> +
>> +     memmap.phys_map = params.mmap;
>> +     memmap.map = early_memremap(params.mmap, params.mmap_size);
>
> Better check the return value?

Yep,

Thanks,
Ard.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 94+ messages in thread

* [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
@ 2015-11-20  6:31         ` Ard Biesheuvel
  0 siblings, 0 replies; 94+ messages in thread
From: Ard Biesheuvel @ 2015-11-20  6:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Matt,

Thanks for taking a look. Note that this patch only moves code from
one file to the other, and I am reluctant to fix bugs at the same
time. Most of your comments deserve a followup however, so I will make
sure this gets addressed at some point.


On 19 November 2015 at 23:34, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Mon, 16 Nov, at 07:32:29PM, Ard Biesheuvel wrote:
>> +
>> +     pr_info("EFI v%u.%.02u by %s\n",
>> +             efi.systab->hdr.revision >> 16,
>> +             efi.systab->hdr.revision & 0xffff, vendor);
>> +
>> +     table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
>> +     config_tables = early_memremap(efi_to_phys(efi.systab->tables),
>> +                                    table_size);
>
> You should probably check the return value of early_memremap().
>

Indeed.

>> +
>> +     retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
>> +                                      sizeof(efi_config_table_64_t), NULL);
>> +
>> +     early_memunmap(config_tables, table_size);
>> +out:
>> +     early_memunmap(efi.systab,  sizeof(efi_system_table_t));
>> +     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:
>> +     case EFI_PERSISTENT_MEMORY:
>> +             return 0;
>> +     default:
>> +             break;
>> +     }
>> +     return is_normal_ram(md);
>> +}
>> +
>> +static __init void reserve_regions(void)
>> +{
>> +     efi_memory_desc_t *md;
>> +     u64 paddr, npages, size;
>> +
>> +     if (efi_enabled(EFI_DBG))
>> +             pr_info("Processing EFI memory map:\n");
>> +
>> +     for_each_efi_memory_desc(&memmap, md) {
>> +             paddr = md->phys_addr;
>> +             npages = md->num_pages;
>> +
>> +             if (efi_enabled(EFI_DBG)) {
>> +                     char buf[64];
>> +
>> +                     pr_info("  0x%012llx-0x%012llx %s",
>> +                             paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
>> +                             efi_md_typeattr_format(buf, sizeof(buf), md));
>> +             }
>> +
>> +             memrange_efi_to_native(&paddr, &npages);
>> +             size = npages << PAGE_SHIFT;
>
> The use of EFI_PAGE_SHIFT and PAGE_SHIFT seem to get mingled in this
> code. What's the correct constant to use throughout, because it
> doesn't look like PAGE_SHIFT == EFI_PAGE_SHIFT always?
>

No, this is correct (although confusing). npages has been converted to
native page size, so PAGE_SHIFT is appropriate here

>> +
>> +             if (is_normal_ram(md))
>> +                     early_init_dt_add_memory_arch(paddr, size);
>> +
>> +             if (is_reserve_region(md)) {
>> +                     memblock_mark_nomap(paddr, size);
>
> Hmm.. I was going to point out the fact that you're not checking the
> return value of memblock_mark_nomap() which can fail if you run out of
> memory when resizing the memblock arrays, until I realised that you
> haven't called memblock_allow_resize() yet. Oh well.
>

Hmm, right. I wasn't even aware that memblock could resize itself in
the first place.

>> +                     if (efi_enabled(EFI_DBG))
>> +                             pr_cont("*");
>> +             }
>> +
>> +             if (efi_enabled(EFI_DBG))
>> +                     pr_cont("\n");
>> +     }
>> +
>> +     set_bit(EFI_MEMMAP, &efi.flags);
>> +}
>> +
>> +void __init efi_init(void)
>> +{
>> +     struct efi_fdt_params params;
>> +
>> +     /* Grab UEFI information placed in FDT by stub */
>> +     if (!efi_get_fdt_params(&params))
>> +             return;
>> +
>> +     efi_system_table = params.system_table;
>> +
>> +     memmap.phys_map = params.mmap;
>> +     memmap.map = early_memremap(params.mmap, params.mmap_size);
>
> Better check the return value?

Yep,

Thanks,
Ard.

^ permalink raw reply	[flat|nested] 94+ messages in thread

end of thread, other threads:[~2015-11-20  6:31 UTC | newest]

Thread overview: 94+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-16 18:32 [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM Ard Biesheuvel
2015-11-16 18:32 ` Ard Biesheuvel
2015-11-16 18:32 ` Ard Biesheuvel
2015-11-16 18:32 ` [PATCH v2 01/12] mm/memblock: add MEMBLOCK_NOMAP attribute to memblock memory table Ard Biesheuvel
2015-11-16 18:32   ` Ard Biesheuvel
     [not found]   ` <1447698757-8762-2-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 18:58     ` Russell King - ARM Linux
2015-11-16 18:58       ` Russell King - ARM Linux
2015-11-16 18:58       ` Russell King - ARM Linux
2015-11-16 19:09       ` Ard Biesheuvel
2015-11-16 19:09         ` Ard Biesheuvel
     [not found]         ` <CAKv+Gu-COD0eSWqaTfV_QgCDEiBg5Af8FDVx+TMiYuVkqgTrvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-16 19:49           ` Russell King - ARM Linux
2015-11-16 19:49             ` Russell King - ARM Linux
2015-11-16 19:49             ` Russell King - ARM Linux
     [not found]             ` <20151116194914.GK8644-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-11-16 20:33               ` Ard Biesheuvel
2015-11-16 20:33                 ` Ard Biesheuvel
2015-11-16 20:33                 ` Ard Biesheuvel
2015-11-16 18:32 ` [PATCH v2 03/12] arm64/efi: mark UEFI reserved regions as MEMBLOCK_NOMAP Ard Biesheuvel
2015-11-16 18:32   ` Ard Biesheuvel
2015-11-16 18:32 ` [PATCH v2 04/12] arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM Ard Biesheuvel
2015-11-16 18:32   ` Ard Biesheuvel
     [not found]   ` <1447698757-8762-5-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 18:48     ` Russell King - ARM Linux
2015-11-16 18:48       ` Russell King - ARM Linux
2015-11-16 18:48       ` Russell King - ARM Linux
     [not found]       ` <20151116184821.GC8644-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-11-17  9:21         ` Ard Biesheuvel
2015-11-17  9:21           ` Ard Biesheuvel
2015-11-17  9:21           ` Ard Biesheuvel
2015-11-19 22:34   ` Matt Fleming
2015-11-19 22:34     ` Matt Fleming
     [not found]     ` <20151119223430.GB2577-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
2015-11-20  6:31       ` Ard Biesheuvel
2015-11-20  6:31         ` Ard Biesheuvel
2015-11-20  6:31         ` Ard Biesheuvel
     [not found] ` <1447698757-8762-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 18:32   ` [PATCH v2 02/12] arm64: only consider memblocks with NOMAP cleared for linear mapping Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 05/12] arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
     [not found]     ` <1447698757-8762-6-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 18:49       ` Russell King - ARM Linux
2015-11-16 18:49         ` Russell King - ARM Linux
2015-11-16 18:49         ` Russell King - ARM Linux
     [not found]         ` <20151116184919.GD8644-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-11-17  9:18           ` Ard Biesheuvel
2015-11-17  9:18             ` Ard Biesheuvel
2015-11-17  9:18             ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 06/12] ARM: add support for generic early_ioremap/early_memremap Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 07/12] ARM: split off core mapping logic from create_mapping Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:55     ` Russell King - ARM Linux
2015-11-16 18:55       ` Russell King - ARM Linux
     [not found]       ` <20151116185519.GE8644-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-11-16 19:01         ` Ard Biesheuvel
2015-11-16 19:01           ` Ard Biesheuvel
2015-11-16 19:01           ` Ard Biesheuvel
     [not found]           ` <CAKv+Gu-P45_S2aHE2Dr=i-2e29-DvmSBR_JWec=JPcZeTMn02Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-16 19:45             ` Russell King - ARM Linux
2015-11-16 19:45               ` Russell King - ARM Linux
2015-11-16 19:45               ` Russell King - ARM Linux
2015-11-16 18:32   ` [PATCH v2 08/12] ARM: factor out allocation routine from __create_mapping() Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 09/12] ARM: implement create_mapping_late() for EFI use Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 10/12] ARM: only consider memblocks with NOMAP cleared for linear mapping Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
     [not found]     ` <1447698757-8762-11-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 19:00       ` Russell King - ARM Linux
2015-11-16 19:00         ` Russell King - ARM Linux
2015-11-16 19:00         ` Russell King - ARM Linux
2015-11-16 19:02         ` Ard Biesheuvel
2015-11-16 19:02           ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 11/12] ARM: wire up UEFI init and runtime support Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
     [not found]     ` <1447698757-8762-12-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-11-16 19:01       ` Russell King - ARM Linux
2015-11-16 19:01         ` Russell King - ARM Linux
2015-11-16 19:01         ` Russell King - ARM Linux
2015-11-16 19:04         ` Ard Biesheuvel
2015-11-16 19:04           ` Ard Biesheuvel
     [not found]           ` <CAKv+Gu8w+2GA5tV4roYtEsza+mkCZKYX_=tT2t=+eh-ZO1Y2fA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-16 19:48             ` Russell King - ARM Linux
2015-11-16 19:48               ` Russell King - ARM Linux
2015-11-16 19:48               ` Russell King - ARM Linux
     [not found]               ` <20151116194812.GJ8644-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-11-17  5:33                 ` Ard Biesheuvel
2015-11-17  5:33                   ` Ard Biesheuvel
2015-11-17  5:33                   ` Ard Biesheuvel
2015-11-16 18:32   ` [PATCH v2 12/12] ARM: add UEFI stub support Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 18:32     ` Ard Biesheuvel
2015-11-16 19:50   ` [PATCH v2 00/12] UEFI boot and runtime services support for 32-bit ARM Ryan Harkin
2015-11-16 19:50     ` Ryan Harkin
2015-11-16 19:50     ` Ryan Harkin
     [not found]     ` <CAD0U-hKfQvV_Dagc2BomK1wuJQG_-bsnLSyGcRduUN9zf30AHg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-11-17  9:26       ` Ard Biesheuvel
2015-11-17  9:26         ` Ard Biesheuvel
2015-11-17  9:26         ` Ard Biesheuvel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.