[tip:efi/urgent] fbdev/efifb: Ignore framebuffer memmap entries that lack any memory types

2019-05-17 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f8585539df0a1527c78b5d760665c89fe1c105a9
Gitweb: https://git.kernel.org/tip/f8585539df0a1527c78b5d760665c89fe1c105a9
Author: Ard Biesheuvel 
AuthorDate: Thu, 16 May 2019 23:31:59 +0200
Committer:  Ingo Molnar 
CommitDate: Fri, 17 May 2019 11:07:42 +0200

fbdev/efifb: Ignore framebuffer memmap entries that lack any memory types

The following commit:

  38ac0287b7f4 ("fbdev/efifb: Honour UEFI memory map attributes when mapping 
the FB")

updated the EFI framebuffer code to use memory mappings for the linear
framebuffer that are permitted by the memory attributes described by the
EFI memory map for the particular region, if the framebuffer happens to
be covered by the EFI memory map (which is typically only the case for
framebuffers in shared memory). This is required since non-x86 systems
may require cacheable attributes for memory mappings that are shared
with other masters (such as GPUs), and this information cannot be
described by the Graphics Output Protocol (GOP) EFI protocol itself,
and so we rely on the EFI memory map for this.

As reported by James, this breaks some x86 systems:

  [ 1.173368] efifb: probing for efifb
  [ 1.173386] efifb: abort, cannot remap video memory 0x1d5000 @ 0xcf80
  [ 1.173395] Trying to free nonexistent resource 

  [ 1.173413] efi-framebuffer: probe of efi-framebuffer.0 failed with error -5

The problem turns out to be that the memory map entry that describes the
framebuffer has no memory attributes listed at all, and so we end up with
a mem_flags value of 0x0.

So work around this by ensuring that the memory map entry's attribute field
has a sane value before using it to mask the set of usable attributes.

Reported-by: James Hilliard 
Tested-by: James Hilliard 
Signed-off-by: Ard Biesheuvel 
Cc:  # v4.19+
Cc: Borislav Petkov 
Cc: James Morse 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 38ac0287b7f4 ("fbdev/efifb: Honour UEFI memory map attributes when ...")
Link: http://lkml.kernel.org/r/20190516213159.3530-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 9e529cc2b4ff..9f39f0c360e0 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -477,8 +477,12 @@ static int efifb_probe(struct platform_device *dev)
 * If the UEFI memory map covers the efifb region, we may only
 * remap it using the attributes the memory map prescribes.
 */
-   mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
-   mem_flags &= md.attribute;
+   md.attribute &= EFI_MEMORY_UC | EFI_MEMORY_WC |
+   EFI_MEMORY_WT | EFI_MEMORY_WB;
+   if (md.attribute) {
+   mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
+   mem_flags &= md.attribute;
+   }
}
if (mem_flags & EFI_MEMORY_WC)
info->screen_base = ioremap_wc(efifb_fix.smem_start,


[tip:efi/core] efi/libstub/arm: Omit unneeded stripping of ksymtab/kcrctab sections

2019-03-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  02562d0ca1084a688ac5c92e0e92947f62f13093
Gitweb: https://git.kernel.org/tip/02562d0ca1084a688ac5c92e0e92947f62f13093
Author: Ard Biesheuvel 
AuthorDate: Thu, 28 Mar 2019 20:34:29 +0100
Committer:  Ingo Molnar 
CommitDate: Fri, 29 Mar 2019 07:35:00 +0100

efi/libstub/arm: Omit unneeded stripping of ksymtab/kcrctab sections

Commit f922c4abdf764 ("module: allow symbol exports to be disabled")
introduced a way to inhibit generation of kcrctab/ksymtab sections
when building ordinary kernel code to be used in a different execution
context (decompressor, EFI stub, etc)

That means we no longer have to strip those sections explicitly when
building the EFI libstub objects, so drop this from the Makefile.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Nick Desaulniers 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190328193429.21373-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index ae9081988c88..b1f7b64652db 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -71,7 +71,6 @@ CFLAGS_arm64-stub.o   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 extra-$(CONFIG_EFI_ARMSTUB):= $(lib-y)
 lib-$(CONFIG_EFI_ARMSTUB)  := $(patsubst %.o,%.stub.o,$(lib-y))
 
-STUBCOPY_RM-y  := -R *ksymtab* -R *kcrctab*
 STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
   --prefix-symbols=__efistub_
 STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
@@ -87,7 +86,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 #
 quiet_cmd_stubcopy = STUBCPY $@
   cmd_stubcopy =   \
-   $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<;   \
+   $(STRIP) --strip-debug -o $@ $<;\
if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); then\
echo "$@: absolute symbol references not allowed in the EFI 
stub" >&2; \
/bin/false; \


[tip:efi/core] efifb: Omit memory map check on legacy boot

2019-03-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c2999c281ea2d2ebbdfce96cecc7b52e2ae7c406
Gitweb: https://git.kernel.org/tip/c2999c281ea2d2ebbdfce96cecc7b52e2ae7c406
Author: Ard Biesheuvel 
AuthorDate: Thu, 28 Mar 2019 20:34:26 +0100
Committer:  Ingo Molnar 
CommitDate: Fri, 29 Mar 2019 07:34:59 +0100

efifb: Omit memory map check on legacy boot

Since the following commit:

  38ac0287b7f4 ("fbdev/efifb: Honour UEFI memory map attributes when mapping 
the FB")

efifb_probe() checks its memory range via efi_mem_desc_lookup(),
and this leads to a spurious error message:

   EFI_MEMMAP is not enabled

at every boot on KVM.  This is quite annoying since the error message
appears even if you set "quiet" boot option.

Since this happens on legacy boot, which strangely enough exposes
a EFI framebuffer via screen_info, let's double check that we are
doing an EFI boot before attempting to access the EFI memory map.

Reported-by: Takashi Iwai 
Tested-by: Takashi Iwai 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190328193429.21373-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index ba906876cc45..9e529cc2b4ff 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -464,7 +464,8 @@ static int efifb_probe(struct platform_device *dev)
info->apertures->ranges[0].base = efifb_fix.smem_start;
info->apertures->ranges[0].size = size_remap;
 
-   if (!efi_mem_desc_lookup(efifb_fix.smem_start, &md)) {
+   if (efi_enabled(EFI_BOOT) &&
+   !efi_mem_desc_lookup(efifb_fix.smem_start, &md)) {
if ((efifb_fix.smem_start + efifb_fix.smem_len) >
(md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) {
pr_err("efifb: video memory @ 0x%lx spans multiple EFI 
memory regions\n",


[tip:efi/urgent] efi/arm: Revert "Defer persistent reservations until after paging_init()"

2019-02-16 Thread tip-bot for Ard Biesheuvel
Commit-ID:  582a32e708823e5957fd73ccd78dc4a9e49d21ea
Gitweb: https://git.kernel.org/tip/582a32e708823e5957fd73ccd78dc4a9e49d21ea
Author: Ard Biesheuvel 
AuthorDate: Fri, 15 Feb 2019 13:33:33 +0100
Committer:  Ingo Molnar 
CommitDate: Sat, 16 Feb 2019 15:02:03 +0100

efi/arm: Revert "Defer persistent reservations until after paging_init()"

This reverts commit eff896288872d687d9662000ec9ae11b6d61766f, which
deferred the processing of persistent memory reservations to a point
where the memory may have already been allocated and overwritten,
defeating the purpose.

Signed-off-by: Ard Biesheuvel 
Acked-by: Will Deacon 
Cc: Linus Torvalds 
Cc: Marc Zyngier 
Cc: Mike Rapoport 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/2019021512.21209-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/setup.c   | 1 -
 drivers/firmware/efi/efi.c  | 4 
 drivers/firmware/efi/libstub/arm-stub.c | 3 ---
 include/linux/efi.h | 7 ---
 4 files changed, 15 deletions(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 4b0e1231625c..d09ec76f08cf 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -313,7 +313,6 @@ void __init setup_arch(char **cmdline_p)
arm64_memblock_init();
 
paging_init();
-   efi_apply_persistent_mem_reservations();
 
acpi_table_upgrade();
 
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 4c46ff6f2242..55b77c576c42 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, 
int count, int sz,
 
early_memunmap(tbl, sizeof(*tbl));
}
-   return 0;
-}
 
-int __init efi_apply_persistent_mem_reservations(void)
-{
if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
unsigned long prsv = efi.mem_reserve;
 
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index eee42d5e25ee..c037c6c5d0b7 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t 
*sys_table_arg)
efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
efi_status_t status;
 
-   if (IS_ENABLED(CONFIG_ARM))
-   return;
-
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv);
if (status != EFI_SUCCESS) {
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 45ff763fba76..28604a8d0aa9 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1198,8 +1198,6 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
-
-extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1218,11 +1216,6 @@ static inline bool efi_is_table_address(unsigned long 
phys_addr)
 {
return false;
 }
-
-static inline int efi_apply_persistent_mem_reservations(void)
-{
-   return 0;
-}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);


[tip:efi/urgent] arm64, mm, efi: Account for GICv3 LPI tables in static memblock reserve table

2019-02-16 Thread tip-bot for Ard Biesheuvel
Commit-ID:  8a5b403d71affa098009cc3dff1b2c45113021ad
Gitweb: https://git.kernel.org/tip/8a5b403d71affa098009cc3dff1b2c45113021ad
Author: Ard Biesheuvel 
AuthorDate: Fri, 15 Feb 2019 13:33:32 +0100
Committer:  Ingo Molnar 
CommitDate: Sat, 16 Feb 2019 15:02:03 +0100

arm64, mm, efi: Account for GICv3 LPI tables in static memblock reserve table

In the irqchip and EFI code, we have what basically amounts to a quirk
to work around a peculiarity in the GICv3 architecture, which permits
the system memory address of LPI tables to be programmable only once
after a CPU reset. This means kexec kernels must use the same memory
as the first kernel, and thus ensure that this memory has not been
given out for other purposes by the time the ITS init code runs, which
is not very early for secondary CPUs.

On systems with many CPUs, these reservations could overflow the
memblock reservation table, and this was addressed in commit:

  eff896288872 ("efi/arm: Defer persistent reservations until after 
paging_init()")

However, this turns out to have made things worse, since the allocation
of page tables and heap space for the resized memblock reservation table
itself may overwrite the regions we are attempting to reserve, which may
cause all kinds of corruption, also considering that the ITS will still
be poking bits into that memory in response to incoming MSIs.

So instead, let's grow the static memblock reservation table on such
systems so it can accommodate these reservations at an earlier time.
This will permit us to revert the above commit in a subsequent patch.

[ mingo: Minor cleanups. ]

Signed-off-by: Ard Biesheuvel 
Acked-by: Mike Rapoport 
Acked-by: Will Deacon 
Acked-by: Marc Zyngier 
Cc: Andrew Morton 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/2019021512.21209-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/memory.h | 11 +++
 include/linux/memblock.h|  3 ---
 mm/memblock.c   | 11 +--
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index e1ec947e7c0c..0c656850eeea 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -332,6 +332,17 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define virt_addr_valid(kaddr) \
(_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
 
+/*
+ * Given that the GIC architecture permits ITS implementations that can only be
+ * configured with a LPI table address once, GICv3 systems with many CPUs may
+ * end up reserving a lot of different regions after a kexec for their LPI
+ * tables (one per CPU), as we are forced to reuse the same memory after kexec
+ * (and thus reserve it persistently with EFI beforehand)
+ */
+#if defined(CONFIG_EFI) && defined(CONFIG_ARM_GIC_V3_ITS)
+# define INIT_MEMBLOCK_RESERVED_REGIONS(INIT_MEMBLOCK_REGIONS + 
NR_CPUS + 1)
+#endif
+
 #include 
 
 #endif
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 64c41cf45590..859b55b66db2 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -29,9 +29,6 @@ extern unsigned long max_pfn;
  */
 extern unsigned long long max_possible_pfn;
 
-#define INIT_MEMBLOCK_REGIONS  128
-#define INIT_PHYSMEM_REGIONS   4
-
 /**
  * enum memblock_flags - definition of memory region attributes
  * @MEMBLOCK_NONE: no special request
diff --git a/mm/memblock.c b/mm/memblock.c
index 022d4cbb3618..ea31045ba704 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -26,6 +26,13 @@
 
 #include "internal.h"
 
+#define INIT_MEMBLOCK_REGIONS  128
+#define INIT_PHYSMEM_REGIONS   4
+
+#ifndef INIT_MEMBLOCK_RESERVED_REGIONS
+# define INIT_MEMBLOCK_RESERVED_REGIONSINIT_MEMBLOCK_REGIONS
+#endif
+
 /**
  * DOC: memblock overview
  *
@@ -92,7 +99,7 @@ unsigned long max_pfn;
 unsigned long long max_possible_pfn;
 
 static struct memblock_region 
memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
-static struct memblock_region 
memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
+static struct memblock_region 
memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] 
__initdata_memblock;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
 static struct memblock_region 
memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
 #endif
@@ -105,7 +112,7 @@ struct memblock memblock __initdata_memblock = {
 
.reserved.regions   = memblock_reserved_init_regions,
.reserved.cnt   = 1,/* empty dummy entry */
-   .reserved.max   = INIT_MEMBLOCK_REGIONS,
+   .reserved.max   = INIT_MEMBLOCK_RESERVED_REGIONS,
.reserved.name  = "reserved",
 
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP


[tip:efi/core] efi: Use 32-bit alignment for efi_guid_t

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  494c704f9af0a0cddf593b381ea44320888733e6
Gitweb: https://git.kernel.org/tip/494c704f9af0a0cddf593b381ea44320888733e6
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:13 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:26:35 +0100

efi: Use 32-bit alignment for efi_guid_t

The UEFI spec and EDK2 reference implementation both define EFI_GUID as
struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment
is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM),
this means that firmware services invoked by the kernel may assume that
efi_guid_t* arguments are 32-bit aligned, and use memory accessors that
do not tolerate misalignment. So let's set the minimum alignment to 32 bits.

Note that the UEFI spec as well as some comments in the EDK2 code base
suggest that EFI_GUID should be 64-bit aligned, but this appears to be
a mistake, given that no code seems to exist that actually enforces that
or relies on it.

Reported-by: Heinrich Schuchardt 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 include/linux/efi.h | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 45ff763fba76..be08518c2553 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -48,7 +48,20 @@ typedef u16 efi_char16_t;/* UNICODE character */
 typedef u64 efi_physical_addr_t;
 typedef void *efi_handle_t;
 
-typedef guid_t efi_guid_t;
+/*
+ * The UEFI spec and EDK2 reference implementation both define EFI_GUID as
+ * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment
+ * is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM),
+ * this means that firmware services invoked by the kernel may assume that
+ * efi_guid_t* arguments are 32-bit aligned, and use memory accessors that
+ * do not tolerate misalignment. So let's set the minimum alignment to 32 bits.
+ *
+ * Note that the UEFI spec as well as some comments in the EDK2 code base
+ * suggest that EFI_GUID should be 64-bit aligned, but this appears to be
+ * a mistake, given that no code seems to exist that actually enforces that
+ * or relies on it.
+ */
+typedef guid_t efi_guid_t __aligned(__alignof__(u32));
 
 #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)


[tip:efi/core] efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4e46c2a956215482418d7b315749fb1b6c6bc224
Gitweb: https://git.kernel.org/tip/4e46c2a956215482418d7b315749fb1b6c6bc224
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:16 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:27:26 +0100

efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted

The UEFI spec revision 2.7 errata A section 8.4 has the following to
say about the virtual memory runtime services:

  "This section contains function definitions for the virtual memory
  support that may be optionally used by an operating system at runtime.
  If an operating system chooses to make EFI runtime service calls in a
  virtual addressing mode instead of the flat physical mode, then the
  operating system must use the services in this section to switch the
  EFI runtime services from flat physical addressing to virtual
  addressing."

So it is pretty clear that calling SetVirtualAddressMap() is entirely
optional, and so there is no point in doing so unless it achieves
anything useful for us.

This is not the case for 64-bit ARM. The identity mapping used by the
firmware is arbitrarily converted into another permutation of userland
addresses (i.e., bits [63:48] cleared), and the runtime code could easily
deal with the original layout in exactly the same way as it deals with
the converted layout. However, due to constraints related to page size
differences if the OS is not running with 4k pages, and related to
systems that may expose the individual sections of PE/COFF runtime
modules as different memory regions, creating the virtual layout is a
bit fiddly, and requires us to sort the memory map and reason about
adjacent regions with identical memory types etc etc.

So the obvious fix is to stop calling SetVirtualAddressMap() altogether
on arm64 systems. However, to avoid surprises, which are notoriously
hard to diagnose when it comes to OS<->firmware interactions, let's
start by making it an opt-out feature, and implement support for the
'efi=novamap' kernel command line parameter on ARM and arm64 systems.

( Note that 32-bit ARM generally does require SetVirtualAddressMap() to be
  used, given that the physical memory map and the kernel virtual address
  map are not guaranteed to be non-overlapping like on arm64. However,
  having support for efi=novamap,noruntime on 32-bit ARM, combined with
  the recently proposed support for earlycon=efifb, is likely to be useful
  to diagnose boot issues on such systems if they have no accessible serial
  port. )

Tested-by: Jeffrey Hugo 
Tested-by: Bjorn Andersson 
Tested-by: Lee Jones 
Signed-off-by: Ard Biesheuvel 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c|  5 +
 drivers/firmware/efi/libstub/efi-stub-helper.c | 10 ++
 drivers/firmware/efi/libstub/efistub.h |  1 +
 drivers/firmware/efi/libstub/fdt.c |  3 +++
 4 files changed, 19 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index eee42d5e25ee..626ec4b4a664 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -370,6 +370,11 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, 
unsigned long map_size,
paddr = in->phys_addr;
size = in->num_pages * EFI_PAGE_SIZE;
 
+   if (novamap()) {
+   in->virt_addr = in->phys_addr;
+   continue;
+   }
+
/*
 * Make the mapping compatible with 64k pages: this allows
 * a 4k page size kernel to kexec a 64k page size kernel and
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 8f2d000bec75..e4610e72b78f 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -31,6 +31,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
 static int __section(.data) __nokaslr;
 static int __section(.data) __quiet;
+static int __section(.data) __novamap;
 
 int __pure nokaslr(void)
 {
@@ -40,6 +41,10 @@ int __pure is_quiet(void)
 {
return __quiet;
 }
+int __pure novamap(void)
+{
+   return __novamap;
+}
 
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
@@ -479,6 +484,11 @@ efi_status_t efi_parse_options(char const *cmdline)
__chunk_size = -1UL;
}
 
+   if (!strncmp(str, "novamap", 7)) {
+   str += strlen("novamap");
+   __novamap = 1;
+   }
+
/* Group wo

[tip:efi/core] acpi/bgrt: Parse BGRT to obtain BMP address before it gets clobbered

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  41dd9d30a0994a138d3d3b5a2e1e46bd1aa38ea2
Gitweb: https://git.kernel.org/tip/41dd9d30a0994a138d3d3b5a2e1e46bd1aa38ea2
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:19 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:27:31 +0100

acpi/bgrt: Parse BGRT to obtain BMP address before it gets clobbered

The bitmap left in the framebuffer by the firmware is described by an
ACPI table called "BGRT", which describes the size, pixel format and
the address of a BMP image in memory. While the BGRT ACPI table is
guaranteed to reside in a "ACPI reclaim" memory region, which is
never touched by Linux, the BMP image, however, typically resides
in EFI Boot Services Memory, which may have been overwritten by the
time the BGRT discovery routine runs.

So instead, drop the handling from the ACPI init code, and call the
BGRT parsing code immediately after going over the EFI configuration
table array, at which time no memory has been touched yet except for
the .data/.bss regions covered by the static kernel image.

Unfortunately, this involves a non-trivial amount of ACPI entry
point and root table parsing, but we cannot rely on the normal
ACPI infrastructure yet this early in the boot.

Also note that we cannot take the 'acpi_disabled' global variable
into account, since it may not have assumed the correct value yet
(on arm64, the default value is '1' which is overridden to '0' if
no DT description has been made available by the firmware).

Signed-off-by: Ard Biesheuvel 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/acpi.c|  2 -
 arch/x86/kernel/acpi/boot.c |  2 -
 drivers/acpi/bgrt.c |  6 ---
 drivers/firmware/efi/efi-bgrt.c | 84 +
 drivers/firmware/efi/efi.c  | 13 +++
 include/linux/efi-bgrt.h|  4 +-
 6 files changed, 92 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 44e3c351e1ea..7429a811f76d 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -230,8 +230,6 @@ done:
early_init_dt_scan_chosen_stdout();
} else {
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
-   if (IS_ENABLED(CONFIG_ACPI_BGRT))
-   acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
}
 }
 
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 2624de16cd7a..2d3535b62752 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1633,8 +1633,6 @@ int __init acpi_boot_init(void)
acpi_process_madt();
 
acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
-   if (IS_ENABLED(CONFIG_ACPI_BGRT))
-   acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
 
if (!acpi_noirq)
x86_init.pci.init = pci_acpi_init;
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
index 75af78361ce5..048413e06898 100644
--- a/drivers/acpi/bgrt.c
+++ b/drivers/acpi/bgrt.c
@@ -81,12 +81,6 @@ static const struct attribute_group bgrt_attribute_group = {
.bin_attrs = bgrt_bin_attributes,
 };
 
-int __init acpi_parse_bgrt(struct acpi_table_header *table)
-{
-   efi_bgrt_init(table);
-   return 0;
-}
-
 static int __init bgrt_init(void)
 {
int ret;
diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index a2384184a7de..9c50d453b143 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -24,24 +24,94 @@ struct bmp_header {
u32 size;
 } __packed;
 
-void __init efi_bgrt_init(struct acpi_table_header *table)
+void __init efi_bgrt_init(unsigned long rsdp_phys)
 {
void *image;
struct bmp_header bmp_header;
struct acpi_table_bgrt *bgrt = &bgrt_tab;
+   struct acpi_table_bgrt *table = NULL;
+   struct acpi_table_rsdp *rsdp;
+   struct acpi_table_header *hdr;
+   u64 xsdt_phys = 0;
+   u32 rsdt_phys = 0;
+   size_t len;
 
-   if (acpi_disabled)
+   if (!efi_enabled(EFI_MEMMAP))
return;
 
-   if (!efi_enabled(EFI_MEMMAP))
+   /* map the root pointer table to find the xsdt/rsdt values */
+   rsdp = early_memremap_ro(rsdp_phys, sizeof(*rsdp));
+   if (rsdp) {
+   if (ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
+   xsdt_phys = rsdp->xsdt_physical_address;
+   rsdt_phys = rsdp->rsdt_physical_address;
+   }
+   early_memunmap(rsdp, sizeof(*rsdp));
+   }
+
+   if (WARN_ON(!xsdt_phys && !rs

[tip:efi/core] efi: Replace GPL license boilerplate with SPDX headers

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4febfb8dd08b6f8bafc19f3f9e382a477425b578
Gitweb: https://git.kernel.org/tip/4febfb8dd08b6f8bafc19f3f9e382a477425b578
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:15 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:27:25 +0100

efi: Replace GPL license boilerplate with SPDX headers

Replace all GPL license blurbs with an equivalent SPDX header (most
files are GPLv2, some are GPLv2+). While at it, drop some outdated
header changelogs as well.

Signed-off-by: Ard Biesheuvel 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-7-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/apple-properties.c| 13 +-
 drivers/firmware/efi/arm-init.c|  6 +--
 drivers/firmware/efi/arm-runtime.c |  6 +--
 drivers/firmware/efi/capsule-loader.c  |  4 +-
 drivers/firmware/efi/capsule.c |  4 +-
 drivers/firmware/efi/cper-arm.c| 14 +--
 drivers/firmware/efi/cper.c| 14 +--
 drivers/firmware/efi/dev-path-parser.c |  9 +---
 drivers/firmware/efi/efi-bgrt.c|  5 +--
 drivers/firmware/efi/efi-pstore.c  |  2 +
 drivers/firmware/efi/efibc.c   | 10 +
 drivers/firmware/efi/efivars.c | 58 +-
 drivers/firmware/efi/esrt.c|  1 +
 drivers/firmware/efi/fake_mem.c| 16 +--
 drivers/firmware/efi/libstub/arm32-stub.c  |  6 +--
 drivers/firmware/efi/libstub/arm64-stub.c  |  6 +--
 drivers/firmware/efi/libstub/efi-stub-helper.c |  5 +--
 drivers/firmware/efi/libstub/fdt.c |  5 +--
 drivers/firmware/efi/libstub/gop.c |  4 +-
 drivers/firmware/efi/libstub/random.c  |  6 +--
 drivers/firmware/efi/libstub/secureboot.c  |  4 +-
 drivers/firmware/efi/libstub/tpm.c |  4 +-
 drivers/firmware/efi/memattr.c |  5 +--
 drivers/firmware/efi/runtime-map.c |  3 +-
 drivers/firmware/efi/test/efi_test.c   |  1 +
 drivers/firmware/efi/test/efi_test.h   |  2 +-
 drivers/firmware/efi/tpm.c |  5 +--
 drivers/firmware/efi/vars.c| 15 +--
 28 files changed, 29 insertions(+), 204 deletions(-)

diff --git a/drivers/firmware/efi/apple-properties.c 
b/drivers/firmware/efi/apple-properties.c
index ac1654f74dc7..0e206c9e0d7a 100644
--- a/drivers/firmware/efi/apple-properties.c
+++ b/drivers/firmware/efi/apple-properties.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * apple-properties.c - EFI device properties on Macs
  * Copyright (C) 2016 Lukas Wunner 
  *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see .
- *
  * Note, all properties are considered as u8 arrays.
  * To get a value of any of them the caller must use 
device_property_read_u8_array().
  */
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 1a6a77df8a5e..311cd349a862 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 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.
- *
  */
 
 #define pr_fmt(fmt)"efi: " fmt
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 352bd2473162..f5666f86 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 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 Sof

[tip:efi/core] efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  69c1f396f25b805aeff08f06d2e992c315ee5b1e
Gitweb: https://git.kernel.org/tip/69c1f396f25b805aeff08f06d2e992c315ee5b1e
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:18 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:27:30 +0100

efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation

Move the x86 EFI earlyprintk implementation to a shared location under
drivers/firmware and tweak it slightly so we can expose it as an earlycon
implementation (which is generic) rather than earlyprintk (which is only
implemented for a few architectures)

This also involves switching to write-combine mappings by default (which
is required on ARM since device mappings lack memory semantics, and so
memcpy/memset may not be used on them), and adding support for shared
memory framebuffers on cache coherent non-x86 systems (which do not
tolerate mismatched attributes).

Note that 32-bit ARM does not populate its struct screen_info early
enough for earlycon=efifb to work, so it is disabled there.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Alexander Graf 
Cc: AKASHI Takahiro 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 Documentation/admin-guide/kernel-parameters.txt |   8 +-
 arch/x86/Kconfig.debug  |  10 -
 arch/x86/include/asm/efi.h  |   1 -
 arch/x86/kernel/early_printk.c  |   4 -
 arch/x86/platform/efi/Makefile  |   1 -
 arch/x86/platform/efi/early_printk.c| 240 
 drivers/firmware/efi/Kconfig|   6 +
 drivers/firmware/efi/Makefile   |   1 +
 drivers/firmware/efi/earlycon.c | 206 
 9 files changed, 220 insertions(+), 257 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index b799bcf67d7b..76dd3baa31e0 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1073,9 +1073,15 @@
specified address. The serial port must already be
setup and configured. Options are not yet supported.
 
+   efifb,[options]
+   Start an early, unaccelerated console on the EFI
+   memory mapped framebuffer (if available). On cache
+   coherent non-x86 systems that use system memory for
+   the framebuffer, pass the 'ram' option so that it is
+   mapped with the correct attributes.
+
earlyprintk=[X86,SH,ARM,M68k,S390]
earlyprintk=vga
-   earlyprintk=efi
earlyprintk=sclp
earlyprintk=xen
earlyprintk=serial[,ttySn[,baudrate]]
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 0723dff17e6c..15d0fbe27872 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -40,16 +40,6 @@ config EARLY_PRINTK_DBGP
  with klogd/syslogd or the X server. You should normally say N here,
  unless you want to debug such a crash. You need usb debug device.
 
-config EARLY_PRINTK_EFI
-   bool "Early printk via the EFI framebuffer"
-   depends on EFI && EARLY_PRINTK
-   select FONT_SUPPORT
-   ---help---
- Write kernel log output directly into the EFI framebuffer.
-
- This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized.
-
 config EARLY_PRINTK_USB_XDBC
bool "Early printk via the xHCI debug port"
depends on EARLY_PRINTK && PCI
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 107283b1eb1e..606a4b6a9812 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -170,7 +170,6 @@ static inline bool efi_runtime_supported(void)
return false;
 }
 
-extern struct console early_efi_console;
 extern void parse_efi_setup(u64 phys_addr, u32 data_len);
 
 extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 374a52fa5296..9b33904251a9 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -388,10 +388,6 @@ static int __init setup_early_printk(char *buf)
if (!strncmp(buf, "xen", 3))
early_console_register(&xenboot_console, keep);
 #endif
-#ifdef CONFIG_EARLY_PRINTK_EFI
-   if (!strncmp(buf, "efi", 3))
-

[tip:efi/core] x86: Make ARCH_USE_MEMREMAP_PROT a generic Kconfig symbol

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  ce9084ba0d1d8030adee7038ace32f8d9d423d0f
Gitweb: https://git.kernel.org/tip/ce9084ba0d1d8030adee7038ace32f8d9d423d0f
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:17 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:27:29 +0100

x86: Make ARCH_USE_MEMREMAP_PROT a generic Kconfig symbol

Turn ARCH_USE_MEMREMAP_PROT into a generic Kconfig symbol, and fix the
dependency expression to reflect that AMD_MEM_ENCRYPT depends on it,
instead of the other way around. This will permit ARCH_USE_MEMREMAP_PROT
to be selected by other architectures.

Note that the encryption related early memremap routines in
arch/x86/mm/ioremap.c cannot be built for 32-bit x86 without triggering
the following warning:

 arch/x86//mm/ioremap.c: In function 'early_memremap_encrypted':
  >> arch/x86/include/asm/pgtable_types.h:193:27: warning: conversion from
 'long long unsigned int' to 'long unsigned int' changes
 value from '9223372036854776163' to '355' [-Woverflow]
  #define __PAGE_KERNEL_ENC (__PAGE_KERNEL | _PAGE_ENC)
^~~
 arch/x86//mm/ioremap.c:713:46: note: in expansion of macro 
'__PAGE_KERNEL_ENC'
   return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC);

which essentially means they are 64-bit only anyway. However, we cannot
make them dependent on CONFIG_ARCH_HAS_MEM_ENCRYPT, since that is always
defined, even for i386 (and changing that results in a slew of build errors)

So instead, build those routines only if CONFIG_AMD_MEM_ENCRYPT is
defined.

Signed-off-by: Ard Biesheuvel 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20190202094119.13230-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/Kconfig  | 3 +++
 arch/x86/Kconfig  | 5 +
 arch/x86/mm/ioremap.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 4cfb6de48f79..9f0213213da8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -885,6 +885,9 @@ config HAVE_ARCH_PREL32_RELOCATIONS
  architectures, and don't require runtime relocation on relocatable
  kernels.
 
+config ARCH_USE_MEMREMAP_PROT
+   bool
+
 source "kernel/gcov/Kconfig"
 
 source "scripts/gcc-plugins/Kconfig"
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 68261430fe6e..a7e7a60602fb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1510,6 +1510,7 @@ config AMD_MEM_ENCRYPT
bool "AMD Secure Memory Encryption (SME) support"
depends on X86_64 && CPU_SUP_AMD
select DYNAMIC_PHYSICAL_MASK
+   select ARCH_USE_MEMREMAP_PROT
---help---
  Say yes to enable support for the encryption of system memory.
  This requires an AMD processor that supports Secure Memory
@@ -1529,10 +1530,6 @@ config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
  If set to N, then the encryption of system memory can be
  activated with the mem_encrypt=on command line option.
 
-config ARCH_USE_MEMREMAP_PROT
-   def_bool y
-   depends on AMD_MEM_ENCRYPT
-
 # Common NUMA Features
 config NUMA
bool "Numa Memory Allocation and Scheduler Support"
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 5378d10f1d31..0029604af8a4 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -705,7 +705,7 @@ bool phys_mem_access_encrypted(unsigned long phys_addr, 
unsigned long size)
return arch_memremap_can_ram_remap(phys_addr, size, 0);
 }
 
-#ifdef CONFIG_ARCH_USE_MEMREMAP_PROT
+#ifdef CONFIG_AMD_MEM_ENCRYPT
 /* Remap memory with encryption */
 void __init *early_memremap_encrypted(resource_size_t phys_addr,
  unsigned long size)
@@ -747,7 +747,7 @@ void __init *early_memremap_decrypted_wp(resource_size_t 
phys_addr,
 
return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_NOENC_WP);
 }
-#endif /* CONFIG_ARCH_USE_MEMREMAP_PROT */
+#endif /* CONFIG_AMD_MEM_ENCRYPT */
 
 static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 


[tip:efi/core] efi/memattr: Don't bail on zero VA if it equals the region's PA

2019-02-04 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5de0fef0230f3c8d75cff450a71740a7bf2db866
Gitweb: https://git.kernel.org/tip/5de0fef0230f3c8d75cff450a71740a7bf2db866
Author: Ard Biesheuvel 
AuthorDate: Sat, 2 Feb 2019 10:41:12 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:26:34 +0100

efi/memattr: Don't bail on zero VA if it equals the region's PA

The EFI memory attributes code cross-references the EFI memory map with
the more granular EFI memory attributes table to ensure that they are in
sync before applying the strict permissions to the regions it describes.

Since we always install virtual mappings for the EFI runtime regions to
which these strict permissions apply, we currently perform a sanity check
on the EFI memory descriptor, and ensure that the EFI_MEMORY_RUNTIME bit
is set, and that the virtual address has been assigned.

However, in cases where a runtime region exists at physical address 0x0,
and the virtual mapping equals the physical mapping, e.g., when running
in mixed mode on x86, we encounter a memory descriptor with the runtime
attribute and virtual address 0x0, and incorrectly draw the conclusion
that a runtime region exists for which no virtual mapping was installed,
and give up altogether. The consequence of this is that firmware mappings
retain their read-write-execute permissions, making the system more
vulnerable to attacks.

So let's only bail if the virtual address of 0x0 has been assigned to a
physical region that does not reside at address 0x0.

Signed-off-by: Ard Biesheuvel 
Acked-by: Sai Praneeth Prakhya 
Cc: AKASHI Takahiro 
Cc: Alexander Graf 
Cc: Bjorn Andersson 
Cc: Borislav Petkov 
Cc: Heinrich Schuchardt 
Cc: Jeffrey Hugo 
Cc: Lee Jones 
Cc: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 10f0d2f577053 ("efi: Implement generic support for the Memory ...")
Link: http://lkml.kernel.org/r/20190202094119.13230-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/memattr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 8986757eafaf..aac972b056d9 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -94,7 +94,7 @@ static bool entry_is_valid(const efi_memory_desc_t *in, 
efi_memory_desc_t *out)
 
if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;
-   if (md->virt_addr == 0) {
+   if (md->virt_addr == 0 && md->phys_addr != 0) {
/* no virtual mapping has been installed by the stub */
break;
}


[tip:efi/core] efi: Reduce the amount of memblock reservations for persistent allocations

2018-11-30 Thread tip-bot for Ard Biesheuvel
Commit-ID:  80424b02d42bb22f8ff8839cb93a84ade53b39c0
Gitweb: https://git.kernel.org/tip/80424b02d42bb22f8ff8839cb93a84ade53b39c0
Author: Ard Biesheuvel 
AuthorDate: Thu, 29 Nov 2018 18:12:29 +0100
Committer:  Ingo Molnar 
CommitDate: Fri, 30 Nov 2018 09:37:57 +0100

efi: Reduce the amount of memblock reservations for persistent allocations

The current implementation of efi_mem_reserve_persistent() is rather
naive, in the sense that for each invocation, it creates a separate
linked list entry to describe the reservation. Since the linked list
entries themselves need to persist across subsequent kexec reboots,
every reservation created this way results in two memblock_reserve()
calls at the next boot.

On arm64 systems with 100s of CPUs, this may result in a excessive
number of memblock reservations, and needless fragmentation.

So instead, make use of the newly updated struct linux_efi_memreserve
layout to put multiple reservations into a single linked list entry.
This should get rid of the numerous tiny memblock reservations, and
effectively cut the total number of reservations in half on arm64
systems with many CPUs.

 [ mingo: build warning fix. ]

Tested-by: Marc Zyngier 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Lutomirski 
Cc: Arend van Spriel 
Cc: Bhupesh Sharma 
Cc: Borislav Petkov 
Cc: Dave Hansen 
Cc: Eric Snowberg 
Cc: Hans de Goede 
Cc: Joe Perches 
Cc: Jon Hunter 
Cc: Julien Thierry 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Nathan Chancellor 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Sedat Dilek 
Cc: Thomas Gleixner 
Cc: YiFei Zhu 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20181129171230.18699-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 21 +
 include/linux/efi.h|  3 +++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 80b11521627a..4c46ff6f2242 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -997,8 +997,8 @@ static int __init efi_memreserve_map_root(void)
 int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
struct linux_efi_memreserve *rsv;
-   int rsvsize = EFI_MEMRESERVE_SIZE(1);
-   int rc;
+   unsigned long prsv;
+   int rc, index;
 
if (efi_memreserve_root == (void *)ULONG_MAX)
return -ENODEV;
@@ -1009,11 +1009,24 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, 
u64 size)
return rc;
}
 
-   rsv = kmalloc(rsvsize, GFP_ATOMIC);
+   /* first try to find a slot in an existing linked list entry */
+   for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
+   rsv = __va(prsv);
+   index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
+   if (index < rsv->size) {
+   rsv->entry[index].base = addr;
+   rsv->entry[index].size = size;
+
+   return 0;
+   }
+   }
+
+   /* no slot found - allocate a new linked list entry */
+   rsv = (struct linux_efi_memreserve *)__get_free_page(GFP_ATOMIC);
if (!rsv)
return -ENOMEM;
 
-   rsv->size = 1;
+   rsv->size = EFI_MEMRESERVE_COUNT(PAGE_SIZE);
atomic_set(&rsv->count, 1);
rsv->entry[0].base = addr;
rsv->entry[0].size = size;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 4f27640fdcdc..becd5d76a207 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1724,4 +1724,7 @@ struct linux_efi_memreserve {
 #define EFI_MEMRESERVE_SIZE(count) (sizeof(struct linux_efi_memreserve) + \
(count) * sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
 
+#define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct 
linux_efi_memreserve)) \
+   / sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
+
 #endif /* _LINUX_EFI_H */


[tip:efi/core] efi: Permit multiple entries in persistent memreserve data structure

2018-11-30 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5f0b0ecf043a5319e729c11a53bc8294df12dab3
Gitweb: https://git.kernel.org/tip/5f0b0ecf043a5319e729c11a53bc8294df12dab3
Author: Ard Biesheuvel 
AuthorDate: Thu, 29 Nov 2018 18:12:28 +0100
Committer:  Ingo Molnar 
CommitDate: Fri, 30 Nov 2018 09:10:31 +0100

efi: Permit multiple entries in persistent memreserve data structure

In preparation of updating efi_mem_reserve_persistent() to cause less
fragmentation when dealing with many persistent reservations, update
the struct definition and the code that handles it currently so it
can describe an arbitrary number of reservations using a single linked
list entry. The actual optimization will be implemented in a subsequent
patch.

Tested-by: Marc Zyngier 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Lutomirski 
Cc: Arend van Spriel 
Cc: Bhupesh Sharma 
Cc: Borislav Petkov 
Cc: Dave Hansen 
Cc: Eric Snowberg 
Cc: Hans de Goede 
Cc: Joe Perches 
Cc: Jon Hunter 
Cc: Julien Thierry 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Nathan Chancellor 
Cc: Peter Zijlstra 
Cc: Sai Praneeth Prakhya 
Cc: Sedat Dilek 
Cc: Thomas Gleixner 
Cc: YiFei Zhu 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20181129171230.18699-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c  | 39 +++--
 drivers/firmware/efi/libstub/arm-stub.c |  2 +-
 include/linux/efi.h | 13 ---
 3 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 415849bab233..80b11521627a 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -602,21 +602,33 @@ int __init efi_apply_persistent_mem_reservations(void)
 
while (prsv) {
struct linux_efi_memreserve *rsv;
-
-   /* reserve the entry itself */
-   memblock_reserve(prsv, sizeof(*rsv));
-
-   rsv = early_memremap(prsv, sizeof(*rsv));
-   if (rsv == NULL) {
+   u8 *p;
+   int i;
+
+   /*
+* Just map a full page: that is what we will get
+* anyway, and it permits us to map the entire entry
+* before knowing its size.
+*/
+   p = early_memremap(ALIGN_DOWN(prsv, PAGE_SIZE),
+  PAGE_SIZE);
+   if (p == NULL) {
pr_err("Could not map UEFI memreserve 
entry!\n");
return -ENOMEM;
}
 
-   if (rsv->size)
-   memblock_reserve(rsv->base, rsv->size);
+   rsv = (void *)(p + prsv % PAGE_SIZE);
+
+   /* reserve the entry itself */
+   memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
+
+   for (i = 0; i < atomic_read(&rsv->count); i++) {
+   memblock_reserve(rsv->entry[i].base,
+rsv->entry[i].size);
+   }
 
prsv = rsv->next;
-   early_memunmap(rsv, sizeof(*rsv));
+   early_memunmap(p, PAGE_SIZE);
}
}
 
@@ -985,6 +997,7 @@ static int __init efi_memreserve_map_root(void)
 int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
struct linux_efi_memreserve *rsv;
+   int rsvsize = EFI_MEMRESERVE_SIZE(1);
int rc;
 
if (efi_memreserve_root == (void *)ULONG_MAX)
@@ -996,12 +1009,14 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, 
u64 size)
return rc;
}
 
-   rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
+   rsv = kmalloc(rsvsize, GFP_ATOMIC);
if (!rsv)
return -ENOMEM;
 
-   rsv->base = addr;
-   rsv->size = size;
+   rsv->size = 1;
+   atomic_set(&rsv->count, 1);
+   rsv->entry[0].base = addr;
+   rsv->entry[0].size = size;
 
spin_lock(&efi_mem_reserve_persistent_lock);
rsv->next = efi_memreserve_root->next;
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 3d36142cf812..9e20159ea5f5 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -86,8 +86,8 @@ void install_memreserve_table(efi_system_table_t 
*sys_table_arg)
}
 
rsv->next = 0;
-   rsv->base = 0;
rsv->size = 0;
+   atomic_set(&rsv->count, 0);
 
status = efi_call_early(install_configuration_table,
&memreserve_table_guid,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2b3b33c83b05..4f27640fdcdc 100644
--- a/include/linux/efi.h
+++ b/include/lin

[tip:efi/urgent] efi: Prevent GICv3 WARN() by mapping the memreserve table before first use

2018-11-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  976b489120cdab2b1b3a41ffa14661db43d58190
Gitweb: https://git.kernel.org/tip/976b489120cdab2b1b3a41ffa14661db43d58190
Author: Ard Biesheuvel 
AuthorDate: Fri, 23 Nov 2018 22:51:32 +0100
Committer:  Ingo Molnar 
CommitDate: Tue, 27 Nov 2018 13:50:20 +0100

efi: Prevent GICv3 WARN() by mapping the memreserve table before first use

Mapping the MEMRESERVE EFI configuration table from an early initcall
is too late: the GICv3 ITS code that creates persistent reservations
for the boot CPU's LPI tables is invoked from init_IRQ(), which runs
much earlier than the handling of the initcalls. This results in a
WARN() splat because the LPI tables cannot be reserved persistently,
which will result in silent memory corruption after a kexec reboot.

So instead, invoke the initialization performed by the initcall from
efi_mem_reserve_persistent() itself as well, but keep the initcall so
that the init is guaranteed to have been called before SMP boot.

Tested-by: Marc Zyngier 
Tested-by: Jan Glauber 
Tested-by: John Garry 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 63eb322d89c8 ("efi: Permit calling efi_mem_reserve_persistent() ...")
Link: http://lkml.kernel.org/r/20181123215132.7951-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 36 ++--
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index fad7c62cfc0e..415849bab233 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -969,13 +969,33 @@ bool efi_is_table_address(unsigned long phys_addr)
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
 static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
 
-int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
+static int __init efi_memreserve_map_root(void)
+{
+   if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+   return -ENODEV;
+
+   efi_memreserve_root = memremap(efi.mem_reserve,
+  sizeof(*efi_memreserve_root),
+  MEMREMAP_WB);
+   if (WARN_ON_ONCE(!efi_memreserve_root))
+   return -ENOMEM;
+   return 0;
+}
+
+int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
struct linux_efi_memreserve *rsv;
+   int rc;
 
-   if (!efi_memreserve_root)
+   if (efi_memreserve_root == (void *)ULONG_MAX)
return -ENODEV;
 
+   if (!efi_memreserve_root) {
+   rc = efi_memreserve_map_root();
+   if (rc)
+   return rc;
+   }
+
rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
if (!rsv)
return -ENOMEM;
@@ -993,14 +1013,10 @@ int efi_mem_reserve_persistent(phys_addr_t addr, u64 
size)
 
 static int __init efi_memreserve_root_init(void)
 {
-   if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
-   return -ENODEV;
-
-   efi_memreserve_root = memremap(efi.mem_reserve,
-  sizeof(*efi_memreserve_root),
-  MEMREMAP_WB);
-   if (!efi_memreserve_root)
-   return -ENOMEM;
+   if (efi_memreserve_root)
+   return 0;
+   if (efi_memreserve_map_root())
+   efi_memreserve_root = (void *)ULONG_MAX;
return 0;
 }
 early_initcall(efi_memreserve_root_init);


[tip:efi/urgent] efi: Permit calling efi_mem_reserve_persistent() from atomic context

2018-11-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  63eb322d89c8505af9b4a3d703e85e42281ebaa0
Gitweb: https://git.kernel.org/tip/63eb322d89c8505af9b4a3d703e85e42281ebaa0
Author: Ard Biesheuvel 
AuthorDate: Wed, 14 Nov 2018 09:55:44 -0800
Committer:  Ingo Molnar 
CommitDate: Thu, 15 Nov 2018 10:04:47 +0100

efi: Permit calling efi_mem_reserve_persistent() from atomic context

Currently, efi_mem_reserve_persistent() may not be called from atomic
context, since both the kmalloc() call and the memremap() call may
sleep.

The kmalloc() call is easy enough to fix, but the memremap() call
needs to be moved into an init hook since we cannot control the
memory allocation behavior of memremap() at the call site.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20181114175544.12860-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 31 +++
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 72a4da76d274..fad7c62cfc0e 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -967,36 +967,43 @@ bool efi_is_table_address(unsigned long phys_addr)
 }
 
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
+static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
 
 int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
-   struct linux_efi_memreserve *rsv, *parent;
+   struct linux_efi_memreserve *rsv;
 
-   if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+   if (!efi_memreserve_root)
return -ENODEV;
 
-   rsv = kmalloc(sizeof(*rsv), GFP_KERNEL);
+   rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
if (!rsv)
return -ENOMEM;
 
-   parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB);
-   if (!parent) {
-   kfree(rsv);
-   return -ENOMEM;
-   }
-
rsv->base = addr;
rsv->size = size;
 
spin_lock(&efi_mem_reserve_persistent_lock);
-   rsv->next = parent->next;
-   parent->next = __pa(rsv);
+   rsv->next = efi_memreserve_root->next;
+   efi_memreserve_root->next = __pa(rsv);
spin_unlock(&efi_mem_reserve_persistent_lock);
 
-   memunmap(parent);
+   return 0;
+}
 
+static int __init efi_memreserve_root_init(void)
+{
+   if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+   return -ENODEV;
+
+   efi_memreserve_root = memremap(efi.mem_reserve,
+  sizeof(*efi_memreserve_root),
+  MEMREMAP_WB);
+   if (!efi_memreserve_root)
+   return -ENOMEM;
return 0;
 }
+early_initcall(efi_memreserve_root_init);
 
 #ifdef CONFIG_KEXEC
 static int update_efi_random_seed(struct notifier_block *nb,


[tip:efi/urgent] efi/arm: Defer persistent reservations until after paging_init()

2018-11-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  eff896288872d687d9662000ec9ae11b6d61766f
Gitweb: https://git.kernel.org/tip/eff896288872d687d9662000ec9ae11b6d61766f
Author: Ard Biesheuvel 
AuthorDate: Wed, 14 Nov 2018 09:55:43 -0800
Committer:  Ingo Molnar 
CommitDate: Thu, 15 Nov 2018 10:04:46 +0100

efi/arm: Defer persistent reservations until after paging_init()

The new memory EFI reservation feature we introduced to allow memory
reservations to persist across kexec may trigger an unbounded number
of calls to memblock_reserve(). The memblock subsystem can deal with
this fine, but not before memblock resizing is enabled, which we can
only do after paging_init(), when the memory we reallocate the array
into is actually mapped.

So break out the memreserve table processing into a separate routine
and call it after paging_init() on arm64. On ARM, because of limited
reviewing bandwidth of the maintainer, we cannot currently fix this,
so instead, disable the EFI persistent memreserve entirely on ARM so
we can fix it later.

Tested-by: Marc Zyngier 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20181114175544.12860-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/setup.c   | 1 +
 drivers/firmware/efi/efi.c  | 4 
 drivers/firmware/efi/libstub/arm-stub.c | 3 +++
 include/linux/efi.h | 7 +++
 4 files changed, 15 insertions(+)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 953e316521fc..f4fc1e0544b7 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -313,6 +313,7 @@ void __init setup_arch(char **cmdline_p)
arm64_memblock_init();
 
paging_init();
+   efi_apply_persistent_mem_reservations();
 
acpi_table_upgrade();
 
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 249eb70691b0..72a4da76d274 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -592,7 +592,11 @@ int __init efi_config_parse_tables(void *config_tables, 
int count, int sz,
 
early_memunmap(tbl, sizeof(*tbl));
}
+   return 0;
+}
 
+int __init efi_apply_persistent_mem_reservations(void)
+{
if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
unsigned long prsv = efi.mem_reserve;
 
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 30ac0c975f8a..3d36142cf812 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -75,6 +75,9 @@ void install_memreserve_table(efi_system_table_t 
*sys_table_arg)
efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
efi_status_t status;
 
+   if (IS_ENABLED(CONFIG_ARM))
+   return;
+
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv);
if (status != EFI_SUCCESS) {
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 845174e113ce..100ce4a4aff6 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1167,6 +1167,8 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
+
+extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1185,6 +1187,11 @@ static inline bool efi_is_table_address(unsigned long 
phys_addr)
 {
return false;
 }
+
+static inline int efi_apply_persistent_mem_reservations(void)
+{
+   return 0;
+}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);


[tip:efi/urgent] efi/arm/libstub: Pack FDT after populating it

2018-11-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  72a58a63a164b4e9d2d914e65caeb551846883f1
Gitweb: https://git.kernel.org/tip/72a58a63a164b4e9d2d914e65caeb551846883f1
Author: Ard Biesheuvel 
AuthorDate: Wed, 14 Nov 2018 09:55:42 -0800
Committer:  Ingo Molnar 
CommitDate: Thu, 15 Nov 2018 10:04:46 +0100

efi/arm/libstub: Pack FDT after populating it

Commit:

  24d7c494ce46 ("efi/arm-stub: Round up FDT allocation to mapping size")

increased the allocation size for the FDT image created by the stub to a
fixed value of 2 MB, to simplify the former code that made several
attempts with increasing values for the size. This is reasonable
given that the allocation is of type EFI_LOADER_DATA, which is released
to the kernel unless it is explicitly memblock_reserve()d by the early
boot code.

However, this allocation size leaked into the 'size' field of the FDT
header metadata, and so the entire allocation remains occupied by the
device tree binary, even if most of it is not used to store device tree
information.

So call fdt_pack() to shrink the FDT data structure to its minimum size
after populating all the fields, so that the remaining memory is no
longer wasted.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.12+
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 24d7c494ce46 ("efi/arm-stub: Round up FDT allocation to mapping size")
Link: http://lkml.kernel.org/r/20181114175544.12860-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/fdt.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 8830fa601e45..0c0d2312f4a8 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -158,6 +158,10 @@ static efi_status_t update_fdt(efi_system_table_t 
*sys_table, void *orig_fdt,
return efi_status;
}
}
+
+   /* shrink the FDT back to its minimum size */
+   fdt_pack(fdt);
+
return EFI_SUCCESS;
 
 fdt_set_fail:


[tip:efi/urgent] efi/arm: Revert deferred unmap of early memmap mapping

2018-11-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  33412b8673135b18ea42beb7f5117ed0091798b6
Gitweb: https://git.kernel.org/tip/33412b8673135b18ea42beb7f5117ed0091798b6
Author: Ard Biesheuvel 
AuthorDate: Wed, 14 Nov 2018 09:55:41 -0800
Committer:  Ingo Molnar 
CommitDate: Thu, 15 Nov 2018 10:04:46 +0100

efi/arm: Revert deferred unmap of early memmap mapping

Commit:

  3ea86495aef2 ("efi/arm: preserve early mapping of UEFI memory map longer for 
BGRT")

deferred the unmap of the early mapping of the UEFI memory map to
accommodate the ACPI BGRT code, which looks up the memory type that
backs the BGRT table to validate it against the requirements of the UEFI spec.

Unfortunately, this causes problems on ARM, which does not permit
early mappings to persist after paging_init() is called, resulting
in a WARN() splat. Since we don't support the BGRT table on ARM anway,
let's revert ARM to the old behaviour, which is to take down the
early mapping at the end of efi_init().

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 3ea86495aef2 ("efi/arm: preserve early mapping of UEFI memory ...")
Link: http://lkml.kernel.org/r/20181114175544.12860-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c| 4 
 drivers/firmware/efi/arm-runtime.c | 2 +-
 drivers/firmware/efi/memmap.c  | 3 +++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 388a929baf95..1a6a77df8a5e 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -265,6 +265,10 @@ void __init efi_init(void)
(params.mmap & ~PAGE_MASK)));
 
init_screen_info();
+
+   /* ARM does not permit early mappings to persist across paging_init() */
+   if (IS_ENABLED(CONFIG_ARM))
+   efi_memmap_unmap();
 }
 
 static int __init register_gop_device(void)
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 922cfb813109..a00934d263c5 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -110,7 +110,7 @@ static int __init arm_enable_runtime_services(void)
 {
u64 mapsize;
 
-   if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) {
+   if (!efi_enabled(EFI_BOOT)) {
pr_info("EFI services will not be available.\n");
return 0;
}
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index fa2904fb841f..38b686c67b17 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -118,6 +118,9 @@ int __init efi_memmap_init_early(struct efi_memory_map_data 
*data)
 
 void __init efi_memmap_unmap(void)
 {
+   if (!efi_enabled(EFI_MEMMAP))
+   return;
+
if (!efi.memmap.late) {
unsigned long size;
 


[tip:core/core] jump_label: Fix NULL dereference bug in __jump_label_mod_update()

2018-10-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  77ac1c02d9f20a0d72fa992c88b98c15d087dbca
Gitweb: https://git.kernel.org/tip/77ac1c02d9f20a0d72fa992c88b98c15d087dbca
Author: Ard Biesheuvel 
AuthorDate: Mon, 1 Oct 2018 10:13:24 +0200
Committer:  Thomas Gleixner 
CommitDate: Tue, 2 Oct 2018 08:08:18 +0200

jump_label: Fix NULL dereference bug in __jump_label_mod_update()

Commit 19483677684b ("jump_label: Annotate entries that operate on
__init code earlier") refactored the code that manages runtime
patching of jump labels in modules that are tied to static keys
defined in other modules or in the core kernel.

In the latter case, we may iterate over the static_key_mod linked
list until we hit the entry for the core kernel, whose 'mod' field
will be NULL, and attempt to dereference it to get at its 'state'
member.

So let's add a non-NULL check: this forces the 'init' argument of
__jump_label_update() to false for static keys that are defined in
the core kernel, which is appropriate given that __init annotated
jump_label entries in the core kernel should no longer be active
at this point (i.e., when loading modules).

Fixes: 19483677684b ("jump_label: Annotate entries that operate on ...")
Reported-by: Dan Carpenter 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Reviewed-by: Kees Cook 
Cc: Jessica Yu 
Cc: Peter Zijlstra 
Link: https://lkml.kernel.org/r/20181001081324.11553-1-ard.biesheu...@linaro.org
---
 kernel/jump_label.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index e8cf3ff3149c..14a7f9881745 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -516,7 +516,7 @@ static void __jump_label_mod_update(struct static_key *key)
else
stop = m->jump_entries + m->num_jump_entries;
__jump_label_update(key, mod->entries, stop,
-   m->state == MODULE_STATE_COMING);
+   m && m->state == MODULE_STATE_COMING);
}
 }
 


[tip:core/core] s390/vmlinux.lds: Move JUMP_TABLE_DATA into output section

2018-10-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  57d15877033e44e9ac283b8c6e82cc67bf6a0aa6
Gitweb: https://git.kernel.org/tip/57d15877033e44e9ac283b8c6e82cc67bf6a0aa6
Author: Ard Biesheuvel 
AuthorDate: Sun, 30 Sep 2018 18:49:50 +0200
Committer:  Thomas Gleixner 
CommitDate: Tue, 2 Oct 2018 08:08:08 +0200

s390/vmlinux.lds: Move JUMP_TABLE_DATA into output section

Commit e872267b8bcbb179 ("jump_table: move entries into ro_after_init
region") moved the __jump_table input section into the __ro_after_init
output section, but inadvertently put the macro in the wrong place in
the s390 linker script. Let's fix that.

Fixes: e872267b8bcbb179 ("jump_table: move entries into ro_after_init region")
Reported-by: Guenter Roeck 
Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Reviewed-by: Kees Cook 
Acked-by: Heiko Carstens 
Tested-by: Guenter Roeck 
Cc: linux-s...@vger.kernel.org
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Cc: Peter Zijlstra 
Link: https://lkml.kernel.org/r/20180930164950.3841-1-ard.biesheu...@linaro.org

---
 arch/s390/kernel/vmlinux.lds.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 4042bbf3f9ad..457713f48734 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -64,9 +64,9 @@ SECTIONS
__start_ro_after_init = .;
.data..ro_after_init : {
 *(.data..ro_after_init)
+   JUMP_TABLE_DATA
}
EXCEPTION_TABLE(16)
-   JUMP_TABLE_DATA
. = ALIGN(PAGE_SIZE);
__end_ro_after_init = .;
 


[tip:core/core] jump_table: Move entries into ro_after_init region

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e872267b8bcbb179e21ccc7118f258873d6e7a59
Gitweb: https://git.kernel.org/tip/e872267b8bcbb179e21ccc7118f258873d6e7a59
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:43 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:49 +0200

jump_table: Move entries into ro_after_init region

The __jump_table sections emitted into the core kernel and into
each module consist of statically initialized references into
other parts of the code, and with the exception of entries that
point into init code, which are defused at post-init time, these
data structures are never modified.

So let's move them into the ro_after_init section, to prevent them
from being corrupted inadvertently by buggy code, or deliberately
by an attacker.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Reviewed-by: Kees Cook 
Acked-by: Jessica Yu 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Link: https://lkml.kernel.org/r/20180919065144.25010-9-ard.biesheu...@linaro.org

---
 arch/s390/kernel/vmlinux.lds.S|  1 +
 include/asm-generic/vmlinux.lds.h | 11 +++
 kernel/module.c   |  9 +
 3 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index b43f8d33a369..4042bbf3f9ad 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -66,6 +66,7 @@ SECTIONS
 *(.data..ro_after_init)
}
EXCEPTION_TABLE(16)
+   JUMP_TABLE_DATA
. = ALIGN(PAGE_SIZE);
__end_ro_after_init = .;
 
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 7b75ff6e2fce..f09ee3c544bc 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -253,10 +253,6 @@
STRUCT_ALIGN(); \
*(__tracepoints)\
/* implement dynamic printk debug */\
-   . = ALIGN(8);   \
-   __start___jump_table = .;   \
-   KEEP(*(__jump_table))   \
-   __stop___jump_table = .;\
. = ALIGN(8);   \
__start___verbose = .;  \
KEEP(*(__verbose))  \
@@ -300,6 +296,12 @@
. = __start_init_task + THREAD_SIZE;\
__end_init_task = .;
 
+#define JUMP_TABLE_DATA
\
+   . = ALIGN(8);   \
+   __start___jump_table = .;   \
+   KEEP(*(__jump_table))   \
+   __stop___jump_table = .;
+
 /*
  * Allow architectures to handle ro_after_init data on their
  * own by defining an empty RO_AFTER_INIT_DATA.
@@ -308,6 +310,7 @@
 #define RO_AFTER_INIT_DATA \
__start_ro_after_init = .;  \
*(.data..ro_after_init) \
+   JUMP_TABLE_DATA \
__end_ro_after_init = .;
 #endif
 
diff --git a/kernel/module.c b/kernel/module.c
index 6746c85511fe..49a405891587 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3315,6 +3315,15 @@ static struct module *layout_and_allocate(struct 
load_info *info, int flags)
 * Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set.
 */
ndx = find_sec(info, ".data..ro_after_init");
+   if (ndx)
+   info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
+   /*
+* Mark the __jump_table section as ro_after_init as well: these data
+* structures are never modified, with the exception of entries that
+* refer to code in the __init section, which are annotated as such
+* at module load time.
+*/
+   ndx = find_sec(info, "__jump_table");
if (ndx)
info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
 


[tip:core/core] jump_label: Annotate entries that operate on __init code earlier

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  19483677684b6ca01606f58503cb79cdfbbc7c72
Gitweb: https://git.kernel.org/tip/19483677684b6ca01606f58503cb79cdfbbc7c72
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:42 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:48 +0200

jump_label: Annotate entries that operate on __init code earlier

Jump table entries are mostly read-only, with the exception of the
init and module loader code that defuses entries that point into init
code when the code being referred to is freed.

For robustness, it would be better to move these entries into the
ro_after_init section, but clearing the 'code' member of each jump
table entry referring to init code at module load time races with the
module_enable_ro() call that remaps the ro_after_init section read
only, so we'd like to do it earlier.

So given that whether such an entry refers to init code can be decided
much earlier, we can pull this check forward. Since we may still need
the code entry at this point, let's switch to setting a low bit in the
'key' member just like we do to annotate the default state of a jump
table entry.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Reviewed-by: Kees Cook 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-8-ard.biesheu...@linaro.org

---
 include/linux/jump_label.h | 11 ---
 init/main.c|  1 -
 kernel/jump_label.c| 48 ++
 3 files changed, 18 insertions(+), 42 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 2768a925bafa..5df6a621e464 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -141,7 +141,7 @@ static inline unsigned long jump_entry_target(const struct 
jump_entry *entry)
 
 static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
 {
-   long offset = entry->key & ~1L;
+   long offset = entry->key & ~3L;
 
return (struct static_key *)((unsigned long)&entry->key + offset);
 }
@@ -160,7 +160,7 @@ static inline unsigned long jump_entry_target(const struct 
jump_entry *entry)
 
 static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
 {
-   return (struct static_key *)((unsigned long)entry->key & ~1UL);
+   return (struct static_key *)((unsigned long)entry->key & ~3UL);
 }
 
 #endif
@@ -172,12 +172,12 @@ static inline bool jump_entry_is_branch(const struct 
jump_entry *entry)
 
 static inline bool jump_entry_is_init(const struct jump_entry *entry)
 {
-   return entry->code == 0;
+   return (unsigned long)entry->key & 2UL;
 }
 
 static inline void jump_entry_set_init(struct jump_entry *entry)
 {
-   entry->code = 0;
+   entry->key |= 2;
 }
 
 #endif
@@ -213,7 +213,6 @@ extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
 extern void jump_label_init(void);
-extern void jump_label_invalidate_initmem(void);
 extern void jump_label_lock(void);
 extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
@@ -261,8 +260,6 @@ static __always_inline void jump_label_init(void)
static_key_initialized = true;
 }
 
-static inline void jump_label_invalidate_initmem(void) {}
-
 static __always_inline bool static_key_false(struct static_key *key)
 {
if (unlikely(static_key_count(key) > 0))
diff --git a/init/main.c b/init/main.c
index 18f8f0140fa0..a664246450d1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1064,7 +1064,6 @@ static int __ref kernel_init(void *unused)
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
ftrace_free_init_mem();
-   jump_label_invalidate_initmem();
free_initmem();
mark_readonly();
 
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 898a1d0c38dc..e8cf3ff3149c 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -373,14 +373,15 @@ static enum jump_label_type jump_label_type(struct 
jump_entry *entry)
 
 static void __jump_label_update(struct static_key *key,
struct jump_entry *entry,
-   struct jump_entry *stop)
+   struct jump_entry *stop,
+   bool init)
 {
for (; (entry < stop) && (jump_entry_key(entry) == key); entry++) {
/*
 * An entry->code of 0 indicates an entry which has been
 * disabled because it was in an init text area.
 */
-   if (!jump_entry_is_init(entry)) {
+   if (init || !jump_entry_is_init(entry)) {
if (kernel_text_address(jum

[tip:core/core] x86/jump_table: Use relative references

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b34006c4258c9c86597b6b7123d6a9a3513d6cd7
Gitweb: https://git.kernel.org/tip/b34006c4258c9c86597b6b7123d6a9a3513d6cd7
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:41 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:48 +0200

x86/jump_table: Use relative references

Similar to the arm64 case, 64-bit x86 can benefit from using relative
references rather than absolute ones when emitting struct jump_entry
instances. Not only does this reduce the memory footprint of the entries
themselves by 33%, it also removes the need for carrying relocation
metadata on relocatable builds (i.e., for KASLR) which saves a fair
chunk of .init space as well (although the savings are not as dramatic
as on arm64)

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-7-ard.biesheu...@linaro.org

---
 arch/x86/Kconfig  |  1 +
 arch/x86/include/asm/jump_label.h | 24 
 tools/objtool/special.c   |  4 ++--
 3 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1a0be022f91d..603f374f871d 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -119,6 +119,7 @@ config X86
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMAP  if X86_64 || X86_PAE
select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN  if X86_64
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS  if MMU
diff --git a/arch/x86/include/asm/jump_label.h 
b/arch/x86/include/asm/jump_label.h
index 8c0de4282659..21efc9d07ed9 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -37,7 +37,8 @@ static __always_inline bool arch_static_branch(struct 
static_key *key, bool bran
".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
".pushsection __jump_table,  \"aw\" \n\t"
_ASM_ALIGN "\n\t"
-   _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
+   ".long 1b - ., %l[l_yes] - . \n\t"
+   _ASM_PTR "%c0 + %c1 - .\n\t"
".popsection \n\t"
: :  "i" (key), "i" (branch) : : l_yes);
 
@@ -53,7 +54,8 @@ static __always_inline bool arch_static_branch_jump(struct 
static_key *key, bool
"2:\n\t"
".pushsection __jump_table,  \"aw\" \n\t"
_ASM_ALIGN "\n\t"
-   _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
+   ".long 1b - ., %l[l_yes] - . \n\t"
+   _ASM_PTR "%c0 + %c1 - .\n\t"
".popsection \n\t"
: :  "i" (key), "i" (branch) : : l_yes);
 
@@ -62,18 +64,6 @@ l_yes:
return true;
 }
 
-#ifdef CONFIG_X86_64
-typedef u64 jump_label_t;
-#else
-typedef u32 jump_label_t;
-#endif
-
-struct jump_entry {
-   jump_label_t code;
-   jump_label_t target;
-   jump_label_t key;
-};
-
 #else  /* __ASSEMBLY__ */
 
 .macro STATIC_JUMP_IF_TRUE target, key, def
@@ -88,7 +78,8 @@ struct jump_entry {
.endif
.pushsection __jump_table, "aw"
_ASM_ALIGN
-   _ASM_PTR.Lstatic_jump_\@, \target, \key
+   .long   .Lstatic_jump_\@ - ., \target - .
+   _ASM_PTR\key - .
.popsection
 .endm
 
@@ -104,7 +95,8 @@ struct jump_entry {
.endif
.pushsection __jump_table, "aw"
_ASM_ALIGN
-   _ASM_PTR.Lstatic_jump_\@, \target, \key + 1
+   .long   .Lstatic_jump_\@ - ., \target - .
+   _ASM_PTR\key + 1 - .
.popsection
 .endm
 
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index 84f001d52322..50af4e1274b3 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -30,9 +30,9 @@
 #define EX_ORIG_OFFSET 0
 #define EX_NEW_OFFSET  4
 
-#define JUMP_ENTRY_SIZE24
+#define JUMP_ENTRY_SIZE16
 #define JUMP_ORIG_OFFSET   0
-#define JUMP_NEW_OFFSET8
+#define JUMP_NEW_OFFSET4
 
 #define ALT_ENTRY_SIZE 13
 #define ALT_ORIG_OFFSET0


[tip:core/core] x86/jump_label: Switch to jump_entry accessors

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9fc0f798ab8a6c042d811e45086260eb59be45c1
Gitweb: https://git.kernel.org/tip/9fc0f798ab8a6c042d811e45086260eb59be45c1
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:40 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:48 +0200

x86/jump_label: Switch to jump_entry accessors

In preparation of switching x86 to use place-relative references for
the code, target and key members of struct jump_entry, replace direct
references to the struct members with invocations of the new accessors.
This will allow us to make the switch by modifying the accessors only.

This incorporates a cleanup of __jump_label_transform() proposed by
Peter.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-6-ard.biesheu...@linaro.org

---
 arch/x86/kernel/jump_label.c | 62 ++--
 1 file changed, 25 insertions(+), 37 deletions(-)

diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
index eeea935e9bb5..aac0c1f7e354 100644
--- a/arch/x86/kernel/jump_label.c
+++ b/arch/x86/kernel/jump_label.c
@@ -42,55 +42,40 @@ static void __ref __jump_label_transform(struct jump_entry 
*entry,
 void *(*poker)(void *, const void *, 
size_t),
 int init)
 {
-   union jump_code_union code;
+   union jump_code_union jmp;
const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
+   const void *expect, *code;
+   int line;
+
+   jmp.jump = 0xe9;
+   jmp.offset = jump_entry_target(entry) -
+(jump_entry_code(entry) + JUMP_LABEL_NOP_SIZE);
 
if (early_boot_irqs_disabled)
poker = text_poke_early;
 
if (type == JUMP_LABEL_JMP) {
if (init) {
-   /*
-* Jump label is enabled for the first time.
-* So we expect a default_nop...
-*/
-   if (unlikely(memcmp((void *)entry->code, default_nop, 5)
-!= 0))
-   bug_at((void *)entry->code, __LINE__);
+   expect = default_nop; line = __LINE__;
} else {
-   /*
-* ...otherwise expect an ideal_nop. Otherwise
-* something went horribly wrong.
-*/
-   if (unlikely(memcmp((void *)entry->code, ideal_nop, 5)
-!= 0))
-   bug_at((void *)entry->code, __LINE__);
+   expect = ideal_nop; line = __LINE__;
}
 
-   code.jump = 0xe9;
-   code.offset = entry->target -
-   (entry->code + JUMP_LABEL_NOP_SIZE);
+   code = &jmp.code;
} else {
-   /*
-* We are disabling this jump label. If it is not what
-* we think it is, then something must have gone wrong.
-* If this is the first initialization call, then we
-* are converting the default nop to the ideal nop.
-*/
if (init) {
-   if (unlikely(memcmp((void *)entry->code, default_nop, 
5) != 0))
-   bug_at((void *)entry->code, __LINE__);
+   expect = default_nop; line = __LINE__;
} else {
-   code.jump = 0xe9;
-   code.offset = entry->target -
-   (entry->code + JUMP_LABEL_NOP_SIZE);
-   if (unlikely(memcmp((void *)entry->code, &code, 5) != 
0))
-   bug_at((void *)entry->code, __LINE__);
+   expect = &jmp.code; line = __LINE__;
}
-   memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
+
+   code = ideal_nop;
}
 
+   if (memcmp((void *)jump_entry_code(entry), expect, JUMP_LABEL_NOP_SIZE))
+   bug_at((void *)jump_entry_code(entry), line);
+
/*
 * Make text_poke_bp() a default fallback poker.
 *
@@ -99,11 +84,14 @@ static void __ref __jump_label_transform(struct jump_entry 
*entry,
 * always nop being the 'currently valid' instruction
 *
 */
-   if (poker)
-   (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
-   else
-   text_poke_bp((void *)entry->code, &code, JUMP_L

[tip:core/core] x86: Add support for 64-bit place relative relocations

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b40a142b12b5c4312171140ff2bc92971b8a7a09
Gitweb: https://git.kernel.org/tip/b40a142b12b5c4312171140ff2bc92971b8a7a09
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:39 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:47 +0200

x86: Add support for 64-bit place relative relocations

Add support for R_X86_64_PC64 relocations, which operate on 64-bit
quantities holding a relative symbol reference. Also remove the
definition of R_X86_64_NUM: given that it is currently unused, it
is unclear what the new value should be.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-5-ard.biesheu...@linaro.org

---
 arch/x86/include/asm/elf.h |  3 +--
 arch/x86/kernel/module.c   |  6 ++
 arch/x86/tools/relocs.c| 10 ++
 arch/x86/um/asm/elf.h  |  3 +--
 4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 0d157d2a1e2a..a357031d85b5 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -62,8 +62,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
 #define R_X86_64_PC16  13  /* 16 bit sign extended pc relative */
 #define R_X86_64_8 14  /* Direct 8 bit sign extended  */
 #define R_X86_64_PC8   15  /* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM   16
+#define R_X86_64_PC64  24  /* Place relative 64-bit signed */
 
 /*
  * These are used to set parameters in the core dumps.
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index f58336af095c..b052e883dd8c 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -201,6 +201,12 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
goto overflow;
 #endif
break;
+   case R_X86_64_PC64:
+   if (*(u64 *)loc != 0)
+   goto invalid_relocation;
+   val -= (u64)loc;
+   *(u64 *)loc = val;
+   break;
default:
pr_err("%s: Unknown rela relocation: %llu\n",
   me->name, ELF64_R_TYPE(rel[i].r_info));
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 3a6c8ebc8032..0b08067c45f3 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -196,6 +196,7 @@ static const char *rel_type(unsigned type)
 #if ELF_BITS == 64
REL_TYPE(R_X86_64_NONE),
REL_TYPE(R_X86_64_64),
+   REL_TYPE(R_X86_64_PC64),
REL_TYPE(R_X86_64_PC32),
REL_TYPE(R_X86_64_GOT32),
REL_TYPE(R_X86_64_PLT32),
@@ -782,6 +783,15 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, 
ElfW(Sym) *sym,
add_reloc(&relocs32neg, offset);
break;
 
+   case R_X86_64_PC64:
+   /*
+* Only used by jump labels
+*/
+   if (is_percpu_sym(sym, symname))
+   die("Invalid R_X86_64_PC64 relocation against per-CPU 
symbol %s\n",
+   symname);
+   break;
+
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index 548197212a45..413f3519d9a1 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -116,8 +116,7 @@ do {
\
 #define R_X86_64_PC16  13  /* 16 bit sign extended pc relative */
 #define R_X86_64_8 14  /* Direct 8 bit sign extended  */
 #define R_X86_64_PC8   15  /* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM   16
+#define R_X86_64_PC64  24  /* Place relative 64-bit signed */
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.


[tip:core/core] arm64/kernel: jump_label: Switch to relative references

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c296146c058c87e9ed53001b6a3988519dbbb6a5
Gitweb: https://git.kernel.org/tip/c296146c058c87e9ed53001b6a3988519dbbb6a5
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:38 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:47 +0200

arm64/kernel: jump_label: Switch to relative references

On a randomly chosen distro kernel build for arm64, vmlinux.o shows the
following sections, containing jump label entries, and the associated
RELA relocation records, respectively:

  ...
  [38088] __jump_table  PROGBITS   00e19f30
   0002ea10    WA   0 0 8
  [38089] .rela__jump_table RELA   01fd8bb0
   0008be30  0018   I  38178   38088 8
  ...

In other words, we have 190 KB worth of 'struct jump_entry' instances,
and 573 KB worth of RELA entries to relocate each entry's code, target
and key members. This means the RELA section occupies 10% of the .init
segment, and the two sections combined represent 5% of vmlinux's entire
memory footprint.

So let's switch from 64-bit absolute references to 32-bit relative
references for the code and target field, and a 64-bit relative
reference for the 'key' field (which may reside in another module or the
core kernel, which may be more than 4 GB way on arm64 when running with
KASLR enable): this reduces the size of the __jump_table by 33%, and
gets rid of the RELA section entirely.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Will Deacon 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-4-ard.biesheu...@linaro.org

---
 arch/arm64/Kconfig  |  1 +
 arch/arm64/include/asm/jump_label.h | 38 ++---
 arch/arm64/kernel/jump_label.c  |  6 +++---
 3 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1b1a0e95c751..16e1e2c1e77b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -104,6 +104,7 @@ config ARM64
select HAVE_ARCH_BITREVERSE
select HAVE_ARCH_HUGE_VMAP
select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS
diff --git a/arch/arm64/include/asm/jump_label.h 
b/arch/arm64/include/asm/jump_label.h
index 7e2b3e360086..472023498d71 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -26,13 +26,16 @@
 
 #define JUMP_LABEL_NOP_SIZEAARCH64_INSN_SIZE
 
-static __always_inline bool arch_static_branch(struct static_key *key, bool 
branch)
+static __always_inline bool arch_static_branch(struct static_key *key,
+  bool branch)
 {
-   asm_volatile_goto("1: nop\n\t"
-".pushsection __jump_table,  \"aw\"\n\t"
-".align 3\n\t"
-".quad 1b, %l[l_yes], %c0\n\t"
-".popsection\n\t"
+   asm_volatile_goto(
+   "1: nop \n\t"
+"  .pushsection__jump_table, \"aw\"\n\t"
+"  .align  3   \n\t"
+"  .long   1b - ., %l[l_yes] - .   \n\t"
+"  .quad   %c0 - . \n\t"
+"  .popsection \n\t"
 :  :  "i"(&((char *)key)[branch]) :  : l_yes);
 
return false;
@@ -40,13 +43,16 @@ l_yes:
return true;
 }
 
-static __always_inline bool arch_static_branch_jump(struct static_key *key, 
bool branch)
+static __always_inline bool arch_static_branch_jump(struct static_key *key,
+   bool branch)
 {
-   asm_volatile_goto("1: b %l[l_yes]\n\t"
-".pushsection __jump_table,  \"aw\"\n\t"
-".align 3\n\t"
-".quad 1b, %l[l_yes], %c0\n\t"
-".popsection\n\t"
+   asm_volatile_goto(
+   "1: b   %l[l_yes]   \n\t"
+"  .pushsection__jump_table, \"aw\"\n\t"
+"  .align  3   \n\t"
+"  .long   1b - ., %l[l_yes] - .   \n\t"
+"  .quad   %c0 - . \n\t"
+"  .popsection \n\t"
 :  :  "i"(&((char *)key)[branch]) :  : l_yes);
 
return false;
@@ -54,13 +60,5 @@ l_yes:
return true;
 }
 
-typedef u64 jump_label_t;
-
-s

[tip:core/core] jump_label: Abstract jump_entry member accessors

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9ae033aca8d600e36034d4d0743aad624cec92ed
Gitweb: https://git.kernel.org/tip/9ae033aca8d600e36034d4d0743aad624cec92ed
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:36 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:46 +0200

jump_label: Abstract jump_entry member accessors

In preparation of allowing architectures to use relative references
in jump_label entries [which can dramatically reduce the memory
footprint], introduce abstractions for references to the 'code' and
'key' members of struct jump_entry.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-2-ard.biesheu...@linaro.org

---
 include/linux/jump_label.h | 34 ++
 kernel/jump_label.c| 40 +++-
 2 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 1a0b6f17a5d6..2eadff9b3b90 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -119,6 +119,40 @@ struct static_key {
 
 #ifdef HAVE_JUMP_LABEL
 #include 
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long jump_entry_code(const struct jump_entry *entry)
+{
+   return entry->code;
+}
+
+static inline unsigned long jump_entry_target(const struct jump_entry *entry)
+{
+   return entry->target;
+}
+
+static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
+{
+   return (struct static_key *)((unsigned long)entry->key & ~1UL);
+}
+
+static inline bool jump_entry_is_branch(const struct jump_entry *entry)
+{
+   return (unsigned long)entry->key & 1UL;
+}
+
+static inline bool jump_entry_is_init(const struct jump_entry *entry)
+{
+   return entry->code == 0;
+}
+
+static inline void jump_entry_set_init(struct jump_entry *entry)
+{
+   entry->code = 0;
+}
+
+#endif
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 2e62503bea0d..834e43de0daf 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -38,10 +38,10 @@ static int jump_label_cmp(const void *a, const void *b)
const struct jump_entry *jea = a;
const struct jump_entry *jeb = b;
 
-   if (jea->key < jeb->key)
+   if (jump_entry_key(jea) < jump_entry_key(jeb))
return -1;
 
-   if (jea->key > jeb->key)
+   if (jump_entry_key(jea) > jump_entry_key(jeb))
return 1;
 
return 0;
@@ -261,8 +261,8 @@ EXPORT_SYMBOL_GPL(jump_label_rate_limit);
 
 static int addr_conflict(struct jump_entry *entry, void *start, void *end)
 {
-   if (entry->code <= (unsigned long)end &&
-   entry->code + JUMP_LABEL_NOP_SIZE > (unsigned long)start)
+   if (jump_entry_code(entry) <= (unsigned long)end &&
+   jump_entry_code(entry) + JUMP_LABEL_NOP_SIZE > (unsigned long)start)
return 1;
 
return 0;
@@ -321,16 +321,6 @@ static inline void static_key_set_linked(struct static_key 
*key)
key->type |= JUMP_TYPE_LINKED;
 }
 
-static inline struct static_key *jump_entry_key(struct jump_entry *entry)
-{
-   return (struct static_key *)((unsigned long)entry->key & ~1UL);
-}
-
-static bool jump_entry_branch(struct jump_entry *entry)
-{
-   return (unsigned long)entry->key & 1UL;
-}
-
 /***
  * A 'struct static_key' uses a union such that it either points directly
  * to a table of 'struct jump_entry' or to a linked list of modules which in
@@ -355,7 +345,7 @@ static enum jump_label_type jump_label_type(struct 
jump_entry *entry)
 {
struct static_key *key = jump_entry_key(entry);
bool enabled = static_key_enabled(key);
-   bool branch = jump_entry_branch(entry);
+   bool branch = jump_entry_is_branch(entry);
 
/* See the comment in linux/jump_label.h */
return enabled ^ branch;
@@ -370,12 +360,12 @@ static void __jump_label_update(struct static_key *key,
 * An entry->code of 0 indicates an entry which has been
 * disabled because it was in an init text area.
 */
-   if (entry->code) {
-   if (kernel_text_address(entry->code))
+   if (!jump_entry_is_init(entry)) {
+   if (kernel_text_address(jump_entry_code(entry)))
arch_jump_label_transform(entry, 
jump_label_type(entry));
else
WARN_ONCE(1, "can't patch jump_label at %pS",
- (void *)(unsigned long)entry->code);
+ (void *)jump_entry_code(entry));
}

[tip:core/core] jump_label: Implement generic support for relative references

2018-09-27 Thread tip-bot for Ard Biesheuvel
Commit-ID:  50ff18ab497aa22f6a59444625df7508c8918237
Gitweb: https://git.kernel.org/tip/50ff18ab497aa22f6a59444625df7508c8918237
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Sep 2018 23:51:37 -0700
Committer:  Thomas Gleixner 
CommitDate: Thu, 27 Sep 2018 17:56:47 +0200

jump_label: Implement generic support for relative references

To reduce the size taken up by absolute references in jump label
entries themselves and the associated relocation records in the
.init segment, add support for emitting them as relative references
instead.

Note that this requires some extra care in the sorting routine, given
that the offsets change when entries are moved around in the jump_entry
table.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Thomas Gleixner 
Acked-by: Peter Zijlstra (Intel) 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-s...@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Heiko Carstens 
Cc: Kees Cook 
Cc: Will Deacon 
Cc: Catalin Marinas 
Cc: Steven Rostedt 
Cc: Martin Schwidefsky 
Cc: Jessica Yu 
Link: https://lkml.kernel.org/r/20180919065144.25010-3-ard.biesheu...@linaro.org

---
 arch/Kconfig   |  3 +++
 include/linux/jump_label.h | 28 
 kernel/jump_label.c| 22 +-
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 6801123932a5..9d329608913e 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -359,6 +359,9 @@ config HAVE_PERF_USER_STACK_DUMP
 config HAVE_ARCH_JUMP_LABEL
bool
 
+config HAVE_ARCH_JUMP_LABEL_RELATIVE
+   bool
+
 config HAVE_RCU_TABLE_FREE
bool
 
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 2eadff9b3b90..2768a925bafa 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -121,6 +121,32 @@ struct static_key {
 #include 
 
 #ifndef __ASSEMBLY__
+#ifdef CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE
+
+struct jump_entry {
+   s32 code;
+   s32 target;
+   long key;   // key may be far away from the core kernel under KASLR
+};
+
+static inline unsigned long jump_entry_code(const struct jump_entry *entry)
+{
+   return (unsigned long)&entry->code + entry->code;
+}
+
+static inline unsigned long jump_entry_target(const struct jump_entry *entry)
+{
+   return (unsigned long)&entry->target + entry->target;
+}
+
+static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
+{
+   long offset = entry->key & ~1L;
+
+   return (struct static_key *)((unsigned long)&entry->key + offset);
+}
+
+#else
 
 static inline unsigned long jump_entry_code(const struct jump_entry *entry)
 {
@@ -137,6 +163,8 @@ static inline struct static_key *jump_entry_key(const 
struct jump_entry *entry)
return (struct static_key *)((unsigned long)entry->key & ~1UL);
 }
 
+#endif
+
 static inline bool jump_entry_is_branch(const struct jump_entry *entry)
 {
return (unsigned long)entry->key & 1UL;
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 834e43de0daf..898a1d0c38dc 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -47,14 +47,34 @@ static int jump_label_cmp(const void *a, const void *b)
return 0;
 }
 
+static void jump_label_swap(void *a, void *b, int size)
+{
+   long delta = (unsigned long)a - (unsigned long)b;
+   struct jump_entry *jea = a;
+   struct jump_entry *jeb = b;
+   struct jump_entry tmp = *jea;
+
+   jea->code   = jeb->code - delta;
+   jea->target = jeb->target - delta;
+   jea->key= jeb->key - delta;
+
+   jeb->code   = tmp.code + delta;
+   jeb->target = tmp.target + delta;
+   jeb->key= tmp.key + delta;
+}
+
 static void
 jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop)
 {
unsigned long size;
+   void *swapfn = NULL;
+
+   if (IS_ENABLED(CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE))
+   swapfn = jump_label_swap;
 
size = (((unsigned long)stop - (unsigned long)start)
/ sizeof(struct jump_entry));
-   sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
+   sort(start, size, sizeof(struct jump_entry), jump_label_cmp, swapfn);
 }
 
 static void jump_label_update(struct static_key *key);


[tip:efi/core] efi/x86: Replace references to efi_early->is64 with efi_is_64bit()

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  aab9593c0cb4454f9d261a8c87a3361f3186c4ec
Gitweb: https://git.kernel.org/tip/aab9593c0cb4454f9d261a8c87a3361f3186c4ec
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:24 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Replace references to efi_early->is64 with efi_is_64bit()

There are a couple of places in the x86 EFI stub code where we select
between 32-bit and 64-bit versions of the support routines based on
the value of efi_early->is64. Referencing that field directly is a
bad idea, since it prevents the compiler from inferring that this
field can never be true on a 32-bit build, and can only become false
on a 64-bit build if support for mixed mode is compiled in. This
results in dead code to be retained in the uncompressed part of the
kernel image, which is wasteful.

So switch to the efi_is_64bit() helper, which will resolve to a
constant boolean unless building for 64-bit with mixed mode support.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 915c64edbe8e..1458b1700fc7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -404,7 +404,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
return NULL;
 
-   if (efi_early->is64)
+   if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
@@ -639,7 +639,6 @@ struct exit_boot_struct {
struct efi_info *efi;
struct setup_data   *e820ext;
__u32   e820ext_size;
-   boolis64;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -666,7 +665,8 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
first = false;
}
 
-   signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
+   signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE
+  : EFI32_LOADER_SIGNATURE;
memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
 
p->efi->efi_systab  = (unsigned long)sys_table_arg;
@@ -683,8 +683,7 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return EFI_SUCCESS;
 }
 
-static efi_status_t exit_boot(struct boot_params *boot_params,
- void *handle, bool is64)
+static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 {
unsigned long map_sz, key, desc_size, buff_size;
efi_memory_desc_t *mem_map;
@@ -705,7 +704,6 @@ static efi_status_t exit_boot(struct boot_params 
*boot_params,
priv.efi= &boot_params->efi_info;
priv.e820ext= NULL;
priv.e820ext_size   = 0;
-   priv.is64   = is64;
 
/* Might as well exit boot services now */
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
@@ -740,13 +738,11 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
-   bool is64;
 
efi_early = c;
 
_table = (efi_system_table_t *)(unsigned long)efi_early->table;
handle = (void *)(unsigned long)efi_early->image_handle;
-   is64 = efi_early->is64;
 
sys_table = _table;
 
@@ -754,7 +750,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   if (is64)
+   if (efi_is_64bit())
setup_boot_services64(efi_early);
else
setup_boot_services32(efi_early);
@@ -810,7 +806,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
hdr->code32_start = bzimage_addr;
}
 
-   status = exit_boot(boot_params, handle, is64);
+   status = exit_boot(boot_params, handle);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "exit_boot() failed!\n");
goto fail;


[tip:efi/core] efi/x86: Add missing NULL initialization in UGA draw protocol discovery

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  093174f52553532b9eb0e63cbbb254f6990d46d5
Gitweb: https://git.kernel.org/tip/093174f52553532b9eb0e63cbbb254f6990d46d5
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:22 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Add missing NULL initialization in UGA draw protocol discovery

The UGA draw protocol discovery routine looks for a EFI handle that has
both the UGA draw protocol and the PCI I/O protocol installed. It checks
for the latter by calling handle_protocol() and pass it a PCI I/O
protocol pointer variable by reference, but fails to initialize it to
NULL, which means the non-NULL check later on in the code could produce
false positives, given that the return code of the handle_protocol() call
is ignored entirely. So add the missing initialization.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ac8e442db71f..92b573fd239c 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -359,6 +359,7 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, 
unsigned long size)
if (status != EFI_SUCCESS)
continue;
 
+   pciio = NULL;
efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
 
status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga,


[tip:efi/core] efi/x86: Align efi_uga_draw_protocol typedef names to convention

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0b767b16d7b634dd62667f224425cef3c78e031c
Gitweb: https://git.kernel.org/tip/0b767b16d7b634dd62667f224425cef3c78e031c
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:20 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Align efi_uga_draw_protocol typedef names to convention

The linux-efi subsystem uses typedefs with the _t suffix to declare
data structures that originate in the UEFI spec. Our type mangling
for mixed mode depends on this convention, so rename the UGA drawing
protocols to allow efi_call_proto() to be used with them in a
subsequent patch.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c |  4 ++--
 arch/x86/boot/compressed/eboot.h | 12 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c72550783c16..011d5c289449 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -321,7 +321,7 @@ static void setup_quirks(struct boot_params *boot_params)
 static efi_status_t
 setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
-   struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
u32 *handles = (u32 *)uga_handle;
@@ -366,7 +366,7 @@ setup_uga32(void **uga_handle, unsigned long size, u32 
*width, u32 *height)
 static efi_status_t
 setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
-   struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
u64 *handles = (u64 *)uga_handle;
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index e799dc5c6448..8297387c4676 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -12,22 +12,22 @@
 
 #define DESC_TYPE_CODE_DATA(1 << 0)
 
-struct efi_uga_draw_protocol_32 {
+typedef struct {
u32 get_mode;
u32 set_mode;
u32 blt;
-};
+} efi_uga_draw_protocol_32_t;
 
-struct efi_uga_draw_protocol_64 {
+typedef struct {
u64 get_mode;
u64 set_mode;
u64 blt;
-};
+} efi_uga_draw_protocol_64_t;
 
-struct efi_uga_draw_protocol {
+typedef struct {
void *get_mode;
void *set_mode;
void *blt;
-};
+} efi_uga_draw_protocol_t;
 
 #endif /* BOOT_COMPRESSED_EBOOT_H */


[tip:efi/core] efi/x86: Prevent reentrant firmware calls in mixed mode

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  83a0a2ea0b991927e42984be220329e776ce7137
Gitweb: https://git.kernel.org/tip/83a0a2ea0b991927e42984be220329e776ce7137
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:18 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Prevent reentrant firmware calls in mixed mode

The UEFI spec does not permit runtime services to be called
reentrantly, and so it is up to the OS to provide proper locking
around such calls.

For the native case, this was fixed a long time ago, but for the
mixed mode case, no locking is done whatsoever. Note that the calls
are made with preemption and interrupts disabled, so only SMP
configurations are affected by this issue.

So add a spinlock and grab it when invoking a UEFI runtime service
in mixed mode. We will also need to provide non-blocking versions
of SetVariable() and QueryVariableInfo(), so add those as well.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/efi_64.c | 101 +++--
 1 file changed, 98 insertions(+), 3 deletions(-)

diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 77873ce700ae..448267f1c073 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -636,6 +636,8 @@ void efi_switch_mm(struct mm_struct *mm)
 #ifdef CONFIG_EFI_MIXED
 extern efi_status_t efi64_thunk(u32, ...);
 
+static DEFINE_SPINLOCK(efi_runtime_lock);
+
 #define runtime_service32(func)
 \
 ({  \
u32 table = (u32)(unsigned long)efi.systab;  \
@@ -657,17 +659,14 @@ extern efi_status_t efi64_thunk(u32, ...);
 #define efi_thunk(f, ...)  \
 ({ \
efi_status_t __s;   \
-   unsigned long __flags;  \
u32 __func; \
\
-   local_irq_save(__flags);\
arch_efi_call_virt_setup(); \
\
__func = runtime_service32(f);  \
__s = efi64_thunk(__func, __VA_ARGS__); \
\
arch_efi_call_virt_teardown();  \
-   local_irq_restore(__flags); \
\
__s;\
 })
@@ -702,14 +701,17 @@ static efi_status_t efi_thunk_get_time(efi_time_t *tm, 
efi_time_cap_t *tc)
 {
efi_status_t status;
u32 phys_tm, phys_tc;
+   unsigned long flags;
 
spin_lock(&rtc_lock);
+   spin_lock_irqsave(&efi_runtime_lock, flags);
 
phys_tm = virt_to_phys_or_null(tm);
phys_tc = virt_to_phys_or_null(tc);
 
status = efi_thunk(get_time, phys_tm, phys_tc);
 
+   spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
 
return status;
@@ -719,13 +721,16 @@ static efi_status_t efi_thunk_set_time(efi_time_t *tm)
 {
efi_status_t status;
u32 phys_tm;
+   unsigned long flags;
 
spin_lock(&rtc_lock);
+   spin_lock_irqsave(&efi_runtime_lock, flags);
 
phys_tm = virt_to_phys_or_null(tm);
 
status = efi_thunk(set_time, phys_tm);
 
+   spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
 
return status;
@@ -737,8 +742,10 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t 
*pending,
 {
efi_status_t status;
u32 phys_enabled, phys_pending, phys_tm;
+   unsigned long flags;
 
spin_lock(&rtc_lock);
+   spin_lock_irqsave(&efi_runtime_lock, flags);
 
phys_enabled = virt_to_phys_or_null(enabled);
phys_pending = virt_to_phys_or_null(pending);
@@ -747,6 +754,7 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t 
*pending,
status = efi_thunk(get_wakeup_time, phys_enabled,
 phys_pending, phys_tm);
 
+   spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
 
return status;
@@ -757,13 +765,16 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t 
*tm)
 {
 

[tip:efi/core] efi/x86: Merge 32-bit and 64-bit UGA draw protocol setup routines

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  290084c2fa13e9aaa7f856ed1ab30760327dd9f8
Gitweb: https://git.kernel.org/tip/290084c2fa13e9aaa7f856ed1ab30760327dd9f8
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:21 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:43 +0200

efi/x86: Merge 32-bit and 64-bit UGA draw protocol setup routines

The two versions of setup_uga##() are mostly identical, with the
exception of the size of EFI_HANDLE. So let's merge the two, and
pull the implementation into the calling function setup_uga().

Note that the 32-bit version was only mixed-mode safe by accident:
it only calls the get_mode() method of the UGA draw protocol, which
happens to be the first member, and so truncating the 64-bit void* at
offset 0 to 32 bits happens to produce the correct value. But let's
not rely on that, and use the proper API instead.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 111 +--
 1 file changed, 26 insertions(+), 85 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 011d5c289449..ac8e442db71f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -318,81 +318,54 @@ static void setup_quirks(struct boot_params *boot_params)
}
 }
 
+/*
+ * See if we have Universal Graphics Adapter (UGA) protocol
+ */
 static efi_status_t
-setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
+setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
 {
+   efi_status_t status;
+   u32 width, height;
+   void **uga_handle = NULL;
efi_uga_draw_protocol_t *uga = NULL, *first_uga;
-   efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
unsigned long nr_ugas;
-   u32 *handles = (u32 *)uga_handle;
-   efi_status_t status = EFI_INVALID_PARAMETER;
int i;
 
-   first_uga = NULL;
-   nr_ugas = size / sizeof(u32);
-   for (i = 0; i < nr_ugas; i++) {
-   efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u32 w, h, depth, refresh;
-   void *pciio;
-   u32 handle = handles[i];
-
-   status = efi_call_early(handle_protocol, handle,
-   &uga_proto, (void **)&uga);
-   if (status != EFI_SUCCESS)
-   continue;
-
-   efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
-
-   status = efi_early->call((unsigned long)uga->get_mode, uga,
-&w, &h, &depth, &refresh);
-   if (status == EFI_SUCCESS && (!first_uga || pciio)) {
-   *width = w;
-   *height = h;
-
-   /*
-* Once we've found a UGA supporting PCIIO,
-* don't bother looking any further.
-*/
-   if (pciio)
-   break;
-
-   first_uga = uga;
-   }
-   }
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   size, (void **)&uga_handle);
+   if (status != EFI_SUCCESS)
+   return status;
 
-   return status;
-}
+   status = efi_call_early(locate_handle,
+   EFI_LOCATE_BY_PROTOCOL,
+   uga_proto, NULL, &size, uga_handle);
+   if (status != EFI_SUCCESS)
+   goto free_handle;
 
-static efi_status_t
-setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
-{
-   efi_uga_draw_protocol_t *uga = NULL, *first_uga;
-   efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
-   unsigned long nr_ugas;
-   u64 *handles = (u64 *)uga_handle;
-   efi_status_t status = EFI_INVALID_PARAMETER;
-   int i;
+   height = 0;
+   width = 0;
 
first_uga = NULL;
-   nr_ugas = size / sizeof(u64);
+   nr_ugas = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
for (i = 0; i < nr_ugas; i++) {
efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 w, h, depth, refresh;
void *pciio;
-   u64 handle = handles[i];
+   unsigned long handle = efi_is_64bit() ? ((u64 *)uga_handle)[i]
+ : ((u32 *)uga_handle)[i];
 
status = efi_call_early(handle_protocol, handle,
-   &uga_proto, (void **)&uga);
+   uga_proto, (void **)&uga);
if (status != EFI_SUCCESS)
   

[tip:efi/core] efi/x86: Merge the setup_efi_pci32() and setup_efi_pci64() routines

2018-07-22 Thread tip-bot for Ard Biesheuvel
Commit-ID:  75c5a713ab4b774c7d990ec748dddba714034436
Gitweb: https://git.kernel.org/tip/75c5a713ab4b774c7d990ec748dddba714034436
Author: Ard Biesheuvel 
AuthorDate: Fri, 20 Jul 2018 10:47:19 +0900
Committer:  Ingo Molnar 
CommitDate: Sun, 22 Jul 2018 14:13:42 +0200

efi/x86: Merge the setup_efi_pci32() and setup_efi_pci64() routines

After merging the 32-bit and 64-bit versions of the code that invokes
the PCI I/O protocol methods to preserve PCI ROM images in commit:

  2c3625cb9fa2 ("efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() ...")

there are still separate code paths for 32-bit and 64-bit, where the only
difference is the size of a EFI_HANDLE. So let's parameterize a single
implementation for that difference only, and get rid of the two copies of
the code.

While at it, rename __setup_efi_pci() to preserve_pci_rom_image() to
better reflect its purpose.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Shevchenko 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180720014726.24031-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 123 ++-
 1 file changed, 32 insertions(+), 91 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 9f6813493945..c72550783c16 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -111,7 +111,7 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom 
**__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
@@ -181,92 +181,6 @@ free_struct:
return status;
 }
 
-static void
-setup_efi_pci32(struct boot_params *params, void **pci_handle, unsigned long 
size)
-{
-   efi_pci_io_protocol_t *pci = NULL;
-   efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u32 *handles = (u32 *)(unsigned long)pci_handle;
-   efi_status_t status;
-   unsigned long nr_pci;
-   struct setup_data *data;
-   int i;
-
-   data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
-
-   while (data && data->next)
-   data = (struct setup_data *)(unsigned long)data->next;
-
-   nr_pci = size / sizeof(u32);
-   for (i = 0; i < nr_pci; i++) {
-   struct pci_setup_rom *rom = NULL;
-   u32 h = handles[i];
-
-   status = efi_call_early(handle_protocol, h,
-   &pci_proto, (void **)&pci);
-
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (!pci)
-   continue;
-
-   status = __setup_efi_pci(pci, &rom);
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (data)
-   data->next = (unsigned long)rom;
-   else
-   params->hdr.setup_data = (unsigned long)rom;
-
-   data = (struct setup_data *)rom;
-   }
-}
-
-static void
-setup_efi_pci64(struct boot_params *params, void **pci_handle, unsigned long 
size)
-{
-   efi_pci_io_protocol_t *pci = NULL;
-   efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
-   u64 *handles = (u64 *)(unsigned long)pci_handle;
-   efi_status_t status;
-   unsigned long nr_pci;
-   struct setup_data *data;
-   int i;
-
-   data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
-
-   while (data && data->next)
-   data = (struct setup_data *)(unsigned long)data->next;
-
-   nr_pci = size / sizeof(u64);
-   for (i = 0; i < nr_pci; i++) {
-   struct pci_setup_rom *rom = NULL;
-   u64 h = handles[i];
-
-   status = efi_call_early(handle_protocol, h,
-   &pci_proto, (void **)&pci);
-
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (!pci)
-   continue;
-
-   status = __setup_efi_pci(pci, &rom);
-   if (status != EFI_SUCCESS)
-   continue;
-
-   if (data)
-   data->next = (unsigned long)rom;
-   else
-   params->hdr.setup_data = (unsigned long)rom;
-
-   data = (struct setup_data *)rom;
-   }
-}
-
 /*
  * There's no way to return an informative status from this function,
  * because any analysis (and printing of error messages) needs to be
@@ -282,6 +196,9 @@ static void setup_efi_pci(struct boot_params *params)
void **pci_handle = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
unsigned long size = 0;
+   u

[tip:efi/core] fbdev/efifb: Honour UEFI memory map attributes when mapping the FB

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  38ac0287b7f4f3922e25fd8f81db67f2c13d16bb
Gitweb: https://git.kernel.org/tip/38ac0287b7f4f3922e25fd8f81db67f2c13d16bb
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:40 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

fbdev/efifb: Honour UEFI memory map attributes when mapping the FB

If the framebuffer address provided by the Graphics Output Protocol
(GOP) is covered by the UEFI memory map, it will tell us which memory
attributes are permitted when mapping this region. In some cases,
(KVM guest on ARM), violating this will result in loss of coherency,
which means that updates sent to the framebuffer by the guest will
not be observeable by the host, and the emulated display simply does
not work.

So if the memory map contains such a description, take the attributes
field into account, and add support for creating WT or WB mappings of
the framebuffer region.

Tested-by: Laszlo Ersek 
Signed-off-by: Ard Biesheuvel 
Acked-by: Bartlomiej Zolnierkiewicz 
Cc: Linus Torvalds 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 51 -
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 46a4484e3da7..c6f78d27947b 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -20,7 +20,7 @@
 #include   /* For DRM_MODE_PANEL_ORIENTATION_* */
 
 static bool request_mem_succeeded = false;
-static bool nowc = false;
+static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
 
 static struct fb_var_screeninfo efifb_defined = {
.activate   = FB_ACTIVATE_NOW,
@@ -68,8 +68,12 @@ static int efifb_setcolreg(unsigned regno, unsigned red, 
unsigned green,
 
 static void efifb_destroy(struct fb_info *info)
 {
-   if (info->screen_base)
-   iounmap(info->screen_base);
+   if (info->screen_base) {
+   if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
+   iounmap(info->screen_base);
+   else
+   memunmap(info->screen_base);
+   }
if (request_mem_succeeded)
release_mem_region(info->apertures->ranges[0].base,
   info->apertures->ranges[0].size);
@@ -104,7 +108,7 @@ static int efifb_setup(char *options)
else if (!strncmp(this_opt, "width:", 6))
screen_info.lfb_width = 
simple_strtoul(this_opt+6, NULL, 0);
else if (!strcmp(this_opt, "nowc"))
-   nowc = true;
+   mem_flags &= ~EFI_MEMORY_WC;
}
}
 
@@ -164,6 +168,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_remap;
unsigned int size_total;
char *option = NULL;
+   efi_memory_desc_t md;
 
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
@@ -272,12 +277,35 @@ static int efifb_probe(struct platform_device *dev)
info->apertures->ranges[0].base = efifb_fix.smem_start;
info->apertures->ranges[0].size = size_remap;
 
-   if (nowc)
-   info->screen_base = ioremap(efifb_fix.smem_start, 
efifb_fix.smem_len);
-   else
-   info->screen_base = ioremap_wc(efifb_fix.smem_start, 
efifb_fix.smem_len);
+   if (!efi_mem_desc_lookup(efifb_fix.smem_start, &md)) {
+   if ((efifb_fix.smem_start + efifb_fix.smem_len) >
+   (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) {
+   pr_err("efifb: video memory @ 0x%lx spans multiple EFI 
memory regions\n",
+  efifb_fix.smem_start);
+   err = -EIO;
+   goto err_release_fb;
+   }
+   /*
+* If the UEFI memory map covers the efifb region, we may only
+* remap it using the attributes the memory map prescribes.
+*/
+   mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
+   mem_flags &= md.attribute;
+   }
+   if (mem_flags & EFI_MEMORY_WC)
+   info->screen_base = ioremap_wc(efifb_fix.smem_start,
+  efifb_fix.smem_len);
+   else if (mem_flags & EFI_MEMORY_UC)
+   info->screen_base = ioremap(efifb_fix.smem_start,
+   efifb_fix.smem_len);
+   else if (mem_flags & EFI_MEMORY_WT)
+   info->screen_base = memremap(efifb_fix.smem_start,
+efifb_fix.smem_len, MEMREMAP_WT);
+   else if (mem_flags & EFI_MEMORY_WB)
+   info->screen_base = memrema

[tip:efi/core] efi: Drop type and attribute checks in efi_mem_desc_lookup()

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  7e1550b8f2081cccdfa9f1cf1e54cbc4d720af7f
Gitweb: https://git.kernel.org/tip/7e1550b8f2081cccdfa9f1cf1e54cbc4d720af7f
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:39 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

efi: Drop type and attribute checks in efi_mem_desc_lookup()

The current implementation of efi_mem_desc_lookup() includes the
following check on the memory descriptor it returns:

if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
md->type != EFI_BOOT_SERVICES_DATA &&
md->type != EFI_RUNTIME_SERVICES_DATA) {
continue;
}

This means that only EfiBootServicesData or EfiRuntimeServicesData
regions are considered, or any other region type provided that it
has the EFI_MEMORY_RUNTIME attribute set.

Given what the name of the function implies, and the fact that any
physical address can be described in the UEFI memory map only a single
time, it does not make sense to impose this condition in the body of the
loop, but instead, should be imposed by the caller depending on the value
that is returned to it.

Two such callers exist at the moment:

- The BGRT code when running on x86, via efi_mem_reserve() and
  efi_arch_mem_reserve(). In this case, the region is already known to
  be EfiBootServicesData, and so the check is redundant.

- The ESRT handling code which introduced this function, which calls it
  both directly from efi_esrt_init() and again via efi_mem_reserve() and
  efi_arch_mem_reserve() [on x86].

So let's move this check into the callers instead. This preserves the
current behavior both for BGRT and ESRT handling, and allows the lookup
routine to be reused by other [upcoming] users that don't have this
limitation.

In the ESRT case, keep the entire condition, so that platforms that
deviate from the UEFI spec and use something other than
EfiBootServicesData for the ESRT table will keep working as before.

For x86's efi_arch_mem_reserve() implementation, limit the type to
EfiBootServicesData, since it is the only type the reservation code
expects to operate on in the first place.

While we're at it, drop the __init annotation so that drivers can use it
as well.

Tested-by: Laszlo Ersek 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/quirks.c | 3 ++-
 drivers/firmware/efi/efi.c | 8 +---
 drivers/firmware/efi/esrt.c| 5 -
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 6af39dc40325..844d31cb8a0c 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -248,7 +248,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
int num_entries;
void *new;
 
-   if (efi_mem_desc_lookup(addr, &md)) {
+   if (efi_mem_desc_lookup(addr, &md) ||
+   md.type != EFI_BOOT_SERVICES_DATA) {
pr_err("Failed to lookup EFI memory descriptor for %pa\n", 
&addr);
return;
}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1379a375dfa8..d8a33a781a57 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -402,7 +402,7 @@ subsys_initcall(efisubsys_init);
  * and if so, populate the supplied memory descriptor with the appropriate
  * data.
  */
-int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
+int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 {
efi_memory_desc_t *md;
 
@@ -420,12 +420,6 @@ int __init efi_mem_desc_lookup(u64 phys_addr, 
efi_memory_desc_t *out_md)
u64 size;
u64 end;
 
-   if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
-   md->type != EFI_BOOT_SERVICES_DATA &&
-   md->type != EFI_RUNTIME_SERVICES_DATA) {
-   continue;
-   }
-
size = md->num_pages << EFI_PAGE_SHIFT;
end = md->phys_addr + size;
if (phys_addr >= md->phys_addr && phys_addr < end) {
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 1ab80e06e7c5..375a77c1c6e5 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -250,7 +250,10 @@ void __init efi_esrt_init(void)
return;
 
rc = efi_mem_desc_lookup(efi.esrt, &md);
-   if (rc < 0) {
+   if (rc < 0 ||
+   (!(md.attribute & EFI_MEMORY_RUNTIME) &&
+md.type != EFI_BOOT_SERVICES_DATA &&
+md.type != EFI_RUNTIME_SERVICES_DATA)) {
pr_warn("ESRT header is not in the memory map.\n");
return;
}


[tip:efi/core] efi/libstub/arm: Add opt-in Kconfig option for the DTB loader

2018-07-15 Thread tip-bot for Ard Biesheuvel
Commit-ID:  3d7ee348aa4127a7893c11261da9b76371a970e6
Gitweb: https://git.kernel.org/tip/3d7ee348aa4127a7893c11261da9b76371a970e6
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:40:38 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 16 Jul 2018 00:43:12 +0200

efi/libstub/arm: Add opt-in Kconfig option for the DTB loader

There are various ways a platform can provide a device tree binary
to the kernel, with different levels of sophistication:

- ideally, the UEFI firmware, which is tightly coupled with the
  platform, provides a device tree image directly as a UEFI
  configuration table, and typically permits the contents to be
  manipulated either via menu options or via UEFI environment
  variables that specify a replacement image,

- GRUB for ARM has a 'devicetree' directive which allows a device
  tree image to be loaded from any location accessible to GRUB, and
  supersede the one provided by the firmware,

- the EFI stub implements a dtb= command line option that allows a
  device tree image to be loaded from a file residing in the same
  file system as the one the kernel image was loaded from.

The dtb= command line option was never intended to be more than a
development feature, to allow the other options to be implemented
in parallel. So let's make it an opt-in feature that is disabled
by default, but can be re-enabled at will.

Note that we already disable the dtb= command line option when we
detect that we are running with UEFI Secure Boot enabled.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Alexander Graf 
Acked-by: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711094040.12506-7-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/Kconfig| 12 
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 781a4a337557..d8e159feb573 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -87,6 +87,18 @@ config EFI_RUNTIME_WRAPPERS
 config EFI_ARMSTUB
bool
 
+config EFI_ARMSTUB_DTB_LOADER
+   bool "Enable the DTB loader"
+   depends on EFI_ARMSTUB
+   help
+ Select this config option to add support for the dtb= command
+ line parameter, allowing a device tree blob to be loaded into
+ memory from the EFI System Partition by the stub.
+
+ The device tree is typically provided by the platform or by
+ the bootloader, so this option is mostly for development
+ purposes only.
+
 config EFI_BOOTLOADER_CONTROL
tristate "EFI Bootloader Control"
depends on EFI_VARS
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 01a9d78ee415..c98b1856fc3d 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -202,9 +202,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 * 'dtb=' unless UEFI Secure Boot is disabled.  We assume that secure
 * boot is enabled if we can't determine its state.
 */
-   if (secure_boot != efi_secureboot_mode_disabled &&
-   strstr(cmdline_ptr, "dtb=")) {
-   pr_efi(sys_table, "Ignoring DTB from command line.\n");
+   if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+secure_boot != efi_secureboot_mode_disabled) {
+   if (strstr(cmdline_ptr, "dtb="))
+   pr_efi(sys_table, "Ignoring DTB from command line.\n");
} else {
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
  "dtb=",


[tip:efi/urgent] efi/x86: Fix mixed mode reboot loop by removing pointless call to PciIo->Attributes()

2018-07-11 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e296701800f30d260a66f8aa1971b5b1bc3d2f81
Gitweb: https://git.kernel.org/tip/e296701800f30d260a66f8aa1971b5b1bc3d2f81
Author: Ard Biesheuvel 
AuthorDate: Wed, 11 Jul 2018 11:02:35 +0200
Committer:  Ingo Molnar 
CommitDate: Wed, 11 Jul 2018 13:15:21 +0200

efi/x86: Fix mixed mode reboot loop by removing pointless call to 
PciIo->Attributes()

Hans de Goede reported that his mixed EFI mode Bay Trail tablet
would not boot at all any more, but enter a reboot loop without
any logs printed by the kernel.

Unbreak 64-bit Linux/x86 on 32-bit UEFI:

When it was first introduced, the EFI stub code that copies the
contents of PCI option ROMs originally only intended to do so if
the EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM attribute was *not* set.

The reason was that the UEFI spec permits PCI option ROM images
to be provided by the platform directly, rather than via the ROM
BAR, and in this case, the OS can only access them at runtime if
they are preserved at boot time by copying them from the areas
described by PciIo->RomImage and PciIo->RomSize.

However, it implemented this check erroneously, as can be seen in
commit:

  dd5fc854de5fd ("EFI: Stash ROMs if they're not in the PCI BAR")

which introduced:

if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
continue;

and given that the numeric value of EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
is 0x4000, this condition never becomes true, and so the option ROMs
were copied unconditionally.

This was spotted and 'fixed' by commit:

  886d751a2ea99a160 ("x86, efi: correct precedence of operators in 
setup_efi_pci")

but inadvertently inverted the logic at the same time, defeating
the purpose of the code, since it now only preserves option ROM
images that can be read from the ROM BAR as well.

Unsurprisingly, this broke some systems, and so the check was removed
entirely in the following commit:

  739701888f5d ("x86, efi: remove attribute check from setup_efi_pci")

It is debatable whether this check should have been included in the
first place, since the option ROM image provided to the UEFI driver by
the firmware may be different from the one that is actually present in
the card's flash ROM, and so whatever PciIo->RomImage points at should
be preferred regardless of whether the attribute is set.

As this was the only use of the attributes field, we can remove
the call to PciIo->Attributes() entirely, which is especially
nice because its prototype involves uint64_t type by-value
arguments which the EFI mixed mode has trouble dealing with.

Any mixed mode system with PCI is likely to be affected.

Tested-by: Wilfried Klaebe 
Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180711090235.9327-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index e57665b4ba1c..e98522ea6f09 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -114,18 +114,12 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct 
pci_setup_rom **__rom)
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
-   uint64_t attributes, romsize;
+   uint64_t romsize;
void *romimage;
 
-   status = efi_call_proto(efi_pci_io_protocol, attributes, pci,
-   EfiPciIoAttributeOperationGet, 0ULL,
-   &attributes);
-   if (status != EFI_SUCCESS)
-   return status;
-
/*
-* Some firmware images contain EFI function pointers at the place 
where the
-* romimage and romsize fields are supposed to be. Typically the EFI
+* Some firmware images contain EFI function pointers at the place where
+* the romimage and romsize fields are supposed to be. Typically the EFI
 * code is mapped at high addresses, translating to an unrealistically
 * large romsize. The UEFI spec limits the size of option ROMs to 16
 * MiB so we reject any ROMs over 16 MiB in size to catch this.


[tip:efi/core] efi: Align efi_pci_io_protocol typedefs to type naming convention

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  cb0ba793525788e40e7a9ee82de8f3b017ca4459
Gitweb: https://git.kernel.org/tip/cb0ba793525788e40e7a9ee82de8f3b017ca4459
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 07:59:59 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:57:48 +0200

efi: Align efi_pci_io_protocol typedefs to type naming convention

In order to use the helper macros that perform type mangling with the
EFI PCI I/O protocol struct typedefs, align their Linux typenames with
the convention we use for definitionns that originate in the UEFI spec,
and add the trailing _t to each.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-14-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 8 
 include/linux/efi.h  | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 09f36c0d9d4f..3994f48c4043 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -109,7 +109,7 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
@@ -176,7 +176,7 @@ static void
 setup_efi_pci32(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_32 *pci = NULL;
+   efi_pci_io_protocol_32_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 *handles = (u32 *)(unsigned long)pci_handle;
efi_status_t status;
@@ -218,7 +218,7 @@ setup_efi_pci32(struct boot_params *params, void 
**pci_handle,
 }
 
 static efi_status_t
-__setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci64(efi_pci_io_protocol_64_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom;
efi_status_t status;
@@ -284,7 +284,7 @@ static void
 setup_efi_pci64(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_64 *pci = NULL;
+   efi_pci_io_protocol_64_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u64 *handles = (u64 *)(unsigned long)pci_handle;
efi_status_t status;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 3016d8c456bc..56add823f190 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -397,7 +397,7 @@ typedef struct {
u32 set_bar_attributes;
u64 romsize;
u32 romimage;
-} efi_pci_io_protocol_32;
+} efi_pci_io_protocol_32_t;
 
 typedef struct {
u64 poll_mem;
@@ -417,7 +417,7 @@ typedef struct {
u64 set_bar_attributes;
u64 romsize;
u64 romimage;
-} efi_pci_io_protocol_64;
+} efi_pci_io_protocol_64_t;
 
 typedef struct {
void *poll_mem;
@@ -437,7 +437,7 @@ typedef struct {
void *set_bar_attributes;
uint64_t romsize;
void *romimage;
-} efi_pci_io_protocol;
+} efi_pci_io_protocol_t;
 
 #define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
 #define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002


[tip:efi/core] efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2c3625cb9fa2c477d5877a1819e29d6a902e5fef
Gitweb: https://git.kernel.org/tip/2c3625cb9fa2c477d5877a1819e29d6a902e5fef
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 08:00:00 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:57:49 +0200

efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function

As suggested by Lukas, use his efi_call_proto() and efi_table_attr()
macros to merge __setup_efi_pci32() and __setup_efi_pci64() into a
single function, removing the need to duplicate changes made in
subsequent patches across both.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-15-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 107 +--
 1 file changed, 25 insertions(+), 82 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 3994f48c4043..dadf32312082 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -109,23 +109,27 @@ void efi_char16_printk(efi_system_table_t *table, 
efi_char16_t *str)
 }
 
 static efi_status_t
-__setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct pci_setup_rom **__rom)
+__setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 {
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
-   uint64_t attributes;
+   uint64_t attributes, romsize;
+   void *romimage;
 
-   status = efi_early->call(pci->attributes, pci,
-EfiPciIoAttributeOperationGet, 0, 0,
-&attributes);
+   status = efi_call_proto(efi_pci_io_protocol, attributes, pci,
+   EfiPciIoAttributeOperationGet, 0, 0,
+   &attributes);
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   romimage = (void *)(unsigned long)efi_table_attr(efi_pci_io_protocol,
+romimage, pci);
+   romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
+   if (!romimage || !romsize)
return EFI_INVALID_PARAMETER;
 
-   size = pci->romsize + sizeof(*rom);
+   size = romsize + sizeof(*rom);
 
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
if (status != EFI_SUCCESS) {
@@ -141,30 +145,32 @@ __setup_efi_pci32(efi_pci_io_protocol_32_t *pci, struct 
pci_setup_rom **__rom)
rom->pcilen = pci->romsize;
*__rom = rom;
 
-   status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
-PCI_VENDOR_ID, 1, &(rom->vendor));
+   status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
+   EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+   &rom->vendor);
 
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to read rom->vendor\n");
goto free_struct;
}
 
-   status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
-PCI_DEVICE_ID, 1, &(rom->devid));
+   status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
+   EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+   &rom->devid);
 
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to read rom->devid\n");
goto free_struct;
}
 
-   status = efi_early->call(pci->get_location, pci, &(rom->segment),
-&(rom->bus), &(rom->device), &(rom->function));
+   status = efi_call_proto(efi_pci_io_protocol, get_location, pci,
+   &rom->segment, &rom->bus, &rom->device,
+   &rom->function);
 
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
-  pci->romsize);
+   memcpy(rom->romdata, romimage, romsize);
return status;
 
 free_struct:
@@ -176,7 +182,7 @@ static void
 setup_efi_pci32(struct boot_params *params, void **pci_handle,
unsigned long size)
 {
-   efi_pci_io_protocol_32_t *pci = NULL;
+   efi_pci_io_protocol_t *pci = NULL;
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
u32 *handles = (u32 *)(unsigned long)pci_handle;
efi_status_t status;
@@ -203,7 +209,7 @@ setup_efi_pci32(struct boot_params *params, void 
**pci_handle,
if (!pci)
continue;
 
-   status = __setup_efi_pci32(pci, &rom);
+   status = __setup_efi_pci(pci, 

[tip:efi/core] efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' definition for mixed mode

2018-05-14 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0b3225ab9407f557a8e20f23f37aa7236c10a9b1
Gitweb: https://git.kernel.org/tip/0b3225ab9407f557a8e20f23f37aa7236c10a9b1
Author: Ard Biesheuvel 
AuthorDate: Fri, 4 May 2018 07:59:58 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 08:56:29 +0200

efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' 
definition for mixed mode

Mixed mode allows a kernel built for x86_64 to interact with 32-bit
EFI firmware, but requires us to define all struct definitions carefully
when it comes to pointer sizes.

'struct efi_pci_io_protocol_32' currently uses a 'void *' for the
'romimage' field, which will be interpreted as a 64-bit field
on such kernels, potentially resulting in bogus memory references
and subsequent crashes.

Tested-by: Hans de Goede 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-13-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c | 6 --
 include/linux/efi.h  | 8 
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..09f36c0d9d4f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -163,7 +163,8 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, pci->romimage, pci->romsize);
+   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+  pci->romsize);
return status;
 
 free_struct:
@@ -269,7 +270,8 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
goto free_struct;
 
-   memcpy(rom->romdata, pci->romimage, pci->romsize);
+   memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+  pci->romsize);
return status;
 
 free_struct:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f1b7d68ac460..3016d8c456bc 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -395,8 +395,8 @@ typedef struct {
u32 attributes;
u32 get_bar_attributes;
u32 set_bar_attributes;
-   uint64_t romsize;
-   void *romimage;
+   u64 romsize;
+   u32 romimage;
 } efi_pci_io_protocol_32;
 
 typedef struct {
@@ -415,8 +415,8 @@ typedef struct {
u64 attributes;
u64 get_bar_attributes;
u64 set_bar_attributes;
-   uint64_t romsize;
-   void *romimage;
+   u64 romsize;
+   u64 romimage;
 } efi_pci_io_protocol_64;
 
 typedef struct {


[tip:efi/urgent] efi/libstub/tpm: Initialize pointer variables to zero for mixed mode

2018-03-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  79832f0b5f718e0023d9dd73e6845310609a564d
Gitweb: https://git.kernel.org/tip/79832f0b5f718e0023d9dd73e6845310609a564d
Author: Ard Biesheuvel 
AuthorDate: Tue, 13 Mar 2018 14:09:21 +
Committer:  Ingo Molnar 
CommitDate: Tue, 13 Mar 2018 15:28:29 +0100

efi/libstub/tpm: Initialize pointer variables to zero for mixed mode

As reported by Jeremy Cline, running the new TPM libstub code in mixed
mode (i.e., 64-bit kernel on 32-bit UEFI) results in hangs when invoking
the TCG2 protocol, or when accessing the log_tbl pool allocation.

The reason turns out to be that in both cases, the 64-bit pointer
variables are not fully initialized by the 32-bit EFI code, and so
we should take care to zero initialize these variables beforehand,
or we'll end up dereferencing bogus pointers.

Reported-by: Jeremy Cline 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: hdego...@redhat.com
Cc: jarkko.sakki...@linux.intel.com
Cc: javi...@redhat.com
Cc: linux-...@vger.kernel.org
Cc: tw...@google.com
Link: http://lkml.kernel.org/r/20180313140922.17266-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/tpm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
index da661bf8cb96..13c1edd37e96 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -68,11 +68,11 @@ void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t 
*sys_table_arg)
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
efi_physical_addr_t log_location, log_last_entry;
-   struct linux_efi_tpm_eventlog *log_tbl;
+   struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
efi_bool_t truncated;
-   void *tcg2_protocol;
+   void *tcg2_protocol = NULL;
 
status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
&tcg2_protocol);


[tip:efi/core] efi: Use string literals for efi_char16_t variable initializers

2018-03-12 Thread tip-bot for Ard Biesheuvel
Commit-ID:  36b649760e94968e0495b73284aaf07eed0a328f
Gitweb: https://git.kernel.org/tip/36b649760e94968e0495b73284aaf07eed0a328f
Author: Ard Biesheuvel 
AuthorDate: Mon, 12 Mar 2018 08:45:00 +
Committer:  Ingo Molnar 
CommitDate: Mon, 12 Mar 2018 10:05:02 +0100

efi: Use string literals for efi_char16_t variable initializers

Now that we unambiguously build the entire kernel with -fshort-wchar,
it is no longer necessary to open code efi_char16_t[] initializers as
arrays of characters, and we can move to the L"xxx" notation instead.

Signed-off-by: Ard Biesheuvel 
Cc: Arnd Bergmann 
Cc: Linus Torvalds 
Cc: Lukas Wunner 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180312084500.10764-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/boot/compressed/eboot.c  |  3 ++-
 arch/x86/platform/efi/quirks.c|  8 +---
 drivers/firmware/efi/libstub/Makefile |  2 +-
 drivers/firmware/efi/libstub/secureboot.c | 12 +++-
 drivers/firmware/efi/libstub/tpm.c|  7 ++-
 5 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index f2251c1c9853..47d3efff6805 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -421,9 +421,10 @@ static void retrieve_apple_device_properties(struct 
boot_params *boot_params)
}
 }
 
+static const efi_char16_t apple[] = L"Apple";
+
 static void setup_quirks(struct boot_params *boot_params)
 {
-   static efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
efi_table_attr(efi_system_table, fw_vendor, sys_table);
 
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 1ef11c26f79b..36c1f8b9f7e0 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -75,7 +75,7 @@ struct quark_security_header {
u32 rsvd[2];
 };
 
-static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
+static const efi_char16_t efi_dummy_name[] = L"DUMMY";
 
 static bool efi_no_storage_paranoia;
 
@@ -105,7 +105,8 @@ early_param("efi_no_storage_paranoia", 
setup_storage_paranoia);
 */
 void efi_delete_dummy_variable(void)
 {
-   efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+   efi.set_variable((efi_char16_t *)efi_dummy_name,
+&EFI_DUMMY_GUID,
 EFI_VARIABLE_NON_VOLATILE |
 EFI_VARIABLE_BOOTSERVICE_ACCESS |
 EFI_VARIABLE_RUNTIME_ACCESS,
@@ -182,7 +183,8 @@ efi_status_t efi_query_variable_store(u32 attributes, 
unsigned long size,
if (!dummy)
return EFI_OUT_OF_RESOURCES;
 
-   status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+   status = efi.set_variable((efi_char16_t *)efi_dummy_name,
+ &EFI_DUMMY_GUID,
  EFI_VARIABLE_NON_VOLATILE |
  EFI_VARIABLE_BOOTSERVICE_ACCESS |
  EFI_VARIABLE_RUNTIME_ACCESS,
diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 7b3ba40f0745..a34e9290a699 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -9,7 +9,7 @@ cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64):= -mcmodel=small
 cflags-$(CONFIG_X86)   += -m$(BITS) -D__KERNEL__ -O2 \
   -fPIC -fno-strict-aliasing -mno-red-zone \
-  -mno-mmx -mno-sse
+  -mno-mmx -mno-sse -fshort-wchar
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
 cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
diff --git a/drivers/firmware/efi/libstub/secureboot.c 
b/drivers/firmware/efi/libstub/secureboot.c
index 959777ec8a77..8f07eb414c00 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -16,18 +16,12 @@
 
 /* BIOS variables */
 static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
-static const efi_char16_t efi_SecureBoot_name[] = {
-   'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
-};
-static const efi_char16_t efi_SetupMode_name[] = {
-   'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
-};
+static const efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
+static const efi_char16_t efi_SetupMode_name[] = L"SetupMode";
 
 /* SHIM variables */
 static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
-static efi_char16_t const shim_MokSBState_name[] = {
-   'M', 'o', 'k', 'S', 'B', 'S', 't', 'a', 't', 'e', 0
-};
+static const efi_char16_t shim_MokSBStat

[tip:efi/core] efi/esrt: Fix handling of early ESRT table mapping

2018-03-12 Thread tip-bot for Ard Biesheuvel
Commit-ID:  136d5d57e35cc6985c57d23d0c823133e3508bed
Gitweb: https://git.kernel.org/tip/136d5d57e35cc6985c57d23d0c823133e3508bed
Author: Ard Biesheuvel 
AuthorDate: Mon, 12 Mar 2018 08:44:59 +
Committer:  Ingo Molnar 
CommitDate: Mon, 12 Mar 2018 10:05:01 +0100

efi/esrt: Fix handling of early ESRT table mapping

As reported by Tyler, efi_esrt_init() will return without releasing the
ESRT table header mapping if it encounters a table with an unexpected
version. Replacing the 'return' with 'goto err_memunmap' would fix this
particular occurrence, but, as it turns out, the code is rather peculiar
to begin with:

 - it never uses the header mapping after memcpy()'ing out its contents,
 - it maps and unmaps the entire table without ever looking at the
   contents.

So let's refactor this code to unmap the table header right after the
memcpy() so we can get rid of the error handling path altogether, and
drop the second mapping entirely.

Reported-by: Tyler Baicar 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180312084500.10764-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/esrt.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index c47e0c6ec00f..1ab80e06e7c5 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -279,6 +279,7 @@ void __init efi_esrt_init(void)
}
 
memcpy(&tmpesrt, va, sizeof(tmpesrt));
+   early_memunmap(va, size);
 
if (tmpesrt.fw_resource_version == 1) {
entry_size = sizeof (*v1_entries);
@@ -291,7 +292,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) {
pr_err("ESRT memory map entry can only hold the header. (max: 
%zu size: %zu)\n",
   max - size, entry_size);
-   goto err_memunmap;
+   return;
}
 
/*
@@ -304,7 +305,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 128) {
pr_err("ESRT says fw_resource_count has very large value %d.\n",
   tmpesrt.fw_resource_count);
-   goto err_memunmap;
+   return;
}
 
/*
@@ -315,18 +316,10 @@ void __init efi_esrt_init(void)
if (max < size + entries_size) {
pr_err("ESRT does not fit on single memory map entry (size: %zu 
max: %zu)\n",
   size, max);
-   goto err_memunmap;
+   return;
}
 
-   /* remap it with our (plausible) new pages */
-   early_memunmap(va, size);
size += entries_size;
-   va = early_memremap(efi.esrt, size);
-   if (!va) {
-   pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
-  size);
-   return;
-   }
 
esrt_data = (phys_addr_t)efi.esrt;
esrt_data_size = size;
@@ -336,8 +329,6 @@ void __init efi_esrt_init(void)
efi_mem_reserve(esrt_data, esrt_data_size);
 
pr_debug("esrt-init: loaded.\n");
-err_memunmap:
-   early_memunmap(va, size);
 }
 
 static int __init register_entries(void)


[tip:efi/core] efi: Reorder pr_notice() with add_device_randomness() call

2018-03-09 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5b4e4c3aa220d07d166d3f21f158bc9c69e3c044
Gitweb: https://git.kernel.org/tip/5b4e4c3aa220d07d166d3f21f158bc9c69e3c044
Author: Ard Biesheuvel 
AuthorDate: Thu, 8 Mar 2018 08:00:18 +
Committer:  Ingo Molnar 
CommitDate: Fri, 9 Mar 2018 08:58:23 +0100

efi: Reorder pr_notice() with add_device_randomness() call

Currently, when we receive a random seed from the EFI stub, we call
add_device_randomness() to incorporate it into the entropy pool, and
issue a pr_notice() saying we are about to do that, e.g.,

  [0.00] efi:  RNG=0x87ff92cf18
  [0.00] random: fast init done
  [0.00] efi: seeding entropy pool

Let's reorder those calls to make the output look less confusing:

  [0.00] efi: seeding entropy pool
  [0.00] efi:  RNG=0x87ff92cf18
  [0.00] random: fast init done

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180308080020.22828-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..92b9e79e5da9 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -542,9 +542,9 @@ int __init efi_config_parse_tables(void *config_tables, int 
count, int sz,
seed = early_memremap(efi.rng_seed,
  sizeof(*seed) + size);
if (seed != NULL) {
+   pr_notice("seeding entropy pool\n");
add_device_randomness(seed->bits, seed->size);
early_memunmap(seed, sizeof(*seed) + size);
-   pr_notice("seeding entropy pool\n");
} else {
pr_err("Could not map UEFI random seed!\n");
}


[tip:efi/core] efi/arm64: Check whether x18 is preserved by runtime services calls

2018-03-09 Thread tip-bot for Ard Biesheuvel
Commit-ID:  7e611e7dbb235938fca1dd359bad5e5f86ceabcb
Gitweb: https://git.kernel.org/tip/7e611e7dbb235938fca1dd359bad5e5f86ceabcb
Author: Ard Biesheuvel 
AuthorDate: Thu, 8 Mar 2018 08:00:13 +
Committer:  Ingo Molnar 
CommitDate: Fri, 9 Mar 2018 08:58:22 +0100

efi/arm64: Check whether x18 is preserved by runtime services calls

Whether or not we will ever decide to start using x18 as a platform
register in Linux is uncertain, but by that time, we will need to
ensure that UEFI runtime services calls don't corrupt it.

So let's start issuing warnings now for this, and increase the
likelihood that these firmware images have all been replaced by that time.

This has been fixed on the EDK2 side in commit:

  6d73863b5464 ("BaseTools/tools_def AARCH64: mark register x18 as reserved")

dated July 13, 2017.

Signed-off-by: Ard Biesheuvel 
Acked-by: Will Deacon 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180308080020.22828-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h   |  4 +++-
 arch/arm64/kernel/Makefile |  3 ++-
 arch/arm64/kernel/efi-rt-wrapper.S | 41 ++
 arch/arm64/kernel/efi.c|  6 ++
 4 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8389050328bb..192d791f1103 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -31,7 +31,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
 ({ \
efi_##f##_t *__f;   \
__f = p->f; \
-   __f(args);  \
+   __efi_rt_asm_wrapper(__f, #f, args);\
 })
 
 #define arch_efi_call_virt_teardown()  \
@@ -40,6 +40,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
efi_virtmap_unload();   \
 })
 
+efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
+
 #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
 
 /* arch specific definitions used by the stub code */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index b87541360f43..6a4bd80c75bd 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -38,7 +38,8 @@ arm64-obj-$(CONFIG_CPU_PM)+= sleep.o suspend.o
 arm64-obj-$(CONFIG_CPU_IDLE)   += cpuidle.o
 arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 arm64-obj-$(CONFIG_KGDB)   += kgdb.o
-arm64-obj-$(CONFIG_EFI)+= efi.o efi-entry.stub.o
+arm64-obj-$(CONFIG_EFI)+= efi.o efi-entry.stub.o   
\
+  efi-rt-wrapper.o
 arm64-obj-$(CONFIG_PCI)+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)   += armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)   += acpi.o
diff --git a/arch/arm64/kernel/efi-rt-wrapper.S 
b/arch/arm64/kernel/efi-rt-wrapper.S
new file mode 100644
index ..05235ebb336d
--- /dev/null
+++ b/arch/arm64/kernel/efi-rt-wrapper.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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 
+
+ENTRY(__efi_rt_asm_wrapper)
+   stp x29, x30, [sp, #-32]!
+   mov x29, sp
+
+   /*
+* Register x18 is designated as the 'platform' register by the AAPCS,
+* which means firmware running at the same exception level as the OS
+* (such as UEFI) should never touch it.
+*/
+   stp x1, x18, [sp, #16]
+
+   /*
+* We are lucky enough that no EFI runtime services take more than
+* 5 arguments, so all are passed in registers rather than via the
+* stack.
+*/
+   mov x8, x0
+   mov x0, x2
+   mov x1, x3
+   mov x2, x4
+   mov x3, x5
+   mov x4, x6
+   blr x8
+
+   ldp x1, x2, [sp, #16]
+   cmp x2, x18
+   ldp x29, x30, [sp], #32
+   b.ne0f
+   ret
+0: b   efi_handle_corrupted_x18// tail call
+ENDPROC(__efi_rt_asm_wrapper)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index a8bf1c892b90..4f9acb5fbe97 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -126,3 +126,9 @@ bool efi_poweroff_required(void)
 {
return efi_enabled(EFI_RUNTIME_SERVICES);
 }
+
+asmlinkage efi_status_t efi_handle_corrupted_x18

[tip:efi/core] efi/arm*: Stop printing addresses of virtual mappings

2018-03-09 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1832e64162ffbbbdf7230401298550f2b624351b
Gitweb: https://git.kernel.org/tip/1832e64162ffbbbdf7230401298550f2b624351b
Author: Ard Biesheuvel 
AuthorDate: Thu, 8 Mar 2018 08:00:11 +
Committer:  Ingo Molnar 
CommitDate: Fri, 9 Mar 2018 08:58:22 +0100

efi/arm*: Stop printing addresses of virtual mappings

With the recent %p -> %px changes, we now get something like this in
the kernel boot log on ARM/arm64 EFI systems:

 Remapping and enabling EFI services.
   EFI remap 0x0087fb83 => (ptrval)
   EFI remap 0x0087fbdb => (ptrval)
   EFI remap 0x0087fffc => (ptrval)

The physical addresses of the UEFI runtime regions will also be
printed when booting with the efi=debug command line option, and the
virtual addresses can be inspected via /sys/kernel/debug/efi_page_tables
(if enabled).

So let's just remove the lines above.

Signed-off-by: Ard Biesheuvel 
Acked-by: Leif Lindholm 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180308080020.22828-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-runtime.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 86a1ad17a32e..13561aeb7396 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -83,10 +83,7 @@ static bool __init efi_virtmap_init(void)
return false;
 
ret = efi_create_mapping(&efi_mm, md);
-   if  (!ret) {
-   pr_info("  EFI remap %pa => %p\n",
-   &phys, (void *)(unsigned long)md->virt_addr);
-   } else {
+   if (ret) {
pr_warn("  EFI remap %pa: failed to create mapping 
(%d)\n",
&phys, ret);
return false;


[tip:efi/core] efi/capsule-loader: Reinstate virtual capsule mapping

2018-01-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f24c4d478013d82bd1b943df566fff3561d52864
Gitweb: https://git.kernel.org/tip/f24c4d478013d82bd1b943df566fff3561d52864
Author: Ard Biesheuvel 
AuthorDate: Tue, 2 Jan 2018 17:21:10 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Jan 2018 13:54:31 +0100

efi/capsule-loader: Reinstate virtual capsule mapping

Commit:

  82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule header")

... refactored the capsule loading code that maps the capsule header,
to avoid having to map it several times.

However, as it turns out, the vmap() call we ended up removing did not
just map the header, but the entire capsule image, and dropping this
virtual mapping breaks capsules that are processed by the firmware
immediately (i.e., without a reboot).

Unfortunately, that change was part of a larger refactor that allowed
a quirk to be implemented for Quark, which has a non-standard memory
layout for capsules, and we have slightly painted ourselves into a
corner by allowing quirk code to mangle the capsule header and memory
layout.

So we need to fix this without breaking Quark. Fortunately, Quark does
not appear to care about the virtual mapping, and so we can simply
do a partial revert of commit:

  2a457fb31df6 ("efi/capsule-loader: Use page addresses rather than struct page 
pointers")

... and create a vmap() mapping of the entire capsule (including header)
based on the reinstated struct page array, unless running on Quark, in
which case we pass the capsule header copy as before.

Reported-by: Ge Song 
Tested-by: Bryan O'Donoghue 
Tested-by: Ge Song 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Dave Young 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Fixes: 82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule 
header")
Link: http://lkml.kernel.org/r/20180102172110.17018-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/platform/efi/quirks.c| 13 +-
 drivers/firmware/efi/capsule-loader.c | 45 ---
 include/linux/efi.h   |  4 +++-
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 8a99a2e..5b513cc 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -592,7 +592,18 @@ static int qrk_capsule_setup_info(struct capsule_info 
*cap_info, void **pkbuff,
/*
 * Update the first page pointer to skip over the CSH header.
 */
-   cap_info->pages[0] += csh->headersize;
+   cap_info->phys[0] += csh->headersize;
+
+   /*
+* cap_info->capsule should point at a virtual mapping of the entire
+* capsule, starting at the capsule header. Our image has the Quark
+* security header prepended, so we cannot rely on the default vmap()
+* mapping created by the generic capsule code.
+* Given that the Quark firmware does not appear to care about the
+* virtual mapping, let's just point cap_info->capsule at our copy
+* of the capsule header.
+*/
+   cap_info->capsule = &cap_info->header;
 
return 1;
 }
diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index ec8ac5c..055e2e8 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,10 +20,6 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
-#ifndef phys_to_page
-#define phys_to_page(x)pfn_to_page((x) >> PAGE_SHIFT)
-#endif
-
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -35,7 +31,7 @@
 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
 {
while (cap_info->index > 0)
-   __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
+   __free_page(cap_info->pages[--cap_info->index]);
 
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
@@ -71,6 +67,14 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)
 
cap_info->pages = temp_page;
 
+   temp_page = krealloc(cap_info->phys,
+pages_needed * sizeof(phys_addr_t *),
+GFP_KERNEL | __GFP_ZERO);
+   if (!temp_page)
+   return -ENOMEM;
+
+   cap_info->phys = temp_page;
+
return 0;
 }
 
@@ -105,9 +109,24 @@ int __weak efi_capsule_setup_info(struct capsule_info 
*cap_info, void *kbuff,
  **/
 static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
 {
+   bool do_vunmap = false;
int ret;
 
-   ret = efi_capsule_update(&cap_info->header, cap_info->pages);
+   /*
+* cap_info->capsule may have been assigned already by a quirk
+* handler, so only overwrite it if it is NULL
+*/
+   if (!cap_info->capsule) {
+   cap_info->capsule = vmap(c

[tip:efi/core] arm64/efi: Ignore EFI_MEMORY_XP attribute if RP and/or WP are set

2018-01-03 Thread tip-bot for Ard Biesheuvel
Commit-ID:  1e9de1d2207d67b97bb0b62e38454b663d6542fa
Gitweb: https://git.kernel.org/tip/1e9de1d2207d67b97bb0b62e38454b663d6542fa
Author: Ard Biesheuvel 
AuthorDate: Tue, 2 Jan 2018 18:10:39 +
Committer:  Ingo Molnar 
CommitDate: Wed, 3 Jan 2018 14:03:48 +0100

arm64/efi: Ignore EFI_MEMORY_XP attribute if RP and/or WP are set

The UEFI memory map is a bit vague about how to interpret the
EFI_MEMORY_XP attribute when it is combined with EFI_MEMORY_RP and/or
EFI_MEMORY_WP, which have retroactively been redefined as cacheability
attributes rather than permission attributes.

So let's ignore EFI_MEMORY_XP if _RP and/or _WP are also set. In this
case, it is likely that they are being used to describe the capability
of the region (i.e., whether it has the controls to reconfigure it as
non-executable) rather than the nature of the contents of the region
(i.e., whether it contains data that we will never attempt to execute)

Reported-by: Stephen Boyd 
Tested-by: Stephen Boyd 
Signed-off-by: Ard Biesheuvel 
Cc: Arvind Yadav 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Tyler Baicar 
Cc: Vasyl Gomonovych 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20180102181042.19074-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/kernel/efi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 82cd075..f85ac58 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -48,7 +48,9 @@ static __init pteval_t 
create_mapping_protection(efi_memory_desc_t *md)
return pgprot_val(PAGE_KERNEL_ROX);
 
/* RW- */
-   if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
+   if (((attr & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP)) ==
+EFI_MEMORY_XP) ||
+   type != EFI_RUNTIME_SERVICES_CODE)
return pgprot_val(PAGE_KERNEL);
 
/* RWX */


[tip:efi/urgent] efi/libstub/arm: Don't randomize runtime regions when CONFIG_HIBERNATION=y

2017-10-25 Thread tip-bot for Ard Biesheuvel
Commit-ID:  38fb6652229c2149e8694d57db442878fdf8a1bd
Gitweb: https://git.kernel.org/tip/38fb6652229c2149e8694d57db442878fdf8a1bd
Author: Ard Biesheuvel 
AuthorDate: Wed, 25 Oct 2017 11:04:48 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 25 Oct 2017 12:10:59 +0200

efi/libstub/arm: Don't randomize runtime regions when CONFIG_HIBERNATION=y

Commit:

  e69176d68d26 ("ef/libstub/arm/arm64: Randomize the base of the UEFI rt 
services region")

implemented randomization of the virtual mapping that the OS chooses for
the UEFI runtime services. This was motivated by the fact that UEFI usually
does not bother to specify any permission restrictions for those regions,
making them prime real estate for exploitation now that the OS is getting
more and more careful not to leave any R+W+X mapped regions lying around.

However, this randomization breaks assumptions in the resume from
hibernation code, which expects all memory regions populated by UEFI to
remain in the same place, including their virtual mapping into the OS
memory space. While this assumption may not be entirely reasonable in the
first place, breaking it deliberately does not make a lot of sense either.
So let's refrain from this randomization pass if CONFIG_HIBERNATION=y.

Signed-off-by: Ard Biesheuvel 
Cc: James Morse 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20171025100448.26056-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 1cb2d1c..a94601d 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -238,7 +238,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
-   if (!nokaslr()) {
+   /* hibernation expects the runtime regions to stay in the same place */
+   if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr()) {
/*
 * Randomize the base of the UEFI runtime services region.
 * Preserve the 2 MB alignment of the region by taking a


[tip:efi/core] efi/random: Increase size of firmware supplied randomness

2017-08-26 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c2ceb5fd4e921506e86208b82fca716a2c3aad59
Gitweb: http://git.kernel.org/tip/c2ceb5fd4e921506e86208b82fca716a2c3aad59
Author: Ard Biesheuvel 
AuthorDate: Fri, 25 Aug 2017 16:50:16 +0100
Committer:  Ingo Molnar 
CommitDate: Sat, 26 Aug 2017 09:20:33 +0200

efi/random: Increase size of firmware supplied randomness

The crng code requires at least 64 bytes (2 * CHACHA20_BLOCK_SIZE)
to complete the fast boot-time init, so provide that many bytes
when invoking UEFI protocols to seed the entropy pool. Also, add
a notice so we can tell from the boot log when the seeding actually
took place.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170825155019.6740-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c|  3 ++-
 drivers/firmware/efi/libstub/random.c | 10 --
 include/linux/efi.h   |  2 ++
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a32e146..c8a27a2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -541,6 +541,7 @@ int __init efi_config_parse_tables(void *config_tables, int 
count, int sz,
if (seed != NULL) {
add_device_randomness(seed->bits, seed->size);
early_memunmap(seed, sizeof(*seed) + size);
+   pr_notice("seeding entropy pool\n");
} else {
pr_err("Could not map UEFI random seed!\n");
}
@@ -900,7 +901,7 @@ static int update_efi_random_seed(struct notifier_block *nb,
 
seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
if (seed != NULL) {
-   size = min(seed->size, 32U);
+   size = min(seed->size, EFI_RANDOM_SEED_SIZE);
memunmap(seed);
} else {
pr_err("Could not map UEFI random seed!\n");
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 7e72954..e0e603a 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -145,8 +145,6 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
return status;
 }
 
-#define RANDOM_SEED_SIZE   32
-
 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
 {
efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
@@ -162,25 +160,25 @@ efi_status_t efi_random_get_seed(efi_system_table_t 
*sys_table_arg)
return status;
 
status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
-   sizeof(*seed) + RANDOM_SEED_SIZE,
+   sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
(void **)&seed);
if (status != EFI_SUCCESS)
return status;
 
-   status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, &rng_algo_raw, EFI_RANDOM_SEED_SIZE,
  seed->bits);
if (status == EFI_UNSUPPORTED)
/*
 * Use whatever algorithm we have available if the raw algorithm
 * is not implemented.
 */
-   status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, NULL, EFI_RANDOM_SEED_SIZE,
  seed->bits);
 
if (status != EFI_SUCCESS)
goto err_freepool;
 
-   seed->size = RANDOM_SEED_SIZE;
+   seed->size = EFI_RANDOM_SEED_SIZE;
status = efi_call_early(install_configuration_table, &rng_table_guid,
seed);
if (status != EFI_SUCCESS)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c241acc..33d41df 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1571,6 +1571,8 @@ efi_status_t efi_exit_boot_services(efi_system_table_t 
*sys_table,
void *priv,
efi_exit_boot_map_processing priv_func);
 
+#define EFI_RANDOM_SEED_SIZE   64U
+
 struct linux_efi_random_seed {
u32 size;
u8  bits[];


[tip:efi/core] arm/efi: Split zImage code and data into separate PE/COFF sections

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e4bae4d0b5f368dda5bbf1374dca74c1b542d841
Gitweb: http://git.kernel.org/tip/e4bae4d0b5f368dda5bbf1374dca74c1b542d841
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:44 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:51 +0200

arm/efi: Split zImage code and data into separate PE/COFF sections

To prevent unintended modifications to the kernel text (malicious or
otherwise) while running the EFI stub, describe the kernel image as
two separate sections: a .text section with read-execute permissions,
covering .text, .rodata, .piggytext and the GOT sections (which the
stub does not care about anyway), and a .data section with read-write
permissions, covering .data and .bss.

This relies on the firmware to actually take the section permission
flags into account, but this is something that is currently being
implemented in EDK2, which means we will likely start seeing it in
the wild between one and two years from now.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Russell King 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S  | 32 +++-
 arch/arm/boot/compressed/vmlinux.lds.S | 30 +++---
 2 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 542e1ad..c94a88a 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -54,20 +54,22 @@ coff_header:
IMAGE_FILE_EXECUTABLE_IMAGE | \
IMAGE_FILE_LINE_NUMS_STRIPPED   @ Characteristics
 
+#define __pecoff_code_size (__pecoff_data_start - __efi_start)
+
 optional_header:
.short  PE_OPT_MAGIC_PE32   @ PE32 format
.byte   0x02@ MajorLinkerVersion
.byte   0x14@ MinorLinkerVersion
-   .long   _end - __efi_start  @ SizeOfCode
-   .long   0   @ SizeOfInitializedData
+   .long   __pecoff_code_size  @ SizeOfCode
+   .long   __pecoff_data_size  @ SizeOfInitializedData
.long   0   @ 
SizeOfUninitializedData
.long   efi_stub_entry - start  @ AddressOfEntryPoint
.long   start_offset@ BaseOfCode
-   .long   0   @ BaseOfData
+   .long   __pecoff_data_start - start @ BaseOfData
 
 extra_header_fields:
.long   0   @ ImageBase
-   .long   SZ_512  @ SectionAlignment
+   .long   SZ_4K   @ SectionAlignment
.long   SZ_512  @ FileAlignment
.short  0   @ MajorOsVersion
.short  0   @ MinorOsVersion
@@ -77,7 +79,7 @@ extra_header_fields:
.short  0   @ MinorSubsystemVersion
.long   0   @ Win32VersionValue
 
-   .long   _end - start@ SizeOfImage
+   .long   __pecoff_end - start@ SizeOfImage
.long   start_offset@ SizeOfHeaders
.long   0   @ CheckSum
.short  IMAGE_SUBSYSTEM_EFI_APPLICATION @ Subsystem
@@ -98,9 +100,9 @@ extra_header_fields:
 
 section_table:
.ascii  ".text\0\0\0"
-   .long   _end - __efi_start  @ VirtualSize
+   .long   __pecoff_code_size  @ VirtualSize
.long   __efi_start @ VirtualAddress
-   .long   _edata - __efi_start@ SizeOfRawData
+   .long   __pecoff_code_size  @ SizeOfRawData
.long   __efi_start @ PointerToRawData
.long   0   @ PointerToRelocations
.long   0   @ PointerToLineNumbers
@@ -108,12 +110,24 @@ section_table:
.short  0   @ NumberOfLineNumbers
.long   IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \
-   IMAGE_SCN_MEM_WRITE | \
IMAGE_SCN_MEM_EXECUTE   @ Characteristics
 
+   .ascii  ".data\0\0\0"
+   .long   __pecoff_data_size  @ VirtualSize
+   .long   __pecoff_data_start - start @ VirtualAdd

[tip:efi/core] arm/efi: Replace open coded constants with symbolic ones

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  609eaf0748a5b9dccf3810a2b822a0559f33c0b2
Gitweb: http://git.kernel.org/tip/609eaf0748a5b9dccf3810a2b822a0559f33c0b2
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:43 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Replace open coded constants with symbolic ones

Replace the various open coded constants in the EFI PE/COFF header with
definitions from pe.h, or expressions based on local symbols.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 128 ++
 1 file changed, 67 insertions(+), 61 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 309d619..542e1ad 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Linaro Ltd
+ * Copyright (C) 2013-2017 Linaro Ltd
  * Authors: Roy Franz 
  *  Ard Biesheuvel 
  *
@@ -8,6 +8,9 @@
  * published by the Free Software Foundation.
  */
 
+#include 
+#include 
+
.macro  __nop
 #ifdef CONFIG_EFI_STUB
@ This is almost but not quite a NOP, since it does clobber the
@@ -15,7 +18,7 @@
@ 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
+   .inst   MZ_MAGIC | (0x1310 << 16)   @ tstne r0, #0x4d000
 #else
  AR_CLASS( mov r0, r0  )
   M_CLASS( nop.w   )
@@ -34,78 +37,81 @@
@ 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.
+   .long   pe_header - start   @ Offset to the PE 
header.
 
 pe_header:
-   .ascii  "PE\0\0"
+   .long   PE_MAGIC
 
 coff_header:
-   .short  0x01c2  @ ARM or Thumb
-   .short  1   @ nr_sections
-   .long   0   @ TimeDateStamp
-   .long   0   @ PointerToSymbolTable
-   .long   0   @ 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
+   .short  IMAGE_FILE_MACHINE_THUMB@ Machine
+   .short  section_count   @ NumberOfSections
+   .long   0   @ TimeDateStamp
+   .long   0   @ PointerToSymbolTable
+   .long   0   @ NumberOfSymbols
+   .short  section_table - optional_header @ SizeOfOptionalHeader
+   .short  IMAGE_FILE_32BIT_MACHINE | \
+   IMAGE_FILE_DEBUG_STRIPPED | \
+   IMAGE_FILE_EXECUTABLE_IMAGE | \
+   IMAGE_FILE_LINE_NUMS_STRIPPED   @ Characteristics
 
 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
+   .short  PE_OPT_MAGIC_PE32   @ 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
+  

[tip:efi/core] arm/efi: Remove forbidden values from the PE/COFF header

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4415f9f4a6e5c6a4228098fc8289f21f3dda515c
Gitweb: http://git.kernel.org/tip/4415f9f4a6e5c6a4228098fc8289f21f3dda515c
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:41 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Remove forbidden values from the PE/COFF header

Bring the PE/COFF header in line with the PE/COFF spec, by setting
NumberOfSymbols to 0, and removing the section alignment flags.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index a17ca8d..4169b90 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -44,7 +44,7 @@ coff_header:
.short  2   @ nr_sections
.long   0   @ TimeDateStamp
.long   0   @ PointerToSymbolTable
-   .long   1   @ NumberOfSymbols
+   .long   0   @ NumberOfSymbols
.short  section_table - optional_header
@ SizeOfOptionalHeader
.short  0x306   @ Characteristics.
@@ -110,7 +110,7 @@ section_table:
.long   0   @ PointerToLineNumbers
.short  0   @ NumberOfRelocations
.short  0   @ NumberOfLineNumbers
-   .long   0x42100040  @ Characteristics
+   .long   0x4240  @ Characteristics
 
.ascii  ".text\0\0\0"
.long   _end - __efi_start  @ VirtualSize
@@ -121,7 +121,7 @@ section_table:
.long   0   @ PointerToLineNumbers
.short  0   @ NumberOfRelocations
.short  0   @ NumberOfLineNumbers
-   .long   0xe0500020  @ Characteristics
+   .long   0xe020  @ Characteristics
 
.align  9
 __efi_start:


[tip:efi/core] drivers/fbdev/efifb: Allow BAR to be moved instead of claiming it

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  dcf8f5ce31656534efada252f6a563c09b295983
Gitweb: http://git.kernel.org/tip/dcf8f5ce31656534efada252f6a563c09b295983
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:40 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

drivers/fbdev/efifb: Allow BAR to be moved instead of claiming it

On UEFI systems, the firmware may expose a Graphics Output Protocol (GOP)
instance to which the efifb driver attempts to attach in order to provide
a minimal, unaccelerated framebuffer. The GOP protocol itself is not very
sophisticated, and only describes the offset and size of the framebuffer
in memory, and the pixel format.

If the GOP framebuffer is provided by a PCI device, it will have been
configured and enabled by the UEFI firmware, and the GOP protocol will
simply point into a live BAR region. However, the GOP protocol itself does
not describe this relation, and so we have to take care not to reconfigure
the BAR without taking efifb's dependency on it into account.

Commit:

  55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that covers the 
framebuffer")

attempted to do so by claiming the BAR resource early on, which prevents the
PCI resource allocation routines from changing it.  However, it turns out
that this only works if the PCI device is not behind any bridges, since
the bridge resources need to be claimed first.

So instead, allow the BAR to be moved, but make the efifb driver deal
with that gracefully. So record the resource that covers the BAR early
on, and if it turns out to have moved by the time we probe the efifb
driver, update the framebuffer address accordingly.

While this is less likely to occur on x86, given that the firmware's
PCI resource allocation is more likely to be preserved, this is a
worthwhile sanity check to have in place, and so let's remove the
preprocessor conditional that makes it !X86 only.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Peter Jones 
Acked-by: Bartlomiej Zolnierkiewicz 
Acked-by: Bjorn Helgaas 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-8-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 31 ++-
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 1e784ad..3a01064 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -149,6 +149,10 @@ ATTRIBUTE_GROUPS(efifb);
 
 static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
 
+static struct pci_dev *efifb_pci_dev;  /* dev with BAR covering the efifb */
+static struct resource *bar_resource;
+static u64 bar_offset;
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -203,6 +207,13 @@ static int efifb_probe(struct platform_device *dev)
efifb_fix.smem_start |= ext_lfb_base;
}
 
+   if (bar_resource &&
+   bar_resource->start + bar_offset != efifb_fix.smem_start) {
+   dev_info(&efifb_pci_dev->dev,
+"BAR has moved, updating efifb address\n");
+   efifb_fix.smem_start = bar_resource->start + bar_offset;
+   }
+
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
efifb_defined.xres = screen_info.lfb_width;
efifb_defined.yres = screen_info.lfb_height;
@@ -370,15 +381,13 @@ static struct platform_driver efifb_driver = {
 
 builtin_platform_driver(efifb_driver);
 
-#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
-
-static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+#if defined(CONFIG_PCI)
 
-static void claim_efifb_bar(struct pci_dev *dev, int idx)
+static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
 {
u16 word;
 
-   pci_bar_found = true;
+   efifb_pci_dev = dev;
 
pci_read_config_word(dev, PCI_COMMAND, &word);
if (!(word & PCI_COMMAND_MEMORY)) {
@@ -389,12 +398,8 @@ static void claim_efifb_bar(struct pci_dev *dev, int idx)
return;
}
 
-   if (pci_claim_resource(dev, idx)) {
-   pci_dev_disabled = true;
-   dev_err(&dev->dev,
-   "BAR %d: failed to claim resource for efifb!\n", idx);
-   return;
-   }
+   bar_resource = &dev->resource[idx];
+   bar_offset = offset;
 
dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
 }
@@ -405,7 +410,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
u64 size = screen_info.lfb_size;
int i;
 
-   if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   if (efifb_pci_dev || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return;
 
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
@@ -421,7 +426,7 @@ static void efif

[tip:efi/core] arm/efi: Remove pointless dummy .reloc section

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  574cea724cd81f4063491ed1c0534d81a094a913
Gitweb: http://git.kernel.org/tip/574cea724cd81f4063491ed1c0534d81a094a913
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:42 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:50 +0200

arm/efi: Remove pointless dummy .reloc section

The kernel's EFI PE/COFF header contains a dummy .reloc section, and
an explanatory comment that claims that this is required for the EFI
application loader to accept the Image as a relocatable image (i.e.,
one that can be loaded at any offset and fixed up in place)

This was inherited from the x86 implementation, which has elaborate host
tooling to mangle the PE/COFF header post-link time, and which populates
the .reloc section with a single dummy base relocation. On ARM, no such
tooling exists, and the .reloc section remains empty, and is never even
exposed via the BaseRelocationTable directory entry, which is where the
PE/COFF loader looks for it.

The PE/COFF spec is unclear about relocatable images that do not require
any fixups, but the EDK2 implementation, which is the de facto reference
for PE/COFF in the UEFI space, clearly does not care, and explicitly
mentions (in a comment) that relocatable images with no base relocations
are perfectly fine, as long as they don't have the RELOCS_STRIPPED
attribute set (which is not the case for our PE/COFF image)

So simply remove the .reloc section altogether.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/boot/compressed/efi-header.S | 18 +-
 1 file changed, 1 insertion(+), 17 deletions(-)

diff --git a/arch/arm/boot/compressed/efi-header.S 
b/arch/arm/boot/compressed/efi-header.S
index 4169b90..309d619 100644
--- a/arch/arm/boot/compressed/efi-header.S
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -41,7 +41,7 @@ pe_header:
 
 coff_header:
.short  0x01c2  @ ARM or Thumb
-   .short  2   @ nr_sections
+   .short  1   @ nr_sections
.long   0   @ TimeDateStamp
.long   0   @ PointerToSymbolTable
.long   0   @ NumberOfSymbols
@@ -96,22 +96,6 @@ extra_header_fields:
.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   0x4240  @ Characteristics
-
.ascii  ".text\0\0\0"
.long   _end - __efi_start  @ VirtualSize
.long   __efi_start @ VirtualAddress


[tip:efi/core] efi/libstub/arm64: Set -fpie when building the EFI stub

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  91ee5b21ee026c49e4e7483de69b55b8b47042be
Gitweb: http://git.kernel.org/tip/91ee5b21ee026c49e4e7483de69b55b8b47042be
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:37 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Set -fpie when building the EFI stub

Clang may emit absolute symbol references when building in non-PIC mode,
even when using the default 'small' code model, which is already mostly
position independent to begin with, due to its use of adrp/add pairs
that have a relative range of +/- 4 GB. The remedy is to pass the -fpie
flag, which can be done safely now that the code has been updated to avoid
GOT indirections (which may be emitted due to the compiler assuming that
the PIC/PIE code may end up in a shared library that is subject to ELF
symbol preemption)

Passing -fpie when building code that needs to execute at an a priori
unknown offset is arguably an improvement in any case, and given that
the recent visibility changes allow the PIC build to pass with GCC as
well, let's add -fpie for all arm64 builds rather than only for Clang.

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-5-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 37e24f5..cf81e6c 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -10,7 +10,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ -O2 \
   -fPIC -fno-strict-aliasing -mno-red-zone \
   -mno-mmx -mno-sse
 
-cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
+cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
 cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
   -fno-builtin -fpic -mno-single-pic-base
 


[tip:efi/core] efi/libstub/arm64: Use hidden attribute for struct screen_info reference

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  760b61d76da6d6a99eb245ab61abf71ca5415cea
Gitweb: http://git.kernel.org/tip/760b61d76da6d6a99eb245ab61abf71ca5415cea
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:35 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Use hidden attribute for struct screen_info reference

To prevent the compiler from emitting absolute references to screen_info
when building position independent code, redeclare the symbol with hidden
visibility.

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8f3043a..464ac85 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -81,6 +81,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned 
long dram_base,
 #define alloc_screen_info(x...)&screen_info
 #define free_screen_info(x...)
 
+/* redeclare as 'hidden' so the compiler will generate relative references */
+extern struct screen_info screen_info 
__attribute__((__visibility__("hidden")));
+
 static inline void efifb_setup_from_dmi(struct screen_info *si, const char 
*opt)
 {
 }


[tip:efi/core] efi/libstub/arm64: Force 'hidden' visibility for section markers

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0426a4e68f18d75515414361de9e3e1445d2644e
Gitweb: http://git.kernel.org/tip/0426a4e68f18d75515414361de9e3e1445d2644e
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:36 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/libstub/arm64: Force 'hidden' visibility for section markers

To prevent the compiler from emitting absolute references to the section
markers when running in PIC mode, override the visibility to 'hidden' for
all contents of asm/sections.h

Tested-by: Matthias Kaehlcke 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm64-stub.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index b4c2589..f7a6970 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -9,9 +9,17 @@
  * published by the Free Software Foundation.
  *
  */
+
+/*
+ * To prevent the compiler from emitting GOT-indirected (and thus absolute)
+ * references to the section markers, override their visibility as 'hidden'
+ */
+#pragma GCC visibility push(hidden)
+#include 
+#pragma GCC visibility pop
+
 #include 
 #include 
-#include 
 #include 
 
 #include "efistub.h"


[tip:efi/core] efi/arm/arm64: Add missing assignment of efi.config_table

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9a9de5c044be14c3337ef45174ac8baa568a0f93
Gitweb: http://git.kernel.org/tip/9a9de5c044be14c3337ef45174ac8baa568a0f93
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:38 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/arm/arm64: Add missing assignment of efi.config_table

The ARM EFI init code never assigns the config_table member of the
efi struct, which means the sysfs device node is missing, and other
in-kernel users will not work correctly. So add the missing assignment.

Note that, for now, the runtime and fw_vendor members are still
omitted. This is deliberate: exposing physical addresses via sysfs nodes
encourages behavior that we would like to avoid on ARM (given how it is
more finicky about using correct memory attributes when mapping memory
in userland that may be mapped by the kernel already as well).

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 0aa4ce7..80d1a88 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -145,6 +145,9 @@ static int __init uefi_init(void)
 sizeof(efi_config_table_t),
 arch_tables);
 
+   if (!retval)
+   efi.config_table = (unsigned long)efi.systab->tables;
+
early_memunmap(config_tables, table_size);
 out:
early_memunmap(efi.systab,  sizeof(efi_system_table_t));


[tip:efi/core] efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP

2017-08-21 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f56ab9a5b73ca2aee777ccdf2d355ae2dd31db5a
Gitweb: http://git.kernel.org/tip/f56ab9a5b73ca2aee777ccdf2d355ae2dd31db5a
Author: Ard Biesheuvel 
AuthorDate: Fri, 18 Aug 2017 20:49:34 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 21 Aug 2017 09:43:49 +0200

efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP

On ARM, regions of memory that are described by UEFI as having special
significance to the firmware itself are omitted from the linear mapping.
This is necessary since we cannot guarantee that alternate mappings of
the same physical region will use attributes that are compatible with
the ones we use for the linear mapping, and aliases with mismatched
attributes are prohibited by the architecture.

The above does not apply to ACPI reclaim regions: such regions have no
special significance to the firmware, and it is up to the OS to decide
whether or not to preserve them after it has consumed their contents,
and for how long, after which time the OS can use the memory in any way
it likes. In the Linux case, such regions are preserved indefinitely,
and are simply treated the same way as other 'reserved' memory types.

Punching holes into the linear mapping causes page table fragmentation,
which increases TLB pressure, and so we should avoid doing so if we can.
So add a special case for regions of type EFI_ACPI_RECLAIM_MEMORY, and
memblock_reserve() them instead of marking them MEMBLOCK_NOMAP.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170818194947.19347-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 1027d7b4..0aa4ce7 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -159,6 +159,7 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
switch (md->type) {
case EFI_LOADER_CODE:
case EFI_LOADER_DATA:
+   case EFI_ACPI_RECLAIM_MEMORY:
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
@@ -211,6 +212,10 @@ static __init void reserve_regions(void)
 
if (!is_usable_memory(md))
memblock_mark_nomap(paddr, size);
+
+   /* keep ACPI reclaim memory intact for kexec etc. */
+   if (md->type == EFI_ACPI_RECLAIM_MEMORY)
+   memblock_reserve(paddr, size);
}
}
 }


[tip:efi/core] efi/arm: Enable DMI/SMBIOS

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  bb817bef3b1989a9cdb40362cfb8d2aa224ac1bc
Gitweb: http://git.kernel.org/tip/bb817bef3b1989a9cdb40362cfb8d2aa224ac1bc
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:07 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:44 +0200

efi/arm: Enable DMI/SMBIOS

Wire up the existing arm64 support for SMBIOS tables (aka DMI) for ARM as
well, by moving the arm64 init code to drivers/firmware/efi/arm-runtime.c
(which is shared between ARM and arm64), and adding a asm/dmi.h header to
ARM that defines the mapping routines for the firmware tables.

This allows userspace to access these tables to discover system information
exposed by the firmware. It also sets the hardware name used in crash
dumps, e.g.:

  Unable to handle kernel NULL pointer dereference at virtual address 
  pgd = ed3c
  [] *pgd=bf1f3835
  Internal error: Oops: 817 [#1] SMP THUMB2
  Modules linked in:
  CPU: 0 PID: 759 Comm: bash Not tainted 4.10.0-09601-g0e8f38792120-dirty #112
  Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
  ^^^

NOTE: This does *NOT* enable or encourage the use of DMI quirks, i.e., the
  the practice of identifying the platform via DMI to decide whether
  certain workarounds for buggy hardware and/or firmware need to be
  enabled. This would require the DMI subsystem to be enabled much
  earlier than we do on ARM, which is non-trivial.

Signed-off-by: Ard Biesheuvel 
Acked-by: Russell King 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-14-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/Kconfig   | 17 +
 arch/arm/include/asm/dmi.h | 19 +++
 arch/arm64/kernel/efi.c| 15 ---
 drivers/firmware/efi/arm-runtime.c | 16 
 4 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4c1a35f..dabcaeb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2061,6 +2061,23 @@ config EFI
  is only useful for kernels that may run on systems that have
  UEFI firmware.
 
+config DMI
+   bool "Enable support for SMBIOS (DMI) tables"
+   depends on EFI
+   default y
+   help
+ This enables SMBIOS/DMI feature for systems.
+
+ This option is only useful on systems that have UEFI firmware.
+ However, even with this option, the resultant kernel should
+ continue to boot on existing non-UEFI platforms.
+
+ NOTE: This does *NOT* enable or encourage the use of DMI quirks,
+ i.e., the the practice of identifying the platform via DMI to
+ decide whether certain workarounds for buggy hardware and/or
+ firmware need to be enabled. This would require the DMI subsystem
+ to be enabled much earlier than we do on ARM, which is non-trivial.
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/include/asm/dmi.h b/arch/arm/include/asm/dmi.h
new file mode 100644
index 000..df2d2ff
--- /dev/null
+++ b/arch/arm/include/asm/dmi.h
@@ -0,0 +1,19 @@
+/*
+ * 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_DMI_H
+#define __ASM_DMI_H
+
+#include 
+#include 
+
+#define dmi_early_remap(x, l)  memremap(x, l, MEMREMAP_WB)
+#define dmi_early_unmap(x, l)  memunmap(x)
+#define dmi_remap(x, l)memremap(x, l, MEMREMAP_WB)
+#define dmi_unmap(x)   memunmap(x)
+#define dmi_alloc(l)   kzalloc(l, GFP_KERNEL)
+
+#endif
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 5d17f37..82cd075 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,7 +11,6 @@
  *
  */
 
-#include 
 #include 
 #include 
 
@@ -117,20 +116,6 @@ int __init efi_set_mapping_permissions(struct mm_struct 
*mm,
   set_permissions, md);
 }
 
-static int __init arm64_dmi_init(void)
-{
-   /*
-* On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
-* be called early because dmi_id_init(), which is an arch_initcall
-* itself, depends on dmi_scan_machine() having been called already.
-*/
-   dmi_scan_machine();
-   if (dmi_available)
-   dmi_set_dump_stack_arch_desc();
-   return 0;
-}
-core_initcall(arm64_dmi_init);
-
 /*
  * UpdateCapsule() depends on the system being shutdown via
  * ResetSystem().
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 974c5a3..1cc41c3 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -166,3 +167,

[tip:efi/core] efi/capsule-loader: Use page addresses rather than struct page pointers

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  2a457fb31df62c6b482f78e4f74aaed99271f44d
Gitweb: http://git.kernel.org/tip/2a457fb31df62c6b482f78e4f74aaed99271f44d
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:03 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:41 +0200

efi/capsule-loader: Use page addresses rather than struct page pointers

To give some leeway to code that handles non-standard capsule headers,
let's keep an array of page addresses rather than struct page pointers.

This gives special implementations of efi_capsule_setup_info() the
opportunity to mangle the payload a bit before it is presented to the
firmware, without putting any knowledge of the nature of such quirks
into the generic code.

Tested-by: Bryan O'Donoghue 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-10-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 12 
 drivers/firmware/efi/capsule.c|  7 ---
 include/linux/efi.h   |  4 ++--
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index cbc35269..ec8ac5c 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,6 +20,10 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
+#ifndef phys_to_page
+#define phys_to_page(x)pfn_to_page((x) >> PAGE_SHIFT)
+#endif
+
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -31,7 +35,7 @@
 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
 {
while (cap_info->index > 0)
-   __free_page(cap_info->pages[--cap_info->index]);
+   __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
 
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
@@ -161,12 +165,12 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
goto failed;
}
 
-   cap_info->pages[cap_info->index++] = page;
+   cap_info->pages[cap_info->index++] = page_to_phys(page);
cap_info->page_bytes_remain = PAGE_SIZE;
+   } else {
+   page = phys_to_page(cap_info->pages[cap_info->index - 1]);
}
 
-   page = cap_info->pages[cap_info->index - 1];
-
kbuff = kmap(page);
kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
 
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index e603ccf..901b930 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
  *
  * Return 0 on success, a converted EFI status code on failure.
  */
-int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
+int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
 {
u32 imagesize = capsule->imagesize;
efi_guid_t guid = capsule->guid;
@@ -249,10 +249,11 @@ int efi_capsule_update(efi_capsule_header_t *capsule, 
struct page **pages)
sglist = kmap(sg_pages[i]);
 
for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
-   u64 sz = min_t(u64, imagesize, PAGE_SIZE);
+   u64 sz = min_t(u64, imagesize,
+  PAGE_SIZE - (u64)*pages % PAGE_SIZE);
 
sglist[j].length = sz;
-   sglist[j].data = page_to_phys(*pages++);
+   sglist[j].data = *pages++;
 
imagesize -= sz;
count--;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a7379a2..8269bcb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -143,7 +143,7 @@ struct capsule_info {
longindex;
size_t  count;
size_t  total_size;
-   struct page **pages;
+   phys_addr_t *pages;
size_t  page_bytes_remain;
 };
 
@@ -1415,7 +1415,7 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 
flags,
 size_t size, int *reset);
 
 extern int efi_capsule_update(efi_capsule_header_t *capsule,
- struct page **pages);
+ phys_addr_t *pages);
 
 #ifdef CONFIG_EFI_RUNTIME_MAP
 int efi_runtime_map_init(struct kobject *);


[tip:efi/core] efi/capsule-loader: Redirect calls to efi_capsule_setup_info() via weak alias

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  3fabd628d5ea24b02ddb1230ffca1df0f779f84e
Gitweb: http://git.kernel.org/tip/3fabd628d5ea24b02ddb1230ffca1df0f779f84e
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:02 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:41 +0200

efi/capsule-loader: Redirect calls to efi_capsule_setup_info() via weak alias

To allow platform specific code to hook into the capsule loading
routines, indirect calls to efi_capsule_setup_info() via a weak alias
of __efi_capsule_setup_info(), allowing platforms to redefine the former
but still use the latter.

Tested-by: Bryan O'Donoghue 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-9-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 56 +--
 include/linux/efi.h   | 12 
 2 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index 2357bcd..cbc35269 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,16 +20,6 @@
 
 #define NO_FURTHER_WRITE_ACTION -1
 
-struct capsule_info {
-   efi_capsule_header_theader;
-   int reset_type;
-   longindex;
-   size_t  count;
-   size_t  total_size;
-   struct page **pages;
-   size_t  page_bytes_remain;
-};
-
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -46,28 +36,13 @@ static void efi_free_all_buff_pages(struct capsule_info 
*cap_info)
cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
 
-/**
- * efi_capsule_setup_info - obtain the efi capsule header in the binary and
- * setup capsule_info structure
- * @cap_info: pointer to current instance of capsule_info structure
- * @kbuff: a mapped first page buffer pointer
- * @hdr_bytes: the total received number of bytes for efi header
- **/
-static int efi_capsule_setup_info(struct capsule_info *cap_info,
- void *kbuff, size_t hdr_bytes)
+int __efi_capsule_setup_info(struct capsule_info *cap_info)
 {
size_t pages_needed;
int ret;
void *temp_page;
 
-   /* Only process data block that is larger than efi header size */
-   if (hdr_bytes < sizeof(efi_capsule_header_t))
-   return 0;
-
-   /* Reset back to the correct offset of header */
-   kbuff -= cap_info->count;
-   memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));
-   pages_needed = ALIGN(cap_info->header.imagesize, PAGE_SIZE) / PAGE_SIZE;
+   pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE;
 
if (pages_needed == 0) {
pr_err("invalid capsule size");
@@ -84,7 +59,6 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return ret;
}
 
-   cap_info->total_size = cap_info->header.imagesize;
temp_page = krealloc(cap_info->pages,
 pages_needed * sizeof(void *),
 GFP_KERNEL | __GFP_ZERO);
@@ -97,6 +71,30 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
 }
 
 /**
+ * efi_capsule_setup_info - obtain the efi capsule header in the binary and
+ * setup capsule_info structure
+ * @cap_info: pointer to current instance of capsule_info structure
+ * @kbuff: a mapped first page buffer pointer
+ * @hdr_bytes: the total received number of bytes for efi header
+ *
+ * Platforms with non-standard capsule update mechanisms can override
+ * this __weak function so they can perform any required capsule
+ * image munging. See quark_quirk_function() for an example.
+ **/
+int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,
+ size_t hdr_bytes)
+{
+   /* Only process data block that is larger than efi header size */
+   if (hdr_bytes < sizeof(efi_capsule_header_t))
+   return 0;
+
+   memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));
+   cap_info->total_size = cap_info->header.imagesize;
+
+   return __efi_capsule_setup_info(cap_info);
+}
+
+/**
  * efi_capsule_submit_update - invoke the efi_capsule_update API once binary
  *upload done
  * @cap_info: pointer to current instance of capsule_info structure
@@ -182,7 +180,7 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
 
/* Setup capsule binary info structure */
if (cap_info->header.headersize == 0) {
-   ret = efi_capsule_setup_info(cap_info, kbuff,
+   r

[tip:efi/core] efi/capsule-loader: Use a cached copy of the capsule header

2017-06-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  82c3768b8d68c40ecde92338899c838b7c674ffb
Gitweb: http://git.kernel.org/tip/82c3768b8d68c40ecde92338899c838b7c674ffb
Author: Ard Biesheuvel 
AuthorDate: Fri, 2 Jun 2017 13:52:00 +
Committer:  Ingo Molnar 
CommitDate: Mon, 5 Jun 2017 17:50:40 +0200

efi/capsule-loader: Use a cached copy of the capsule header

Instead of kmapping the capsule data twice, copy the capsule header
into the capsule info struct we keep locally. This is an improvement
by itself, but will also enable handling of non-standard header formats
more easily.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-7-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/capsule-loader.c | 41 +++
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/efi/capsule-loader.c 
b/drivers/firmware/efi/capsule-loader.c
index 37d3f6e..5b012a4 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -21,13 +21,13 @@
 #define NO_FURTHER_WRITE_ACTION -1
 
 struct capsule_info {
-   boolheader_obtained;
-   int reset_type;
-   longindex;
-   size_t  count;
-   size_t  total_size;
-   struct page **pages;
-   size_t  page_bytes_remain;
+   efi_capsule_header_theader;
+   int reset_type;
+   longindex;
+   size_t  count;
+   size_t  total_size;
+   struct page **pages;
+   size_t  page_bytes_remain;
 };
 
 /**
@@ -56,7 +56,6 @@ static void efi_free_all_buff_pages(struct capsule_info 
*cap_info)
 static int efi_capsule_setup_info(struct capsule_info *cap_info,
  void *kbuff, size_t hdr_bytes)
 {
-   efi_capsule_header_t *cap_hdr;
size_t pages_needed;
int ret;
void *temp_page;
@@ -66,8 +65,9 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return 0;
 
/* Reset back to the correct offset of header */
-   cap_hdr = kbuff - cap_info->count;
-   pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
+   kbuff -= cap_info->count;
+   memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));
+   pages_needed = ALIGN(cap_info->header.imagesize, PAGE_SIZE) / PAGE_SIZE;
 
if (pages_needed == 0) {
pr_err("invalid capsule size");
@@ -75,15 +75,16 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
}
 
/* Check if the capsule binary supported */
-   ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
-   cap_hdr->imagesize,
+   ret = efi_capsule_supported(cap_info->header.guid,
+   cap_info->header.flags,
+   cap_info->header.imagesize,
&cap_info->reset_type);
if (ret) {
pr_err("capsule not supported\n");
return ret;
}
 
-   cap_info->total_size = cap_hdr->imagesize;
+   cap_info->total_size = cap_info->header.imagesize;
temp_page = krealloc(cap_info->pages,
 pages_needed * sizeof(void *),
 GFP_KERNEL | __GFP_ZERO);
@@ -91,7 +92,6 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
return -ENOMEM;
 
cap_info->pages = temp_page;
-   cap_info->header_obtained = true;
 
return 0;
 }
@@ -104,15 +104,8 @@ static int efi_capsule_setup_info(struct capsule_info 
*cap_info,
 static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
 {
int ret;
-   void *cap_hdr_temp;
 
-   cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
-   VM_MAP, PAGE_KERNEL);
-   if (!cap_hdr_temp)
-   return -ENOMEM;
-
-   ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
-   vunmap(cap_hdr_temp);
+   ret = efi_capsule_update(&cap_info->header, cap_info->pages);
if (ret) {
pr_err("capsule update failed\n");
return ret;
@@ -192,7 +185,7 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
cap_info->page_bytes_remain -= write_byte;
 
/* Setup capsule binary info structure */
-   if (!cap_info->header_obtained) {
+   if (cap_info->header.headersize == 0) {
ret = efi_capsule_setup_info(cap_info, kbuff,
 cap_info->count + write_byte);
if (ret)
@@ -203,7 +196,7 @@ static ssize_t efi_capsule_write(struct file *file, const 
char __user *buff,
 

[tip:efi/core] efi/libstub/arm: Don't use TASK_SIZE when randomizing the RT space

2017-04-18 Thread tip-bot for Ard Biesheuvel
Commit-ID:  197decefdb79d6f1350ba0316ce26ba737372d0c
Gitweb: http://git.kernel.org/tip/197decefdb79d6f1350ba0316ce26ba737372d0c
Author: Ard Biesheuvel 
AuthorDate: Mon, 17 Apr 2017 10:32:01 +0100
Committer:  Ingo Molnar 
CommitDate: Mon, 17 Apr 2017 12:35:33 +0200

efi/libstub/arm: Don't use TASK_SIZE when randomizing the RT space

As reported by James, Catalin and Mark, commit:

  e69176d68d26 ("ef/libstub/arm/arm64: Randomize the base of the UEFI rt 
services region")

... results in a crash in the firmware, regardless of whether KASLR
is in effect or not and whether the firmware implements EFI_RNG_PROTOCOL
or not.

Mark has identified the root cause to be the inappropriate use of
TASK_SIZE in the stub, which arm64 defines as:

  #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
TASK_SIZE_32 : TASK_SIZE_64)

and testing thread flags at this point results in the dereference of
pointers in uninitialized structures.

So instead, introduce a preprocessor symbol EFI_RT_VIRTUAL_LIMIT and
define it to TASK_SIZE_64 on arm64 and TASK_SIZE on ARM, both of which
are compile time constants. Also, change the 'headroom' variable to
static const to force an error if this might change in the future.

Tested-by: Mark Rutland 
Tested-by: James Morse 
Tested-by: Catalin Marinas 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170417093201.10181-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 1e45ec5..8181ac1 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -32,6 +32,12 @@
 #define EFI_RT_VIRTUAL_BASESZ_512M
 #define EFI_RT_VIRTUAL_SIZESZ_512M
 
+#ifdef CONFIG_ARM64
+# define EFI_RT_VIRTUAL_LIMIT  TASK_SIZE_64
+#else
+# define EFI_RT_VIRTUAL_LIMIT  TASK_SIZE
+#endif
+
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
@@ -236,8 +242,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 * shift of 21 bit positions into account when scaling
 * the headroom value using a 32-bit random value.
 */
-   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
-  EFI_RT_VIRTUAL_SIZE;
+   static const u64 headroom = EFI_RT_VIRTUAL_LIMIT -
+   EFI_RT_VIRTUAL_BASE -
+   EFI_RT_VIRTUAL_SIZE;
u32 rnd;
 
status = efi_get_random_bytes(sys_table, sizeof(rnd),


[tip:efi/core] efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  eeff7d634f4750306785be709ca444140c29b043
Gitweb: http://git.kernel.org/tip/eeff7d634f4750306785be709ca444140c29b043
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:09 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:28 +0200

efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

The EFI stub currently prints a number of diagnostic messages that do
not carry a lot of information. Since these prints are not controlled
by 'loglevel' or other command line parameters, and since they appear on
the EFI framebuffer as well (if enabled), it would be nice if we could
turn them off.

So let's add support for the 'quiet' command line parameter in the stub,
and disable the non-error prints if it is passed.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 20 ++--
 drivers/firmware/efi/libstub/arm32-stub.c  |  2 ++
 drivers/firmware/efi/libstub/efi-stub-helper.c |  9 +
 drivers/firmware/efi/libstub/efistub.h |  7 +++
 drivers/firmware/efi/libstub/secureboot.c  |  2 ++
 include/linux/efi.h|  3 ---
 6 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index ac3222f..657bb72 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -116,8 +116,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   pr_efi(sys_table, "Booting Linux Kernel...\n");
-
status = check_platform_features(sys_table);
if (status != EFI_SUCCESS)
goto fail;
@@ -151,6 +149,16 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
+
+   pr_efi(sys_table, "Booting Linux Kernel...\n");
+
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, &image_size,
@@ -162,14 +170,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
-   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
-   cmdline_size == 0)
-   efi_parse_options(CONFIG_CMDLINE);
-
-   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
-   efi_parse_options(cmdline_ptr);
-
secure_boot = efi_get_secureboot(sys_table);
 
/*
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index 18a8b5e..becbda4 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,8 @@
 #include 
 #include 
 
+#include "efistub.h"
+
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
int block;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 2e17d2b..b018436 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -33,11 +33,16 @@
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
 static int __section(.data) __nokaslr;
+static int __section(.data) __quiet;
 
 int __pure nokaslr(void)
 {
return __nokaslr;
 }
+int __pure is_quiet(void)
+{
+   return __quiet;
+}
 
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
@@ -424,6 +429,10 @@ efi_status_t efi_parse_options(char const *cmdline)
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
__nokaslr = 1;
 
+   str = strstr(cmdline, "quiet");
+   if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+   __quiet = 1;
+
/*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index a7a2a2c..83f268c 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -25,6 +25,13 @@
 #endif
 
 exte

[tip:efi/core] efi/libstub: Fix harmless command line parsing bug

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  4c3f14bb87b683a2e5bbc6d6660b41893ecacfd0
Gitweb: http://git.kernel.org/tip/4c3f14bb87b683a2e5bbc6d6660b41893ecacfd0
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:45 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:27 +0200

efi/libstub: Fix harmless command line parsing bug

When we parse the 'efi=' command line parameter in the stub, we
fail to take spaces into account. Currently, the only way this
could result in unexpected behavior is when the string 'nochunk'
appears as a separate command line argument after 'efi=xxx,yyy,zzz ',
so this is harmless in practice. But let's fix it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 919822b..3290fae 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -436,14 +436,14 @@ efi_status_t efi_parse_options(char *cmdline)
 * Remember, because efi= is also used by the kernel we need to
 * skip over arguments we don't understand.
 */
-   while (*str) {
+   while (*str && *str != ' ') {
if (!strncmp(str, "nochunk", 7)) {
str += strlen("nochunk");
__chunk_size = -1UL;
}
 
/* Group words together, delimited by "," */
-   while (*str && *str != ',')
+   while (*str && *str != ' ' && *str != ',')
str++;
 
if (*str == ',')


[tip:efi/core] efi/libstub: Unify command line param parsing

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  60f38de7a8d4e816100ceafd1b382df52527bd50
Gitweb: http://git.kernel.org/tip/60f38de7a8d4e816100ceafd1b382df52527bd50
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:08 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:28 +0200

efi/libstub: Unify command line param parsing

Merge the parsing of the command line carried out in arm-stub.c with
the handling in efi_parse_options(). Note that this also fixes the
missing handling of CONFIG_CMDLINE_FORCE=y, in which case the builtin
command line should supersede the one passed by the firmware.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-1-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 24 +++-
 drivers/firmware/efi/libstub/arm64-stub.c  |  4 +---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 19 +++
 drivers/firmware/efi/libstub/efistub.h |  2 ++
 include/linux/efi.h|  2 +-
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 02049ff..ac3222f 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,8 +18,6 @@
 
 #include "efistub.h"
 
-bool __nokaslr;
-
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -153,18 +151,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
-   /* check whether 'nokaslr' was passed on the command line */
-   if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   static const u8 default_cmdline[] = CONFIG_CMDLINE;
-   const u8 *str, *cmdline = cmdline_ptr;
-
-   if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
-   cmdline = default_cmdline;
-   str = strstr(cmdline, "nokaslr");
-   if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
-   __nokaslr = true;
-   }
-
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, &image_size,
@@ -176,9 +162,13 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   status = efi_parse_options(cmdline_ptr);
-   if (status != EFI_SUCCESS)
-   pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
 
secure_boot = efi_get_secureboot(sys_table);
 
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index eae693e..b4c2589 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -16,8 +16,6 @@
 
 #include "efistub.h"
 
-extern bool __nokaslr;
-
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
u64 tg;
@@ -52,7 +50,7 @@ efi_status_t handle_kernel_image(efi_system_table_t 
*sys_table_arg,
u64 phys_seed = 0;
 
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   if (!__nokaslr) {
+   if (!nokaslr()) {
status = efi_get_random_bytes(sys_table_arg,
  sizeof(phys_seed),
  (u8 *)&phys_seed);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3290fae..2e17d2b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,6 +32,13 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
+static int __section(.data) __nokaslr;
+
+int __pure nokaslr(void)
+{
+   return __nokaslr;
+}
+
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
@@ -409,17 +416,13 @@ static efi_status_t efi_file_close(void *handle)
  * environments, first in the early boot environment of the EFI boot
  * stub, and subsequently during the kernel boot.
  */
-efi_status_t efi_parse_options(char *cmdline)
+efi_status_t efi_parse_options(char const *cmdline)
 {
char *str;
 
-   /*
-* Currently, the only efi= option 

[tip:efi/core] ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  e69176d68d26d63d9214797c191ce65358ea1ecf
Gitweb: http://git.kernel.org/tip/e69176d68d26d63d9214797c191ce65358ea1ecf
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:10 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:29 +0200

ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

Update the allocation logic for the virtual mapping of the UEFI runtime
services to start from a randomized base address if KASLR is in effect,
and if the UEFI firmware exposes an implementation of EFI_RNG_PROTOCOL.

This makes it more difficult to predict the location of exploitable
data structures in the runtime UEFI firmware, which increases robustness
against attacks. Note that these regions are only mapped during the
time a runtime service call is in progress, and only on a single CPU
at a time, bit given the lack of a downside, let's enable it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 49 -
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 657bb72..1e45ec5 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,6 +18,22 @@
 
 #include "efistub.h"
 
+/*
+ * This is the base address at which to start allocating virtual memory ranges
+ * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
+ * any allocation we choose, and eliminate the risk of a conflict after kexec.
+ * 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. (512 MB is a reasonable upper bound for the
+ * entire footprint of the UEFI runtime services memory regions)
+ */
+#define EFI_RT_VIRTUAL_BASESZ_512M
+#define EFI_RT_VIRTUAL_SIZESZ_512M
+
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -213,6 +229,25 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
+   if (!nokaslr()) {
+   /*
+* Randomize the base of the UEFI runtime services region.
+* Preserve the 2 MB alignment of the region by taking a
+* shift of 21 bit positions into account when scaling
+* the headroom value using a 32-bit random value.
+*/
+   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
+  EFI_RT_VIRTUAL_SIZE;
+   u32 rnd;
+
+   status = efi_get_random_bytes(sys_table, sizeof(rnd),
+ (u8 *)&rnd);
+   if (status == EFI_SUCCESS) {
+   virtmap_base = EFI_RT_VIRTUAL_BASE +
+  (((headroom >> 21) * rnd) >> (32 - 21));
+   }
+   }
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
@@ -242,18 +277,6 @@ fail:
return EFI_ERROR;
 }
 
-/*
- * This is the base address at which to start allocating virtual memory ranges
- * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
- * any allocation we choose, and eliminate the risk of a conflict after kexec.
- * 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_BASESZ_512M
-
 static int cmp_mem_desc(const void *l, const void *r)
 {
const efi_memory_desc_t *left = l, *right = r;
@@ -303,7 +326,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, 
unsigned long map_size,
 unsigned long desc_size, efi_memory_desc_t *runtime_map,
 int *count)
 {
-   u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
+   u64 efi_virt_base = virtmap_base;
efi_memory_desc_t *in, *prev = NULL, *out = runtim

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  318532bf63cfab779d763527d8b93e48c4a96dba
Gitweb: http://git.kernel.org/tip/318532bf63cfab779d763527d8b93e48c4a96dba
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:26 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= &memory_map,
+   .map_size   = &map_size,
+   .desc_size  = &desc_size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = &buff_size,
+   };
+
+   /*
+* 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 + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, &map);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 
map.\n");
+   return status;
+   }
+
+   for (l = 0; l < map_size; l += desc_size) {
+   efi_memory_desc_t *desc;
+   u64 start, end;
+
+   desc = (void *)memory_map + l;

[tip:efi/core] efi/arm-stub: Correct FDT and initrd allocation rules for arm64

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  138728dd4ee30d3f35587c269c46cc829ec4d58b
Gitweb: http://git.kernel.org/tip/138728dd4ee30d3f35587c269c46cc829ec4d58b
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:37 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:23 +0200

efi/arm-stub: Correct FDT and initrd allocation rules for arm64

On arm64, we have made some changes over the past year to the way the
kernel itself is allocated and to how it deals with the initrd and FDT.
This patch brings the allocation logic in the EFI stub in line with that,
which is necessary because the introduction of KASLR has created the
possibility for the initrd to be allocated in a place where the kernel
may not be able to map it. (This is mostly a theoretical scenario, since
it only affects systems where the physical memory footprint exceeds the
size of the linear mapping.)

Since we know the kernel itself will be covered by the linear mapping,
choose a suitably sized window (i.e., based on the size of the linear
region) covering the kernel when allocating memory for the initrd.

The FDT may be anywhere in memory on arm64 now that we map it via the
fixmap, so we can lift the address restriction there completely.

Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h  | 14 +-
 arch/arm64/include/asm/efi.h| 23 ++-
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e4e6a9d6..17f1f1a 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info 
*si, const char *opt)
  */
 #define ZIMAGE_OFFSET_LIMITSZ_128M
 #define MIN_ZIMAGE_OFFSET  MAX_UNCOMP_KERNEL_SIZE
-#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
+
+/* on ARM, the FDT should be located in the first 128 MB of RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return dram_base + ZIMAGE_OFFSET_LIMIT;
+}
+
+/* on ARM, the initrd should be loaded in a lowmem region */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return dram_base + SZ_512M;
+}
 
 #endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e744528..083a52d3 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
  * 2MiB so we know it won't cross a 2MiB boundary.
  */
 #define EFI_FDT_ALIGN  SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET SZ_512M
+
+/* on arm64, the FDT may be located anywhere in system RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return ULONG_MAX;
+}
+
+/*
+ * On arm64, we have to ensure that the initrd ends up in the linear region,
+ * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
+ * guaranteed to cover the kernel Image.
+ *
+ * Since the EFI stub is part of the kernel Image, we can relax the
+ * usual requirements in Documentation/arm64/booting.txt, which still
+ * apply to other bootloaders, and are required for some kernel
+ * configurations.
+ */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
+}
 
 #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
 #define __efi_call_early(f, ...)   f(__VA_ARGS__)
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index d4056c6..02049ff 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (!fdt_addr)
pr_efi(sys_table, "Generating empty DTB\n");
 
-   status = handle_cmdline_files(sys_table, image, cmdline_ptr,
- "initrd=", dram_base + SZ_512M,
+   status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+ efi_get_max_initrd_addr(dram_base,
+ *image_addr),
  (unsigned long *)&initrd_addr,
  (unsigned long *)&initrd_size);
if (st

[tip:efi/core] efi/arm-stub: Round up FDT allocation to mapping size

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  24d7c494ce46d5bb6c8fd03e88a48ae249ec1492
Gitweb: http://git.kernel.org/tip/24d7c494ce46d5bb6c8fd03e88a48ae249ec1492
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:39 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:24 +0200

efi/arm-stub: Round up FDT allocation to mapping size

The FDT is mapped via a fixmap entry that is at least 2 MB in size and
2 MB aligned on 4 KB page size kernels.

On UEFI systems, the FDT allocation may share this 2 MB mapping with a
reserved region (or another memory region that we should never map),
unless we account for this in the size of the allocation (the alignment
is already 2 MB)

So instead of taking guesses at the needed space, simply allocate 2 MB
immediately. The allocation will be recorded as EFI_LOADER_DATA, and the
kernel only memblock_reserve()'s the actual size of the FDT, so the
unused space will be released back to the kernel.

Reviewed-By: Jeffrey Hugo 
Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h   |  1 +
 drivers/firmware/efi/libstub/fdt.c | 57 --
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 083a52d3..8f3043a 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 260c4b4..41f457b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
+#ifndef MAX_FDT_SIZE
+#define MAX_FDT_SIZE   SZ_2M
+#endif
+
 /*
  * Allocate memory for a new FDT, then add EFI, commandline, and
  * initrd related fields to the FDT.  This routine increases the
@@ -233,7 +237,6 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
u32 desc_ver;
unsigned long mmap_key;
efi_memory_desc_t *memory_map, *runtime_map;
-   unsigned long new_fdt_size;
efi_status_t status;
int runtime_entry_count = 0;
struct efi_boot_memmap map;
@@ -262,41 +265,29 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
   "Exiting boot services and installing virtual address map...\n");
 
map.map = &memory_map;
+   status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
+   new_fdt_addr, max_addr);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table,
+  "Unable to allocate memory for new device tree.\n");
+   goto fail;
+   }
+
/*
-* Estimate size of new FDT, and allocate memory for it. We
-* will allocate a bigger buffer if this ends up being too
-* small, so a rough guess is OK here.
+* Now that we have done our final memory allocation (and free)
+* we can get the memory map key needed for exit_boot_services().
 */
-   new_fdt_size = fdt_size + EFI_PAGE_SIZE;
-   while (1) {
-   status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
-   new_fdt_addr, max_addr);
-   if (status != EFI_SUCCESS) {
-   pr_efi_err(sys_table, "Unable to allocate memory for 
new device tree.\n");
-   goto fail;
-   }
-
-   status = update_fdt(sys_table,
-   (void *)fdt_addr, fdt_size,
-   (void *)*new_fdt_addr, new_fdt_size,
-   cmdline_ptr, initrd_addr, initrd_size);
+   status = efi_get_memory_map(sys_table, &map);
+   if (status != EFI_SUCCESS)
+   goto fail_free_new_fdt;
 
-   /* Succeeding the first time is the expected case. */
-   if (status == EFI_SUCCESS)
-   break;
+   status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
+   (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
+   initrd_addr, initrd_size);
 
-   if (status == EFI_BUFFER_TOO_SMALL) {
-   /*
-* We need to allocate more space for the new
-* device tree, so free existing buffer that is
-* too small.
-*/
-   efi_free(sys_table, new_fdt_size, *new_fdt_addr);
- 

[tip:efi/urgent] efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  55d728a40d368ba80443be85c02e641fc9082a3f
Gitweb: http://git.kernel.org/tip/55d728a40d368ba80443be85c02e641fc9082a3f
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 16:27:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:25:53 +0200

efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

On UEFI systems, the PCI subsystem is enumerated by the firmware,
and if a graphical framebuffer is exposed via a PCI device, its base
address and size are exposed to the OS via the Graphics Output
Protocol (GOP).

On arm64 PCI systems, the entire PCI hierarchy is reconfigured from
scratch at boot. This may result in the GOP framebuffer address to
become stale, if the BAR covering the framebuffer is modified. This
will cause the framebuffer to become unresponsive, and may in some
cases result in unpredictable behavior if the range is reassigned to
another device.

So add a non-x86 quirk to the EFI fb driver to find the BAR associated
with the GOP base address, and claim the BAR resource so that the PCI
core will not move it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.7+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: lorenzo.pieral...@arm.com
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Link: http://lkml.kernel.org/r/20170404152744.26687-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 66 -
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 8c4dc1e..b827a81 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
+static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_total;
char *option = NULL;
 
-   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
 
if (fb_get_options("efifb", &option))
@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = {
 };
 
 builtin_platform_driver(efifb_driver);
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
+
+static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+
+static void claim_efifb_bar(struct pci_dev *dev, int idx)
+{
+   u16 word;
+
+   pci_bar_found = true;
+
+   pci_read_config_word(dev, PCI_COMMAND, &word);
+   if (!(word & PCI_COMMAND_MEMORY)) {
+   pci_dev_disabled = true;
+   dev_err(&dev->dev,
+   "BAR %d: assigned to efifb but device is disabled!\n",
+   idx);
+   return;
+   }
+
+   if (pci_claim_resource(dev, idx)) {
+   pci_dev_disabled = true;
+   dev_err(&dev->dev,
+   "BAR %d: failed to claim resource for efifb!\n", idx);
+   return;
+   }
+
+   dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
+}
+
+static void efifb_fixup_resources(struct pci_dev *dev)
+{
+   u64 base = screen_info.lfb_base;
+   u64 size = screen_info.lfb_size;
+   int i;
+
+   if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   return;
+
+   if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+   base |= (u64)screen_info.ext_lfb_base << 32;
+
+   if (!base)
+   return;
+
+   for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+   struct resource *res = &dev->resource[i];
+
+   if (!(res->flags & IORESOURCE_MEM))
+   continue;
+
+   if (res->start <= base && res->end >= base + size - 1) {
+   claim_efifb_bar(dev, i);
+   break;
+   }
+   }
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
+  16, efifb_fixup_resources);
+
+#endif


[tip:efi/core] efi/libstub: Unify command line param parsing

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  794e5ecb8c444bcc7e42b82e3ae7a457987949d3
Gitweb: http://git.kernel.org/tip/794e5ecb8c444bcc7e42b82e3ae7a457987949d3
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:08 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:54 +0200

efi/libstub: Unify command line param parsing

Merge the parsing of the command line carried out in arm-stub.c with
the handling in efi_parse_options(). Note that this also fixes the
missing handling of CONFIG_CMDLINE_FORCE=y, in which case the builtin
command line should supersede the one passed by the firmware.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-1-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 24 +++-
 drivers/firmware/efi/libstub/arm64-stub.c  |  4 +---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 19 +++
 drivers/firmware/efi/libstub/efistub.h |  2 ++
 include/linux/efi.h|  2 +-
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 02049ff..ac3222f 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,8 +18,6 @@
 
 #include "efistub.h"
 
-bool __nokaslr;
-
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -153,18 +151,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
-   /* check whether 'nokaslr' was passed on the command line */
-   if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   static const u8 default_cmdline[] = CONFIG_CMDLINE;
-   const u8 *str, *cmdline = cmdline_ptr;
-
-   if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
-   cmdline = default_cmdline;
-   str = strstr(cmdline, "nokaslr");
-   if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
-   __nokaslr = true;
-   }
-
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, &image_size,
@@ -176,9 +162,13 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   status = efi_parse_options(cmdline_ptr);
-   if (status != EFI_SUCCESS)
-   pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
 
secure_boot = efi_get_secureboot(sys_table);
 
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c 
b/drivers/firmware/efi/libstub/arm64-stub.c
index eae693e..b4c2589 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -16,8 +16,6 @@
 
 #include "efistub.h"
 
-extern bool __nokaslr;
-
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
u64 tg;
@@ -52,7 +50,7 @@ efi_status_t handle_kernel_image(efi_system_table_t 
*sys_table_arg,
u64 phys_seed = 0;
 
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-   if (!__nokaslr) {
+   if (!nokaslr()) {
status = efi_get_random_bytes(sys_table_arg,
  sizeof(phys_seed),
  (u8 *)&phys_seed);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3290fae..2e17d2b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,6 +32,13 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
+static int __section(.data) __nokaslr;
+
+int __pure nokaslr(void)
+{
+   return __nokaslr;
+}
+
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
@@ -409,17 +416,13 @@ static efi_status_t efi_file_close(void *handle)
  * environments, first in the early boot environment of the EFI boot
  * stub, and subsequently during the kernel boot.
  */
-efi_status_t efi_parse_options(char *cmdline)
+efi_status_t efi_parse_options(char const *cmdline)
 {
char *str;
 
-   /*
-* Currently, the only efi= option 

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Gitweb: http://git.kernel.org/tip/0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:52 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= &memory_map,
+   .map_size   = &map_size,
+   .desc_size  = &desc_size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = &buff_size,
+   };
+
+   /*
+* 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 + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, &map);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 
map.\n");
+   return status;
+   }
+
+   for (l = 0; l < map_size; l += desc_size) {
+   efi_memory_desc_t *desc;
+   u64 start, end;
+
+   desc = (void *)memory_map + l;

[tip:efi/core] efi/libstub: Fix harmless command line parsing bug

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  935061e3a7de5eae398327de9f7b92588bfcf7fc
Gitweb: http://git.kernel.org/tip/935061e3a7de5eae398327de9f7b92588bfcf7fc
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:45 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:53 +0200

efi/libstub: Fix harmless command line parsing bug

When we parse the 'efi=' command line parameter in the stub, we
fail to take spaces into account. Currently, the only way this
could result in unexpected behavior is when the string 'nochunk'
appears as a separate command line argument after 'efi=xxx,yyy,zzz ',
so this is harmless in practice. But let's fix it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-12-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 919822b..3290fae 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -436,14 +436,14 @@ efi_status_t efi_parse_options(char *cmdline)
 * Remember, because efi= is also used by the kernel we need to
 * skip over arguments we don't understand.
 */
-   while (*str) {
+   while (*str && *str != ' ') {
if (!strncmp(str, "nochunk", 7)) {
str += strlen("nochunk");
__chunk_size = -1UL;
}
 
/* Group words together, delimited by "," */
-   while (*str && *str != ',')
+   while (*str && *str != ' ' && *str != ',')
str++;
 
if (*str == ',')


[tip:efi/core] efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b27aef2499e8c5af11aee9c239029ca4dbe162ed
Gitweb: http://git.kernel.org/tip/b27aef2499e8c5af11aee9c239029ca4dbe162ed
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:09 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:55 +0200

efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg

The EFI stub currently prints a number of diagnostic messages that do
not carry a lot of information. Since these prints are not controlled
by 'loglevel' or other command line parameters, and since they appear on
the EFI framebuffer as well (if enabled), it would be nice if we could
turn them off.

So let's add support for the 'quiet' command line parameter in the stub,
and disable the non-error prints if it is passed.

Signed-off-by: Ard Biesheuvel 
Acked-by: Mark Rutland 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: b...@alien8.de
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-2-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c| 20 ++--
 drivers/firmware/efi/libstub/arm32-stub.c  |  2 ++
 drivers/firmware/efi/libstub/efi-stub-helper.c |  9 +
 drivers/firmware/efi/libstub/efistub.h |  7 +++
 drivers/firmware/efi/libstub/secureboot.c  |  2 ++
 include/linux/efi.h|  3 ---
 6 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index ac3222f..657bb72 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -116,8 +116,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
 
-   pr_efi(sys_table, "Booting Linux Kernel...\n");
-
status = check_platform_features(sys_table);
if (status != EFI_SUCCESS)
goto fail;
@@ -151,6 +149,16 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail;
}
 
+   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+   cmdline_size == 0)
+   efi_parse_options(CONFIG_CMDLINE);
+
+   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+   efi_parse_options(cmdline_ptr);
+
+   pr_efi(sys_table, "Booting Linux Kernel...\n");
+
si = setup_graphics(sys_table);
 
status = handle_kernel_image(sys_table, image_addr, &image_size,
@@ -162,14 +170,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
-   if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
-   IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
-   cmdline_size == 0)
-   efi_parse_options(CONFIG_CMDLINE);
-
-   if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
-   efi_parse_options(cmdline_ptr);
-
secure_boot = efi_get_secureboot(sys_table);
 
/*
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index 18a8b5e..becbda4 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -9,6 +9,8 @@
 #include 
 #include 
 
+#include "efistub.h"
+
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 {
int block;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 2e17d2b..b018436 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -33,11 +33,16 @@
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
 static int __section(.data) __nokaslr;
+static int __section(.data) __quiet;
 
 int __pure nokaslr(void)
 {
return __nokaslr;
 }
+int __pure is_quiet(void)
+{
+   return __quiet;
+}
 
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
@@ -424,6 +429,10 @@ efi_status_t efi_parse_options(char const *cmdline)
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
__nokaslr = 1;
 
+   str = strstr(cmdline, "quiet");
+   if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
+   __quiet = 1;
+
/*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index a7a2a2c..83f268c 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -25,6 +25,13 @@
 #endif
 
 exte

[tip:efi/core] ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  170bd898f1ae1ad717d56053846f8bbd2e526045
Gitweb: http://git.kernel.org/tip/170bd898f1ae1ad717d56053846f8bbd2e526045
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:09:10 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:55 +0200

ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region

Update the allocation logic for the virtual mapping of the UEFI runtime
services to start from a randomized base address if KASLR is in effect,
and if the UEFI firmware exposes an implementation of EFI_RNG_PROTOCOL.

This makes it more difficult to predict the location of exploitable
data structures in the runtime UEFI firmware, which increases robustness
against attacks. Note that these regions are only mapped during the
time a runtime service call is in progress, and only on a single CPU
at a time, bit given the lack of a downside, let's enable it nonetheless.

Signed-off-by: Ard Biesheuvel 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: b...@redhat.com
Cc: bhsha...@redhat.com
Cc: eug...@hp.com
Cc: evgeny.kalu...@intel.com
Cc: jh...@codeaurora.org
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: mark.rutl...@arm.com
Cc: roy.fr...@cavium.com
Cc: rruig...@codeaurora.org
Link: http://lkml.kernel.org/r/20170404160910.28115-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c | 49 -
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 657bb72..1e45ec5 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -18,6 +18,22 @@
 
 #include "efistub.h"
 
+/*
+ * This is the base address at which to start allocating virtual memory ranges
+ * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
+ * any allocation we choose, and eliminate the risk of a conflict after kexec.
+ * 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. (512 MB is a reasonable upper bound for the
+ * entire footprint of the UEFI runtime services memory regions)
+ */
+#define EFI_RT_VIRTUAL_BASESZ_512M
+#define EFI_RT_VIRTUAL_SIZESZ_512M
+
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 void *__image, void **__fh)
 {
@@ -213,6 +229,25 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
 
efi_random_get_seed(sys_table);
 
+   if (!nokaslr()) {
+   /*
+* Randomize the base of the UEFI runtime services region.
+* Preserve the 2 MB alignment of the region by taking a
+* shift of 21 bit positions into account when scaling
+* the headroom value using a 32-bit random value.
+*/
+   u64 headroom = TASK_SIZE - EFI_RT_VIRTUAL_BASE -
+  EFI_RT_VIRTUAL_SIZE;
+   u32 rnd;
+
+   status = efi_get_random_bytes(sys_table, sizeof(rnd),
+ (u8 *)&rnd);
+   if (status == EFI_SUCCESS) {
+   virtmap_base = EFI_RT_VIRTUAL_BASE +
+  (((headroom >> 21) * rnd) >> (32 - 21));
+   }
+   }
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
@@ -242,18 +277,6 @@ fail:
return EFI_ERROR;
 }
 
-/*
- * This is the base address at which to start allocating virtual memory ranges
- * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
- * any allocation we choose, and eliminate the risk of a conflict after kexec.
- * 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_BASESZ_512M
-
 static int cmp_mem_desc(const void *l, const void *r)
 {
const efi_memory_desc_t *left = l, *right = r;
@@ -303,7 +326,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, 
unsigned long map_size,
 unsigned long desc_size, efi_memory_desc_t *runtime_map,
 int *count)
 {
-   u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
+   u64 efi_virt_base = virtmap_base;
efi_memory_desc_t *in, *prev = NULL, *out = runtim

[tip:efi/core] efi/arm-stub: Round up FDT allocation to mapping size

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  05181c7c42c830e5f3fe7a0e93dfec0bd0fd8456
Gitweb: http://git.kernel.org/tip/05181c7c42c830e5f3fe7a0e93dfec0bd0fd8456
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:39 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:49 +0200

efi/arm-stub: Round up FDT allocation to mapping size

The FDT is mapped via a fixmap entry that is at least 2 MB in size and
2 MB aligned on 4 KB page size kernels.

On UEFI systems, the FDT allocation may share this 2 MB mapping with a
reserved region (or another memory region that we should never map),
unless we account for this in the size of the allocation (the alignment
is already 2 MB)

So instead of taking guesses at the needed space, simply allocate 2 MB
immediately. The allocation will be recorded as EFI_LOADER_DATA, and the
kernel only memblock_reserve()'s the actual size of the FDT, so the
unused space will be released back to the kernel.

Reviewed-By: Jeffrey Hugo 
Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-6-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm64/include/asm/efi.h   |  1 +
 drivers/firmware/efi/libstub/fdt.c | 57 --
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 083a52d3..8f3043a 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 260c4b4..41f457b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
+#ifndef MAX_FDT_SIZE
+#define MAX_FDT_SIZE   SZ_2M
+#endif
+
 /*
  * Allocate memory for a new FDT, then add EFI, commandline, and
  * initrd related fields to the FDT.  This routine increases the
@@ -233,7 +237,6 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
u32 desc_ver;
unsigned long mmap_key;
efi_memory_desc_t *memory_map, *runtime_map;
-   unsigned long new_fdt_size;
efi_status_t status;
int runtime_entry_count = 0;
struct efi_boot_memmap map;
@@ -262,41 +265,29 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
   "Exiting boot services and installing virtual address map...\n");
 
map.map = &memory_map;
+   status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
+   new_fdt_addr, max_addr);
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table,
+  "Unable to allocate memory for new device tree.\n");
+   goto fail;
+   }
+
/*
-* Estimate size of new FDT, and allocate memory for it. We
-* will allocate a bigger buffer if this ends up being too
-* small, so a rough guess is OK here.
+* Now that we have done our final memory allocation (and free)
+* we can get the memory map key needed for exit_boot_services().
 */
-   new_fdt_size = fdt_size + EFI_PAGE_SIZE;
-   while (1) {
-   status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
-   new_fdt_addr, max_addr);
-   if (status != EFI_SUCCESS) {
-   pr_efi_err(sys_table, "Unable to allocate memory for 
new device tree.\n");
-   goto fail;
-   }
-
-   status = update_fdt(sys_table,
-   (void *)fdt_addr, fdt_size,
-   (void *)*new_fdt_addr, new_fdt_size,
-   cmdline_ptr, initrd_addr, initrd_size);
+   status = efi_get_memory_map(sys_table, &map);
+   if (status != EFI_SUCCESS)
+   goto fail_free_new_fdt;
 
-   /* Succeeding the first time is the expected case. */
-   if (status == EFI_SUCCESS)
-   break;
+   status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
+   (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
+   initrd_addr, initrd_size);
 
-   if (status == EFI_BUFFER_TOO_SMALL) {
-   /*
-* We need to allocate more space for the new
-* device tree, so free existing buffer that is
-* too small.
-*/
-   efi_free(sys_table, new_fdt_size, *new_fdt_addr);
- 

[tip:efi/core] efi/arm-stub: Correct FDT and initrd allocation rules for arm64

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5e0e04e655826dce058c75a82adaa979231e6149
Gitweb: http://git.kernel.org/tip/5e0e04e655826dce058c75a82adaa979231e6149
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:37 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:48 +0200

efi/arm-stub: Correct FDT and initrd allocation rules for arm64

On arm64, we have made some changes over the past year to the way the
kernel itself is allocated and to how it deals with the initrd and FDT.
This patch brings the allocation logic in the EFI stub in line with that,
which is necessary because the introduction of KASLR has created the
possibility for the initrd to be allocated in a place where the kernel
may not be able to map it. (This is mostly a theoretical scenario, since
it only affects systems where the physical memory footprint exceeds the
size of the linear mapping.)

Since we know the kernel itself will be covered by the linear mapping,
choose a suitably sized window (i.e., based on the size of the linear
region) covering the kernel when allocating memory for the initrd.

The FDT may be anywhere in memory on arm64 now that we map it via the
fixmap, so we can lift the address restriction there completely.

Tested-by: Richard Ruigrok 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h  | 14 +-
 arch/arm64/include/asm/efi.h| 23 ++-
 drivers/firmware/efi/libstub/arm-stub.c |  7 ---
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e4e6a9d6..17f1f1a 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info 
*si, const char *opt)
  */
 #define ZIMAGE_OFFSET_LIMITSZ_128M
 #define MIN_ZIMAGE_OFFSET  MAX_UNCOMP_KERNEL_SIZE
-#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
+
+/* on ARM, the FDT should be located in the first 128 MB of RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return dram_base + ZIMAGE_OFFSET_LIMIT;
+}
+
+/* on ARM, the initrd should be loaded in a lowmem region */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return dram_base + SZ_512M;
+}
 
 #endif /* _ASM_ARM_EFI_H */
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e744528..083a52d3 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, 
efi_memory_desc_t *md);
  * 2MiB so we know it won't cross a 2MiB boundary.
  */
 #define EFI_FDT_ALIGN  SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET SZ_512M
+
+/* on arm64, the FDT may be located anywhere in system RAM */
+static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
+{
+   return ULONG_MAX;
+}
+
+/*
+ * On arm64, we have to ensure that the initrd ends up in the linear region,
+ * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
+ * guaranteed to cover the kernel Image.
+ *
+ * Since the EFI stub is part of the kernel Image, we can relax the
+ * usual requirements in Documentation/arm64/booting.txt, which still
+ * apply to other bootloaders, and are required for some kernel
+ * configurations.
+ */
+static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
+   unsigned long image_addr)
+{
+   return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
+}
 
 #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
 #define __efi_call_early(f, ...)   f(__VA_ARGS__)
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index d4056c6..02049ff 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (!fdt_addr)
pr_efi(sys_table, "Generating empty DTB\n");
 
-   status = handle_cmdline_files(sys_table, image, cmdline_ptr,
- "initrd=", dram_base + SZ_512M,
+   status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+ efi_get_max_initrd_addr(dram_base,
+ *image_addr),
  (unsigned long *)&initrd_addr,
  (unsigned long *)&initrd_size);
if (st

[tip:efi/urgent] efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  5a8997342183bb792fe2c15cecf371665d784dd7
Gitweb: http://git.kernel.org/tip/5a8997342183bb792fe2c15cecf371665d784dd7
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 16:27:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:20:18 +0200

efi/fb: Avoid reconfiguration of BAR that covers the framebuffer

On UEFI systems, the PCI subsystem is enumerated by the firmware,
and if a graphical framebuffer is exposed via a PCI device, its base
address and size are exposed to the OS via the Graphics Output
Protocol (GOP).

On arm64 PCI systems, the entire PCI hierarchy is reconfigured from
scratch at boot. This may result in the GOP framebuffer address to
become stale, if the BAR covering the framebuffer is modified. This
will cause the framebuffer to become unresponsive, and may in some
cases result in unpredictable behavior if the range is reassigned to
another device.

So add a non-x86 quirk to the EFI fb driver to find the BAR associated
with the GOP base address, and claim the BAR resource so that the PCI
core will not move it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.7+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: leif.lindh...@linaro.org
Cc: linux-...@vger.kernel.org
Cc: lorenzo.pieral...@arm.com
Fixes: 9822504c1fa5 ("efifb: Enable the efi-framebuffer platform driver ...")
Link: http://lkml.kernel.org/r/20170404152744.26687-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/video/fbdev/efifb.c | 66 -
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 8c4dc1e..758960b 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
 };
 ATTRIBUTE_GROUPS(efifb);
 
+static bool pci_dev_disabled;  /* FB base matches BAR of a disabled device */
+
 static int efifb_probe(struct platform_device *dev)
 {
struct fb_info *info;
@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_total;
char *option = NULL;
 
-   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
 
if (fb_get_options("efifb", &option))
@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = {
 };
 
 builtin_platform_driver(efifb_driver);
+
+#ifndef CONFIG_X86
+
+static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+
+static void claim_efifb_bar(struct pci_dev *dev, int idx)
+{
+   u16 word;
+
+   pci_bar_found = true;
+
+   pci_read_config_word(dev, PCI_COMMAND, &word);
+   if (!(word & PCI_COMMAND_MEMORY)) {
+   pci_dev_disabled = true;
+   dev_err(&dev->dev,
+   "BAR %d: assigned to efifb but device is disabled!\n",
+   idx);
+   return;
+   }
+
+   if (pci_claim_resource(dev, idx)) {
+   pci_dev_disabled = true;
+   dev_err(&dev->dev,
+   "BAR %d: failed to claim resource for efifb!\n", idx);
+   return;
+   }
+
+   dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
+}
+
+static void efifb_fixup_resources(struct pci_dev *dev)
+{
+   u64 base = screen_info.lfb_base;
+   u64 size = screen_info.lfb_size;
+   int i;
+
+   if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+   return;
+
+   if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+   base |= (u64)screen_info.ext_lfb_base << 32;
+
+   if (!base)
+   return;
+
+   for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+   struct resource *res = &dev->resource[i];
+
+   if (!(res->flags & IORESOURCE_MEM))
+   continue;
+
+   if (res->start <= base && res->end >= base + size - 1) {
+   claim_efifb_bar(dev, i);
+   break;
+   }
+   }
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
+  16, efifb_fixup_resources);
+
+#endif


[tip:efi/urgent] efi/libstub: Treat missing SecureBoot variable as Secure Boot disabled

2017-03-02 Thread tip-bot for Ard Biesheuvel
Commit-ID:  52e51f16407b7b34e26affb500a21e250d9fce0b
Gitweb: http://git.kernel.org/tip/52e51f16407b7b34e26affb500a21e250d9fce0b
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Mar 2017 19:04:35 +
Committer:  Ingo Molnar 
CommitDate: Thu, 2 Mar 2017 08:11:18 +0100

efi/libstub: Treat missing SecureBoot variable as Secure Boot disabled

The newly refactored code that infers the firmware's Secure Boot state
prints the following error when the EFI variable 'SecureBoot' does not
exist:

  EFI stub: ERROR: Could not determine UEFI Secure Boot status.

However, this variable is only guaranteed to be defined on a system that
is Secure Boot capable to begin with, and so it is not an error if it is
missing. So report Secure Boot as being disabled in this case, without
printing any error messages.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1488395076-29712-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/secureboot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/secureboot.c 
b/drivers/firmware/efi/libstub/secureboot.c
index 6def402..5da36e5 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -45,6 +45,8 @@ enum efi_secureboot_mode 
efi_get_secureboot(efi_system_table_t *sys_table_arg)
size = sizeof(secboot);
status = get_efi_var(efi_SecureBoot_name, &efi_variable_guid,
 NULL, &size, &secboot);
+   if (status == EFI_NOT_FOUND)
+   return efi_secureboot_mode_disabled;
if (status != EFI_SUCCESS)
goto out_efi_err;
 
@@ -78,7 +80,5 @@ secure_boot_enabled:
 
 out_efi_err:
pr_efi_err(sys_table_arg, "Could not determine UEFI Secure Boot 
status.\n");
-   if (status == EFI_NOT_FOUND)
-   return efi_secureboot_mode_disabled;
return efi_secureboot_mode_unknown;
 }


[tip:efi/urgent] efi/arm: Fix boot crash with CONFIG_CPUMASK_OFFSTACK=y

2017-03-02 Thread tip-bot for Ard Biesheuvel
Commit-ID:  d1eb98143c56f24fef125f5bbed49ae0b52fb7d6
Gitweb: http://git.kernel.org/tip/d1eb98143c56f24fef125f5bbed49ae0b52fb7d6
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Mar 2017 19:05:54 +
Committer:  Ingo Molnar 
CommitDate: Thu, 2 Mar 2017 08:11:19 +0100

efi/arm: Fix boot crash with CONFIG_CPUMASK_OFFSTACK=y

On ARM and arm64, we use a dedicated mm_struct to map the UEFI
Runtime Services regions, which allows us to map those regions
on demand, and in a way that is guaranteed to be compatible
with incoming kernels across kexec.

As it turns out, we don't fully initialize the mm_struct in the
same way as process mm_structs are initialized on fork(), which
results in the following crash on ARM if CONFIG_CPUMASK_OFFSTACK=y
is enabled:

  ...
  EFI Variables Facility v0.08 2004-May-17
  Unable to handle kernel NULL pointer dereference at virtual address 
  [...]
  Process swapper/0 (pid: 1)
  ...
  __memzero()
  check_and_switch_context()
  virt_efi_get_next_variable()
  efivar_init()
  efivars_sysfs_init()
  do_one_initcall()
  ...

This is due to a missing call to mm_init_cpumask(), so add it.

Signed-off-by: Ard Biesheuvel 
Cc:  # v4.5+
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1488395154-29786-1-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-runtime.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 349dc3e..974c5a3 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -65,6 +65,7 @@ static bool __init efi_virtmap_init(void)
bool systab_found;
 
efi_mm.pgd = pgd_alloc(&efi_mm);
+   mm_init_cpumask(&efi_mm);
init_new_context(NULL, &efi_mm);
 
systab_found = false;


[tip:efi/core] efi/libstub: Make file I/O chunking x86-specific

2017-02-07 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b3879a4d3a31ef14265a52e8d941cf4b0f6627ae
Gitweb: http://git.kernel.org/tip/b3879a4d3a31ef14265a52e8d941cf4b0f6627ae
Author: Ard Biesheuvel 
AuthorDate: Mon, 6 Feb 2017 11:22:46 +
Committer:  Ingo Molnar 
CommitDate: Tue, 7 Feb 2017 10:42:11 +0100

efi/libstub: Make file I/O chunking x86-specific

The ARM decompressor is finicky when it comes to uninitialized variables
with local linkage, the reason being that it may relocate .text and .bss
independently when executing from ROM. This is only possible if all
references into .bss from .text are absolute, and this happens to be the
case for references emitted under -fpic to symbols with external linkage,
and so all .bss references must involve symbols with external linkage.

When building the ARM stub using clang, the initialized local variable
__chunk_size is optimized into a zero-initialized flag that indicates
whether chunking is in effect or not. This flag is therefore emitted into
.bss, which triggers the ARM decompressor's diagnostics, resulting in a
failed build.

Under UEFI, we never execute the decompressor from ROM, so the diagnostic
makes little sense here. But we can easily work around the issue by making
__chunk_size global instead.

However, given that the file I/O chunking that is controlled by the
__chunk_size variable is intended to work around known bugs on various
x86 implementations of UEFI, we can simply make the chunking an x86
specific feature. This is an improvement by itself, and also removes the
need to parse the efi= options in the stub entirely.

Tested-by: Arnd Bergmann 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1486380166-31868-8-git-send-email-ard.biesheu...@linaro.org
[ Small readability edits. ]
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 6ee9164..919822b 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -414,6 +414,14 @@ efi_status_t efi_parse_options(char *cmdline)
char *str;
 
/*
+* Currently, the only efi= option we look for is 'nochunk', which
+* is intended to work around known issues on certain x86 UEFI
+* versions. So ignore for now on other architectures.
+*/
+   if (!IS_ENABLED(CONFIG_X86))
+   return EFI_SUCCESS;
+
+   /*
 * If no EFI parameters were specified on the cmdline we've got
 * nothing to do.
 */
@@ -586,7 +594,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t 
*sys_table_arg,
size = files[j].size;
while (size) {
unsigned long chunksize;
-   if (size > __chunk_size)
+
+   if (IS_ENABLED(CONFIG_X86) && size > 
__chunk_size)
chunksize = __chunk_size;
else
chunksize = size;


[tip:efi/urgent] efi/fdt: Avoid FDT manipulation after ExitBootServices()

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c8f325a59cfc718d13a50fbc746ed9b415c25e92
Gitweb: http://git.kernel.org/tip/c8f325a59cfc718d13a50fbc746ed9b415c25e92
Author: Ard Biesheuvel 
AuthorDate: Wed, 1 Feb 2017 17:45:02 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 21:17:49 +0100

efi/fdt: Avoid FDT manipulation after ExitBootServices()

Some AArch64 UEFI implementations disable the MMU in ExitBootServices(),
after which unaligned accesses to RAM are no longer supported.

Commit:

  abfb7b686a3e ("efi/libstub/arm*: Pass latest memory map to the kernel")

fixed an issue in the memory map handling of the stub FDT code, but
inadvertently created an issue with such firmware, by moving some
of the FDT manipulation to after the invocation of ExitBootServices().

Given that the stub's libfdt implementation uses the ordinary, accelerated
string functions, which rely on hardware handling of unaligned accesses,
manipulating the FDT with the MMU off may result in alignment faults.

So fix the situation by moving the update_fdt_memmap() call into the
callback function invoked by efi_exit_boot_services() right before it
calls the ExitBootServices() UEFI service (which is arguably a better
place for it anyway)

Note that disabling the MMU in ExitBootServices() is not compliant with
the UEFI spec, and carries great risk due to the fact that switching from
cached to uncached memory accesses halfway through compiler generated code
(i.e., involving a stack) can never be done in a way that is architecturally
safe.

Fixes: abfb7b686a3e ("efi/libstub/arm*: Pass latest memory map to the kernel")
Signed-off-by: Ard Biesheuvel 
Tested-by: Riku Voipio 
Cc: 
Cc: mark.rutl...@arm.com
Cc: linux-...@vger.kernel.org
Cc: m...@codeblueprint.co.uk
Cc: leif.lindh...@linaro.org
Cc: linux-arm-ker...@lists.infradead.org
Link: 
http://lkml.kernel.org/r/1485971102-23330-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/fdt.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index 921dfa0..260c4b4 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -187,6 +187,7 @@ static efi_status_t update_fdt_memmap(void *fdt, struct 
efi_boot_memmap *map)
 struct exit_boot_struct {
efi_memory_desc_t *runtime_map;
int *runtime_entry_count;
+   void *new_fdt_addr;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -202,7 +203,7 @@ static efi_status_t exit_boot_func(efi_system_table_t 
*sys_table_arg,
efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
p->runtime_map, p->runtime_entry_count);
 
-   return EFI_SUCCESS;
+   return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
 /*
@@ -300,22 +301,13 @@ efi_status_t 
allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 
priv.runtime_map = runtime_map;
priv.runtime_entry_count = &runtime_entry_count;
+   priv.new_fdt_addr = (void *)*new_fdt_addr;
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
exit_boot_func);
 
if (status == EFI_SUCCESS) {
efi_set_virtual_address_map_t *svam;
 
-   status = update_fdt_memmap((void *)*new_fdt_addr, &map);
-   if (status != EFI_SUCCESS) {
-   /*
-* The kernel won't get far without the memory map, but
-* may still be able to print something meaningful so
-* return success here.
-*/
-   return EFI_SUCCESS;
-   }
-
/* Install the new virtual address map */
svam = sys_table->runtime->set_virtual_address_map;
status = svam(runtime_entry_count * desc_size, desc_size,


[tip:efi/core] efi/libstub: Preserve .debug sections after absolute relocation check

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  696204faa6e8a318320ebb49d9fa69bc8275644d
Gitweb: http://git.kernel.org/tip/696204faa6e8a318320ebb49d9fa69bc8275644d
Author: Ard Biesheuvel 
AuthorDate: Tue, 31 Jan 2017 13:21:42 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 08:45:47 +0100

efi/libstub: Preserve .debug sections after absolute relocation check

The build commands for the ARM and arm64 EFI stubs strip the .debug
sections and other sections that may legally contain absolute relocations,
in order to inspect the remaining sections for the presence of such
relocations.

This leaves us without debugging symbols in the stub for no good reason,
considering that these sections are omitted from the kernel binary anyway,
and that these relocations are thus only consumed by users of the ELF
binary, such as debuggers.

So move to 'strip' for performing the relocation check, and if it succeeds,
invoke objcopy as before, but leaving the .debug sections in place. Note
that these sections may refer to ksymtab/kcrctab contents, so leave those
in place as well.

Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1485868902-20401-11-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index d564d25..33e0e2f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ -O2 \
   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
-cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \
+cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
   -fno-builtin -fpic -mno-single-pic-base
 
 cflags-$(CONFIG_EFI_ARMSTUB)   += -I$(srctree)/scripts/dtc/libfdt
@@ -60,7 +60,7 @@ CFLAGS_arm64-stub.o   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 extra-$(CONFIG_EFI_ARMSTUB):= $(lib-y)
 lib-$(CONFIG_EFI_ARMSTUB)  := $(patsubst %.o,%.stub.o,$(lib-y))
 
-STUBCOPY_FLAGS-y   := -R .debug* -R *ksymtab* -R *kcrctab*
+STUBCOPY_RM-y  := -R *ksymtab* -R *kcrctab*
 STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
   --prefix-symbols=__efistub_
 STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
@@ -68,17 +68,25 @@ STUBCOPY_RELOC-$(CONFIG_ARM64)  := R_AARCH64_ABS
 $(obj)/%.stub.o: $(obj)/%.o FORCE
$(call if_changed,stubcopy)
 
+#
+# Strip debug sections and some other sections that may legally contain
+# absolute relocations, so that we can inspect the remaining sections for
+# such relocations. If none are found, regenerate the output object, but
+# this time, use objcopy and leave all sections in place.
+#
 quiet_cmd_stubcopy = STUBCPY $@
-  cmd_stubcopy = if $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; then \
-$(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
+  cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \
+then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \
+then (echo >&2 "$@: absolute symbol references not allowed 
in the EFI stub"; \
+  rm -f $@; /bin/false); \
+else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi\
+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 \
-  -R ___ksymtab+sort -R ___kcrctab+sort
+STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub
+STUBCOPY_RM-$(CONFIG_ARM)  += -R ___ksymtab+sort -R ___kcrctab+sort
 STUBCOPY_RELOC-$(CONFIG_ARM)   := R_ARM_ABS


[tip:efi/core] efi: Use typed function pointers for the runtime services table

2017-02-01 Thread tip-bot for Ard Biesheuvel
Commit-ID:  c4c39c70c5fef43655019236bec8ba5e7273b868
Gitweb: http://git.kernel.org/tip/c4c39c70c5fef43655019236bec8ba5e7273b868
Author: Ard Biesheuvel 
AuthorDate: Tue, 31 Jan 2017 13:21:39 +
Committer:  Ingo Molnar 
CommitDate: Wed, 1 Feb 2017 08:45:45 +0100

efi: Use typed function pointers for the runtime services table

Instead of using void pointers, and casting them to correctly typed
function pointers upon use, declare the runtime services pointers
as function pointers using their respective prototypes, for which
typedefs are already available.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1485868902-20401-8-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 include/linux/efi.h | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f632bf..85e9fda 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -509,24 +509,6 @@ typedef struct {
u64 query_variable_info;
 } efi_runtime_services_64_t;
 
-typedef struct {
-   efi_table_hdr_t hdr;
-   void *get_time;
-   void *set_time;
-   void *get_wakeup_time;
-   void *set_wakeup_time;
-   void *set_virtual_address_map;
-   void *convert_pointer;
-   void *get_variable;
-   void *get_next_variable;
-   void *set_variable;
-   void *get_next_high_mono_count;
-   void *reset_system;
-   void *update_capsule;
-   void *query_capsule_caps;
-   void *query_variable_info;
-} efi_runtime_services_t;
-
 typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
 typedef efi_status_t efi_set_time_t (efi_time_t *tm);
 typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t 
*pending,
@@ -561,6 +543,24 @@ typedef efi_status_t efi_query_variable_store_t(u32 
attributes,
unsigned long size,
bool nonblocking);
 
+typedef struct {
+   efi_table_hdr_t hdr;
+   efi_get_time_t  *get_time;
+   efi_set_time_t  *set_time;
+   efi_get_wakeup_time_t   *get_wakeup_time;
+   efi_set_wakeup_time_t   *set_wakeup_time;
+   efi_set_virtual_address_map_t   *set_virtual_address_map;
+   void*convert_pointer;
+   efi_get_variable_t  *get_variable;
+   efi_get_next_variable_t *get_next_variable;
+   efi_set_variable_t  *set_variable;
+   efi_get_next_high_mono_count_t  *get_next_high_mono_count;
+   efi_reset_system_t  *reset_system;
+   efi_update_capsule_t*update_capsule;
+   efi_query_capsule_caps_t*query_capsule_caps;
+   efi_query_variable_info_t   *query_variable_info;
+} efi_runtime_services_t;
+
 void efi_native_runtime_setup(void);
 
 /*


[tip:efi/urgent] efi/libstub/arm*: Pass latest memory map to the kernel

2016-12-29 Thread tip-bot for Ard Biesheuvel
Commit-ID:  abfb7b686a3e5be27bf81db62f9c5c895b76f5d1
Gitweb: http://git.kernel.org/tip/abfb7b686a3e5be27bf81db62f9c5c895b76f5d1
Author: Ard Biesheuvel 
AuthorDate: Sat, 24 Dec 2016 13:59:23 +
Committer:  Ingo Molnar 
CommitDate: Wed, 28 Dec 2016 09:23:32 +0100

efi/libstub/arm*: Pass latest memory map to the kernel

As reported by James Morse, the current libstub code involving the
annotated memory map only works somewhat correctly by accident, due
to the fact that a pool allocation happens to be reused immediately,
retaining its former contents on most implementations of the
UEFI boot services.

Instead of juggling memory maps, which makes the code more complex than
it needs to be, simply put placeholder values into the FDT for the memory
map parameters, and only write the actual values after ExitBootServices()
has been called.

Reported-by: James Morse 
Signed-off-by: Ard Biesheuvel 
Cc: 
Cc: Jeffrey Hugo 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-...@vger.kernel.org
Fixes: ed9cc156c42f ("efi/libstub: Use efi_exit_boot_services() in FDT")
Link: 
http://lkml.kernel.org/r/1482587963-20183-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/efistub.h |  8 
 drivers/firmware/efi/libstub/fdt.c | 87 ++
 2 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index b98824e..0e2a96b 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -39,14 +39,6 @@ efi_status_t efi_file_close(void *handle);
 
 unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-   unsigned long orig_fdt_size,
-   void *fdt, int new_fdt_size, char *cmdline_ptr,
-   u64 initrd_addr, u64 initrd_size,
-   efi_memory_desc_t *memory_map,
-   unsigned long map_size, unsigned long desc_size,
-   u32 desc_ver);
-
 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
void *handle,
unsigned long *new_fdt_addr,
diff --git a/drivers/firmware/efi/libstub/fdt.c 
b/drivers/firmware/efi/libstub/fdt.c
index a6a9311..921dfa0 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -16,13 +16,10 @@
 
 #include "efistub.h"
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-   unsigned long orig_fdt_size,
-   void *fdt, int new_fdt_size, char *cmdline_ptr,
-   u64 initrd_addr, u64 initrd_size,
-   efi_memory_desc_t *memory_map,
-   unsigned long map_size, unsigned long desc_size,
-   u32 desc_ver)
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+  unsigned long orig_fdt_size,
+  void *fdt, int new_fdt_size, char *cmdline_ptr,
+  u64 initrd_addr, u64 initrd_size)
 {
int node, num_rsv;
int status;
@@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, 
void *orig_fdt,
if (status)
goto fdt_set_fail;
 
-   fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+   fdt_val64 = U64_MAX; /* placeholder */
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
 &fdt_val64,  sizeof(fdt_val64));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(map_size);
+   fdt_val32 = U32_MAX; /* placeholder */
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
 &fdt_val32,  sizeof(fdt_val32));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(desc_size);
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
 &fdt_val32, sizeof(fdt_val32));
if (status)
goto fdt_set_fail;
 
-   fdt_val32 = cpu_to_fdt32(desc_ver);
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
 &fdt_val32, sizeof(fdt_val32));
if (status)
@@ -148,6 +143,43 @@ fdt_set_fail:
return EFI_LOAD_ERROR;
 }
 
+static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
+{
+   int node = fdt_path_offset(fdt, "/chosen");
+   u64 fdt_val64;
+   u32 fdt_val32;
+   int err;
+
+   if (node < 0)
+   return EFI_LOAD_ERROR;
+
+   fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
+   err = fdt_setp

[tip:efi/core] efi/libstub: Make efi_random_alloc() allocate below 4 GB on 32-bit

2016-11-24 Thread tip-bot for Ard Biesheuvel
Commit-ID:  018edcfac4c3b140366ad51b0907f3becb5bb624
Gitweb: http://git.kernel.org/tip/018edcfac4c3b140366ad51b0907f3becb5bb624
Author: Ard Biesheuvel 
AuthorDate: Thu, 24 Nov 2016 18:02:23 +
Committer:  Ingo Molnar 
CommitDate: Fri, 25 Nov 2016 07:15:23 +0100

efi/libstub: Make efi_random_alloc() allocate below 4 GB on 32-bit

The UEFI stub executes in the context of the firmware, which identity
maps the available system RAM, which implies that only memory below
4 GB can be used for allocations on 32-bit architectures, even on [L]PAE
capable hardware.

So ignore any reported memory above 4 GB in efi_random_alloc(). This
also fixes a reported build problem on ARM under -Os, where the 64-bit
logical shift relies on a software routine that the ARM decompressor does
not provide.

A second [minor] issue is also fixed, where the '+ 1' is moved out of
the shift, where it belongs: the reason for its presence is that a
memory region where start == end should count as a single slot, given
that 'end' takes the desired size and alignment of the allocation into
account.

To clarify the code in this regard, rename start/end to 'first_slot' and
'last_slot', respectively, and introduce 'region_end' to describe the
last usable address of the current region.

Reported-by: Arnd Bergmann 
Signed-off-by: Ard Biesheuvel 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1480010543-25709-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/random.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 3a3feac..7e72954 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -45,19 +45,20 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t 
*md,
 unsigned long align_shift)
 {
unsigned long align = 1UL << align_shift;
-   u64 start, end;
+   u64 first_slot, last_slot, region_end;
 
if (md->type != EFI_CONVENTIONAL_MEMORY)
return 0;
 
-   start = round_up(md->phys_addr, align);
-   end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
-align);
+   region_end = min((u64)ULONG_MAX, md->phys_addr + 
md->num_pages*EFI_PAGE_SIZE - 1);
 
-   if (start > end)
+   first_slot = round_up(md->phys_addr, align);
+   last_slot = round_down(region_end - size + 1, align);
+
+   if (first_slot > last_slot)
return 0;
 
-   return (end - start + 1) >> align_shift;
+   return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1;
 }
 
 /*


[tip:efi/core] efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  568bc4e87033d232c5fd00d5b0cd22a2ccc04944
Gitweb: http://git.kernel.org/tip/568bc4e87033d232c5fd00d5b0cd22a2ccc04944
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:33 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:15 +0100

efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

Invoke the EFI_RNG_PROTOCOL protocol in the context of the stub and
install the Linux-specific RNG seed UEFI config table. This will be
picked up by the EFI routines in the core kernel to seed the kernel
entropy pool.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-6-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm-stub.c |  2 ++
 drivers/firmware/efi/libstub/efistub.h  |  2 ++
 drivers/firmware/efi/libstub/random.c   | 48 +
 include/linux/efi.h |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56..b4f7d78 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
if (status != EFI_SUCCESS)
pr_efi_err(sys_table, "Failed initrd from command line!\n");
 
+   efi_random_get_seed(sys_table);
+
new_fdt_addr = fdt_addr;
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index fe1f225..b98824e 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -71,4 +71,6 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
 #endif
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index f8e2e5a..3a3feac 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -143,3 +143,51 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
 
return status;
 }
+
+#define RANDOM_SEED_SIZE   32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+   efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+   efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+   efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+   struct efi_rng_protocol *rng;
+   struct linux_efi_random_seed *seed;
+   efi_status_t status;
+
+   status = efi_call_early(locate_protocol, &rng_proto, NULL,
+   (void **)&rng);
+   if (status != EFI_SUCCESS)
+   return status;
+
+   status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+   sizeof(*seed) + RANDOM_SEED_SIZE,
+   (void **)&seed);
+   if (status != EFI_SUCCESS)
+   return status;
+
+   status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+ seed->bits);
+   if (status == EFI_UNSUPPORTED)
+   /*
+* Use whatever algorithm we have available if the raw algorithm
+* is not implemented.
+*/
+   status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+ seed->bits);
+
+   if (status != EFI_SUCCESS)
+   goto err_freepool;
+
+   seed->size = RANDOM_SEED_SIZE;
+   status = efi_call_early(install_configuration_table, &rng_table_guid,
+   seed);
+   if (status != EFI_SUCCESS)
+   goto err_freepool;
+
+   return EFI_SUCCESS;
+
+err_freepool:
+   efi_call_early(free_pool, seed);
+   return status;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85e28b1..f5a821d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -589,6 +589,7 @@ void efi_native_runtime_setup(void);
 #define DEVICE_TREE_GUID   EFI_GUID(0xb1b621d5, 0xf19c, 
0x41a5,  0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
 #define EFI_PROPERTIES_TABLE_GUID  EFI_GUID(0x880aaca3, 0x4adc, 
0x4a04,  0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
 #define EFI_RNG_PROTOCOL_GUID  EFI_GUID(0x3152bca5, 0xeade, 
0x433d,  0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+#define EFI_RNG_ALGORITHM_RAW  EFI_GUID(0xe43176d7, 0xb6e8, 
0x4827,  0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
 #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID   E

[tip:efi/core] efi/libstub: Add random.c to ARM build

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  a6a144698db93a2c456d1e3811140cadef1ba0e3
Gitweb: http://git.kernel.org/tip/a6a144698db93a2c456d1e3811140cadef1ba0e3
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:32 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:15 +0100

efi/libstub: Add random.c to ARM build

Make random.c build for ARM by moving the fallback definition of
EFI_ALLOC_ALIGN to efistub.h, and replacing a division by a value
we know to be a power of 2 with a right shift (this is required since
ARM does not have any integer division helper routines in its decompressor)

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-5-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile  | 4 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c | 9 -
 drivers/firmware/efi/libstub/efistub.h | 9 +
 drivers/firmware/efi/libstub/random.c  | 8 +---
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d..6621b13 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c 
fdt_empty_tree.c fdt_sw.c sort.c
 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
 
-lib-$(CONFIG_EFI_ARMSTUB)  += arm-stub.o fdt.o string.o \
+lib-$(CONFIG_EFI_ARMSTUB)  += arm-stub.o fdt.o string.o random.o \
   $(patsubst %.c,lib-%.o,$(arm-deps))
 
 lib-$(CONFIG_ARM)  += arm32-stub.o
-lib-$(CONFIG_ARM64)+= arm64-stub.o random.o
+lib-$(CONFIG_ARM64)+= arm64-stub.o
 CFLAGS_arm64-stub.o:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 4b74bf8..757badc 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGNEFI_PAGE_SIZE
-#endif
-
 #define EFI_MMAP_NR_SLACK_SLOTS8
 
 struct file_info {
diff --git a/drivers/firmware/efi/libstub/efistub.h 
b/drivers/firmware/efi/libstub/efistub.h
index ee49cd2..fe1f225 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
  */
 #undef __init
 
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGNEFI_PAGE_SIZE
+#endif
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 0c9f58c..f8e2e5a 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 
 #include "efistub.h"
@@ -41,8 +42,9 @@ efi_status_t efi_get_random_bytes(efi_system_table_t 
*sys_table_arg,
  */
 static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
 unsigned long size,
-unsigned long align)
+unsigned long align_shift)
 {
+   unsigned long align = 1UL << align_shift;
u64 start, end;
 
if (md->type != EFI_CONVENTIONAL_MEMORY)
@@ -55,7 +57,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t 
*md,
if (start > end)
return 0;
 
-   return (end - start + 1) / align;
+   return (end - start + 1) >> align_shift;
 }
 
 /*
@@ -98,7 +100,7 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
efi_memory_desc_t *md = (void *)memory_map + map_offset;
unsigned long slots;
 
-   slots = get_entry_num_slots(md, size, align);
+   slots = get_entry_num_slots(md, size, ilog2(align));
MD_NUM_SLOTS(md) = slots;
total_slots += slots;
}


[tip:efi/core] MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  f135a176426fc643caf6480e3200f1733f58dbf6
Gitweb: http://git.kernel.org/tip/f135a176426fc643caf6480e3200f1733f58dbf6
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:30 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:14 +0100

MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem

Since I will be co-maintaining the EFI subsystem, it makes sense to
mention the ARM and arm64 EFI bits in the EFI section in MAINTAINERS
so that Matt, the list and I get cc'ed on proposed changes.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Acked-by: Will Deacon 
Acked-by: Russell King 
Cc: Linus Torvalds 
Cc: M: Matthew Garrett 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-3-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 MAINTAINERS | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 851b89b..afaf24f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4631,12 +4631,14 @@ L:  linux-...@vger.kernel.org
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
 S: Maintained
 F: Documentation/efi-stub.txt
-F: arch/ia64/kernel/efi.c
+F: arch/*/kernel/efi.c
 F: arch/x86/boot/compressed/eboot.[ch]
-F: arch/x86/include/asm/efi.h
+F: arch/*/include/asm/efi.h
 F: arch/x86/platform/efi/
 F: drivers/firmware/efi/
 F: include/linux/efi*.h
+F: arch/arm/boot/compressed/efi-header.S
+F: arch/arm64/kernel/efi-entry.S
 
 EFI VARIABLE FILESYSTEM
 M: Matthew Garrett 


[tip:efi/core] efi: Add support for seeding the RNG from a UEFI config table

2016-11-13 Thread tip-bot for Ard Biesheuvel
Commit-ID:  636259880a7e7d3446a707dddebc799da94bdd0b
Gitweb: http://git.kernel.org/tip/636259880a7e7d3446a707dddebc799da94bdd0b
Author: Ard Biesheuvel 
AuthorDate: Sat, 12 Nov 2016 21:32:31 +
Committer:  Ingo Molnar 
CommitDate: Sun, 13 Nov 2016 08:23:14 +0100

efi: Add support for seeding the RNG from a UEFI config table

Specify a Linux specific UEFI configuration table that carries some
random bits, and use the contents during early boot to seed the kernel's
random number generator. This allows much strong random numbers to be
generated early on.

The entropy is fed to the kernel using add_device_randomness(), which is
documented as being appropriate for being called very early.

Since UEFI configuration tables may also be consumed by kexec'd kernels,
register a reboot notifier that updates the seed in the table.

Note that the config table could be generated by the EFI stub or by any
other UEFI driver or application (e.g., GRUB), but the random seed table
GUID and the associated functionality should be considered an internal
kernel interface (unless it is promoted to ABI later on)

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Reviewed-by: Kees Cook 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-4-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/efi.c | 72 ++
 include/linux/efi.h|  8 ++
 2 files changed, 80 insertions(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a4944e2..9291480 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,7 +23,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
.esrt   = EFI_INVALID_TABLE_ADDR,
.properties_table   = EFI_INVALID_TABLE_ADDR,
.mem_attr_table = EFI_INVALID_TABLE_ADDR,
+   .rng_seed   = EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -440,6 +444,7 @@ static __initdata efi_config_table_type_t common_tables[] = 
{
{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
+   {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
{NULL_GUID, NULL, NULL},
 };
 
@@ -501,6 +506,29 @@ int __init efi_config_parse_tables(void *config_tables, 
int count, int sz,
pr_cont("\n");
set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
+   if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
+   struct linux_efi_random_seed *seed;
+   u32 size = 0;
+
+   seed = early_memremap(efi.rng_seed, sizeof(*seed));
+   if (seed != NULL) {
+   size = seed->size;
+   early_memunmap(seed, sizeof(*seed));
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   if (size > 0) {
+   seed = early_memremap(efi.rng_seed,
+ sizeof(*seed) + size);
+   if (seed != NULL) {
+   add_device_randomness(seed->bits, seed->size);
+   early_memunmap(seed, sizeof(*seed) + size);
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   }
+   }
+
/* Parse the EFI Properties table if it exists */
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
efi_properties_table_t *tbl;
@@ -824,3 +852,47 @@ int efi_status_to_err(efi_status_t status)
 
return err;
 }
+
+#ifdef CONFIG_KEXEC
+static int update_efi_random_seed(struct notifier_block *nb,
+ unsigned long code, void *unused)
+{
+   struct linux_efi_random_seed *seed;
+   u32 size = 0;
+
+   if (!kexec_in_progress)
+   return NOTIFY_DONE;
+
+   seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+   if (seed != NULL) {
+   size = min(seed->size, 32U);
+   memunmap(seed);
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   if (size > 0) {
+   seed = memremap(efi.rng_seed, sizeof(*seed) + size,
+   MEMREMAP_WB);
+   if (seed != NULL) {
+   seed->size = size;
+   get_random_bytes(seed->bits, seed->size);
+   memunmap(seed);
+   } else {
+   pr_err("Could not map UEFI random seed!\n");
+   }
+   }
+   return NOTIFY_DONE;
+}
+
+stati

[tip:efi/urgent] efi/arm: Fix absolute relocation detection for older toolchains

2016-10-19 Thread tip-bot for Ard Biesheuvel
Commit-ID:  b0dddf6c147e6fe61374d625c4bb2b7c52018639
Gitweb: http://git.kernel.org/tip/b0dddf6c147e6fe61374d625c4bb2b7c52018639
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Oct 2016 16:53:11 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 19 Oct 2016 14:49:44 +0200

efi/arm: Fix absolute relocation detection for older toolchains

When building the ARM kernel with CONFIG_EFI=y, the following build
error may occur when using a less recent version of binutils (2.23 or
older):

   STUBCPY drivers/firmware/efi/libstub/lib-sort.stub.o
  R_ARM_ABS32   sort
 0004 R_ARM_ABS32   __ksymtab_strings
 drivers/firmware/efi/libstub/lib-sort.stub.o: absolute symbol references not 
allowed in the EFI stub

(and when building with debug symbols, the list above is much longer, and
contains all the internal references between the .debug sections and the
actual code)

This issue is caused by the fact that objcopy v2.23 or earlier does not
support wildcards in its -R and -j options, which means the following
line from the Makefile:

  STUBCOPY_FLAGS-y  := -R .debug* -R *ksymtab* -R *kcrctab*

fails to take effect, leaving harmless absolute relocations in the binary
that are indistinguishable from relocations that may cause crashes at
runtime due to the fact that these relocations are resolved at link time
using the virtual address of the kernel, which is always different from
the address at which the EFI firmware loads and invokes the stub.

So, as a workaround, disable debug symbols explicitly when building the
stub for ARM, and strip the ksymtab and kcrctab symbols for the only
exported symbol we currently reuse in the stub, which is 'sort'.

Tested-by: Jon Hunter 
Signed-off-by: Ard Biesheuvel 
Reviewed-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1476805991-7160-2-git-send-email-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/Makefile | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index c069451..5e23e2d 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86)  += -m$(BITS) -D__KERNEL__ 
$(LINUX_INCLUDE) -O2 \
   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
-cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) \
+cflags-$(CONFIG_ARM)   := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \
   -fno-builtin -fpic -mno-single-pic-base
 
 cflags-$(CONFIG_EFI_ARMSTUB)   += -I$(srctree)/scripts/dtc/libfdt
@@ -79,5 +79,6 @@ quiet_cmd_stubcopy = STUBCPY $@
 # 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_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub \
+  -R ___ksymtab+sort -R ___kcrctab+sort
 STUBCOPY_RELOC-$(CONFIG_ARM)   := R_ARM_ABS


[tip:efi/core] MAINTAINERS: Add myself as EFI maintainer

2016-10-18 Thread tip-bot for Ard Biesheuvel
Commit-ID:  6026ed2fe258b61ea5aadd91a95c4f36a6dbe167
Gitweb: http://git.kernel.org/tip/6026ed2fe258b61ea5aadd91a95c4f36a6dbe167
Author: Ard Biesheuvel 
AuthorDate: Tue, 18 Oct 2016 15:33:11 +0100
Committer:  Ingo Molnar 
CommitDate: Tue, 18 Oct 2016 17:11:14 +0200

MAINTAINERS: Add myself as EFI maintainer

At the request of Matt, I am taking up co-maintainership of the EFI
subsystem. So add my name to the EFI section in MAINTAINERS, and
change the SCM tree reference to point to the new shared Git repo.

Signed-off-by: Ard Biesheuvel 
Acked-by: Will Deacon 
Acked-by: Matt Fleming 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20161018143318.15673-2-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 MAINTAINERS | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1cd38a7..6847ba8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4620,8 +4620,9 @@ F:sound/usb/misc/ua101.c
 
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M: Matt Fleming 
+M: Ard Biesheuvel 
 L: linux-...@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
 S: Maintained
 F: Documentation/efi-stub.txt
 F: arch/ia64/kernel/efi.c


[tip:efi/core] efi/arm-init: Reserve rather than unmap the memory map for ARM as well

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  249f7632162980b286f30166436471f8ba81fc1e
Gitweb: http://git.kernel.org/tip/249f7632162980b286f30166436471f8ba81fc1e
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:07:02 +0100
Committer:  Ingo Molnar 
CommitDate: Thu, 28 Apr 2016 11:34:05 +0200

efi/arm-init: Reserve rather than unmap the memory map for ARM as well

Now that ARM has a fully functional memremap() implementation, there is
no longer a need to remove the UEFI memory map from the linear mapping
in order to be able to create a permanent mapping for it using generic
code.

So remove the 'IS_ENABLED(CONFIG_ARM)' conditional we added in:

7cc8cbcf82d1 ("efi/arm64: Don't apply MEMBLOCK_NOMAP to UEFI memory map 
mapping")

... and revert to using memblock_reserve() for both ARM and arm64.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: Leif Lindholm 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-31-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/arm-init.c | 17 +++--
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 7a3318d..ef90f0c 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -244,20 +244,9 @@ void __init efi_init(void)
efi_memattr_init();
early_memunmap(efi.memmap.map, params.mmap_size);
 
-   if (IS_ENABLED(CONFIG_ARM)) {
-   /*
-* ARM currently does not allow ioremap_cache() to be called on
-* memory regions that are covered by struct page. So remove the
-* UEFI memory map from the linear mapping.
-*/
-   memblock_mark_nomap(params.mmap & PAGE_MASK,
-   PAGE_ALIGN(params.mmap_size +
-  (params.mmap & ~PAGE_MASK)));
-   } else {
-   memblock_reserve(params.mmap & PAGE_MASK,
-PAGE_ALIGN(params.mmap_size +
-   (params.mmap & ~PAGE_MASK)));
-   }
+   memblock_reserve(params.mmap & PAGE_MASK,
+PAGE_ALIGN(params.mmap_size +
+   (params.mmap & ~PAGE_MASK)));
 
init_screen_info();
 }


[tip:efi/core] efifb: Enable the efi-framebuffer platform driver for ARM and arm64

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  9822504c1fa5c557ea8776765f03fd16eb4de4c9
Gitweb: http://git.kernel.org/tip/9822504c1fa5c557ea8776765f03fd16eb4de4c9
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:56 +0100
Committer:  Ingo Molnar 
CommitDate: Thu, 28 Apr 2016 11:34:01 +0200

efifb: Enable the efi-framebuffer platform driver for ARM and arm64

Allows the efifb driver to be built for ARM and arm64. This simply involves
updating the Kconfig dependency expression, and supplying dummy versions of
efifb_setup_from_dmi().

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-25-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h   | 4 
 arch/arm64/include/asm/efi.h | 4 
 drivers/video/fbdev/Kconfig  | 2 +-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 25f8b11..b45fe39 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -67,6 +67,10 @@ void efi_virtmap_unload(void);
 struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
 void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
 
+static inline void efifb_setup_from_dmi(struct screen_info *si, const char 
*opt)
+{
+}
+
 /*
  * 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
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index fa09886..79dc8c2 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -59,6 +59,10 @@ int efi_create_mapping(struct mm_struct *mm, 
efi_memory_desc_t *md);
 #define alloc_screen_info(x...)&screen_info
 #define free_screen_info(x...)
 
+static inline void efifb_setup_from_dmi(struct screen_info *si, const char 
*opt)
+{
+}
+
 #define EFI_ALLOC_ALIGNSZ_64K
 
 /*
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 983280e..e5a391a 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -761,7 +761,7 @@ config FB_VESA
 
 config FB_EFI
bool "EFI-based Framebuffer Support"
-   depends on (FB = y) && X86 && EFI
+   depends on (FB = y) && !IA64 && EFI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT


[tip:efi/core] efi/arm/libstub: Make screen_info accessible to the UEFI stub

2016-04-28 Thread tip-bot for Ard Biesheuvel
Commit-ID:  801820bee9bccb7c156af2b95c7208f428a06ae7
Gitweb: http://git.kernel.org/tip/801820bee9bccb7c156af2b95c7208f428a06ae7
Author: Ard Biesheuvel 
AuthorDate: Mon, 25 Apr 2016 21:06:53 +0100
Committer:  Ingo Molnar 
CommitDate: Thu, 28 Apr 2016 11:33:59 +0200

efi/arm/libstub: Make screen_info accessible to the UEFI stub

In order to hand over the framebuffer described by the GOP protocol and
discovered by the UEFI stub, make struct screen_info accessible by the
stub. This involves allocating a loader data buffer and passing it to the
kernel proper via a UEFI Configuration Table, since the UEFI stub executes
in the context of the decompressor, and cannot access the kernel's copy of
struct screen_info directly.

Signed-off-by: Ard Biesheuvel 
Signed-off-by: Matt Fleming 
Cc: Borislav Petkov 
Cc: David Herrmann 
Cc: Mark Rutland 
Cc: Peter Jones 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: linux-...@vger.kernel.org
Link: 
http://lkml.kernel.org/r/1461614832-17633-22-git-send-email-m...@codeblueprint.co.uk
Signed-off-by: Ingo Molnar 
---
 arch/arm/include/asm/efi.h|  3 +++
 arch/arm/kernel/setup.c   |  3 ++-
 drivers/firmware/efi/arm-init.c   | 34 +++-
 drivers/firmware/efi/efi.c|  5 +++--
 drivers/firmware/efi/libstub/arm32-stub.c | 37 +++
 include/linux/efi.h   | 11 -
 6 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index dc30d89..25f8b11 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -64,6 +64,9 @@ void efi_virtmap_unload(void);
 #define __efi_call_early(f, ...)   f(__VA_ARGS__)
 #define efi_is_64bit() (false)
 
+struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
+void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
+
 /*
  * 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
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 2c4bea3..7d4e285 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -883,7 +883,8 @@ static void __init request_standard_resources(const struct 
machine_desc *mdesc)
request_resource(&ioport_resource, &lp2);
 }
 
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \
+defined(CONFIG_EFI)
 struct screen_info screen_info = {
  .orig_video_lines = 30,
  .orig_video_cols  = 80,
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 909d974..ac95dd8 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -11,12 +11,15 @@
  *
  */
 
+#define pr_fmt(fmt)"efi: " fmt
+
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -51,6 +54,32 @@ static phys_addr_t efi_to_phys(unsigned long addr)
return addr;
 }
 
+static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
+
+static __initdata efi_config_table_type_t arch_tables[] = {
+   {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table},
+   {NULL_GUID, NULL, NULL}
+};
+
+static void __init init_screen_info(void)
+{
+   struct screen_info *si;
+
+   if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
+   si = early_memremap_ro(screen_info_table, sizeof(*si));
+   if (!si) {
+   pr_err("Could not map screen_info config table\n");
+   return;
+   }
+   screen_info = *si;
+   early_memunmap(si, sizeof(*si));
+
+   /* dummycon on ARM needs non-zero values for columns/lines */
+   screen_info.orig_video_cols = 80;
+   screen_info.orig_video_lines = 25;
+   }
+}
+
 static int __init uefi_init(void)
 {
efi_char16_t *c16;
@@ -108,7 +137,8 @@ static int __init uefi_init(void)
goto out;
}
retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-sizeof(efi_config_table_t), NULL);
+sizeof(efi_config_table_t),
+arch_tables);
 
early_memunmap(config_tables, table_size);
 out:
@@ -223,4 +253,6 @@ void __init efi_init(void)
 PAGE_ALIGN(params.mmap_size +
(params.mmap & ~PAGE_MASK)));
}
+
+   init_screen_info();
 }
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 583e647..4991371 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -353,8 +353,9 @@ static __init int match_config_table(efi

  1   2   >