]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.34/efi-arm-arm64-allow-setvirtualaddressmap-to-be-omitt.patch
Linux 4.14.111
[thirdparty/kernel/stable-queue.git] / releases / 4.19.34 / efi-arm-arm64-allow-setvirtualaddressmap-to-be-omitt.patch
1 From 920be3d562e543740252b3b94134c94f941d91cf Mon Sep 17 00:00:00 2001
2 From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
3 Date: Sat, 2 Feb 2019 10:41:16 +0100
4 Subject: efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted
5
6 [ Upstream commit 4e46c2a956215482418d7b315749fb1b6c6bc224 ]
7
8 The UEFI spec revision 2.7 errata A section 8.4 has the following to
9 say about the virtual memory runtime services:
10
11 "This section contains function definitions for the virtual memory
12 support that may be optionally used by an operating system at runtime.
13 If an operating system chooses to make EFI runtime service calls in a
14 virtual addressing mode instead of the flat physical mode, then the
15 operating system must use the services in this section to switch the
16 EFI runtime services from flat physical addressing to virtual
17 addressing."
18
19 So it is pretty clear that calling SetVirtualAddressMap() is entirely
20 optional, and so there is no point in doing so unless it achieves
21 anything useful for us.
22
23 This is not the case for 64-bit ARM. The identity mapping used by the
24 firmware is arbitrarily converted into another permutation of userland
25 addresses (i.e., bits [63:48] cleared), and the runtime code could easily
26 deal with the original layout in exactly the same way as it deals with
27 the converted layout. However, due to constraints related to page size
28 differences if the OS is not running with 4k pages, and related to
29 systems that may expose the individual sections of PE/COFF runtime
30 modules as different memory regions, creating the virtual layout is a
31 bit fiddly, and requires us to sort the memory map and reason about
32 adjacent regions with identical memory types etc etc.
33
34 So the obvious fix is to stop calling SetVirtualAddressMap() altogether
35 on arm64 systems. However, to avoid surprises, which are notoriously
36 hard to diagnose when it comes to OS<->firmware interactions, let's
37 start by making it an opt-out feature, and implement support for the
38 'efi=novamap' kernel command line parameter on ARM and arm64 systems.
39
40 ( Note that 32-bit ARM generally does require SetVirtualAddressMap() to be
41 used, given that the physical memory map and the kernel virtual address
42 map are not guaranteed to be non-overlapping like on arm64. However,
43 having support for efi=novamap,noruntime on 32-bit ARM, combined with
44 the recently proposed support for earlycon=efifb, is likely to be useful
45 to diagnose boot issues on such systems if they have no accessible serial
46 port. )
47
48 Tested-by: Jeffrey Hugo <jhugo@codeaurora.org>
49 Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org>
50 Tested-by: Lee Jones <lee.jones@linaro.org>
51 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
52 Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
53 Cc: Alexander Graf <agraf@suse.de>
54 Cc: Borislav Petkov <bp@alien8.de>
55 Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
56 Cc: Leif Lindholm <leif.lindholm@linaro.org>
57 Cc: Linus Torvalds <torvalds@linux-foundation.org>
58 Cc: Matt Fleming <matt@codeblueprint.co.uk>
59 Cc: Peter Jones <pjones@redhat.com>
60 Cc: Peter Zijlstra <peterz@infradead.org>
61 Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
62 Cc: Thomas Gleixner <tglx@linutronix.de>
63 Cc: linux-efi@vger.kernel.org
64 Link: http://lkml.kernel.org/r/20190202094119.13230-8-ard.biesheuvel@linaro.org
65 Signed-off-by: Ingo Molnar <mingo@kernel.org>
66 Signed-off-by: Sasha Levin <sashal@kernel.org>
67 ---
68 drivers/firmware/efi/libstub/arm-stub.c | 5 +++++
69 drivers/firmware/efi/libstub/efi-stub-helper.c | 10 ++++++++++
70 drivers/firmware/efi/libstub/efistub.h | 1 +
71 drivers/firmware/efi/libstub/fdt.c | 3 +++
72 4 files changed, 19 insertions(+)
73
74 diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
75 index 6920033de6d4..6c09644d620e 100644
76 --- a/drivers/firmware/efi/libstub/arm-stub.c
77 +++ b/drivers/firmware/efi/libstub/arm-stub.c
78 @@ -340,6 +340,11 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
79 paddr = in->phys_addr;
80 size = in->num_pages * EFI_PAGE_SIZE;
81
82 + if (novamap()) {
83 + in->virt_addr = in->phys_addr;
84 + continue;
85 + }
86 +
87 /*
88 * Make the mapping compatible with 64k pages: this allows
89 * a 4k page size kernel to kexec a 64k page size kernel and
90 diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
91 index e94975f4655b..442f51c2a53d 100644
92 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
93 +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
94 @@ -34,6 +34,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
95
96 static int __section(.data) __nokaslr;
97 static int __section(.data) __quiet;
98 +static int __section(.data) __novamap;
99
100 int __pure nokaslr(void)
101 {
102 @@ -43,6 +44,10 @@ int __pure is_quiet(void)
103 {
104 return __quiet;
105 }
106 +int __pure novamap(void)
107 +{
108 + return __novamap;
109 +}
110
111 #define EFI_MMAP_NR_SLACK_SLOTS 8
112
113 @@ -482,6 +487,11 @@ efi_status_t efi_parse_options(char const *cmdline)
114 __chunk_size = -1UL;
115 }
116
117 + if (!strncmp(str, "novamap", 7)) {
118 + str += strlen("novamap");
119 + __novamap = 1;
120 + }
121 +
122 /* Group words together, delimited by "," */
123 while (*str && *str != ' ' && *str != ',')
124 str++;
125 diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
126 index 32799cf039ef..337b52c4702c 100644
127 --- a/drivers/firmware/efi/libstub/efistub.h
128 +++ b/drivers/firmware/efi/libstub/efistub.h
129 @@ -27,6 +27,7 @@
130
131 extern int __pure nokaslr(void);
132 extern int __pure is_quiet(void);
133 +extern int __pure novamap(void);
134
135 #define pr_efi(sys_table, msg) do { \
136 if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
137 diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
138 index 0c0d2312f4a8..dba296a44f4e 100644
139 --- a/drivers/firmware/efi/libstub/fdt.c
140 +++ b/drivers/firmware/efi/libstub/fdt.c
141 @@ -327,6 +327,9 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
142 if (status == EFI_SUCCESS) {
143 efi_set_virtual_address_map_t *svam;
144
145 + if (novamap())
146 + return EFI_SUCCESS;
147 +
148 /* Install the new virtual address map */
149 svam = sys_table->runtime->set_virtual_address_map;
150 status = svam(runtime_entry_count * desc_size, desc_size,
151 --
152 2.19.1
153