]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.20/arm64-mm-efi-account-for-gicv3-lpi-tables-in-static-.patch
patches for 4.20
[thirdparty/kernel/stable-queue.git] / queue-4.20 / arm64-mm-efi-account-for-gicv3-lpi-tables-in-static-.patch
1 From 28ada55266abae290a58e2662f38b6f73e9a1dc5 Mon Sep 17 00:00:00 2001
2 From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
3 Date: Tue, 19 Feb 2019 20:03:12 +0100
4 Subject: arm64, mm, efi: Account for GICv3 LPI tables in static memblock
5 reserve table
6
7 Commit 8a5b403d71affa098009cc3dff1b2c45113021ad upstream.
8
9 In the irqchip and EFI code, we have what basically amounts to a quirk
10 to work around a peculiarity in the GICv3 architecture, which permits
11 the system memory address of LPI tables to be programmable only once
12 after a CPU reset. This means kexec kernels must use the same memory
13 as the first kernel, and thus ensure that this memory has not been
14 given out for other purposes by the time the ITS init code runs, which
15 is not very early for secondary CPUs.
16
17 On systems with many CPUs, these reservations could overflow the
18 memblock reservation table, and this was addressed in commit:
19
20 eff896288872 ("efi/arm: Defer persistent reservations until after paging_init()")
21
22 However, this turns out to have made things worse, since the allocation
23 of page tables and heap space for the resized memblock reservation table
24 itself may overwrite the regions we are attempting to reserve, which may
25 cause all kinds of corruption, also considering that the ITS will still
26 be poking bits into that memory in response to incoming MSIs.
27
28 So instead, let's grow the static memblock reservation table on such
29 systems so it can accommodate these reservations at an earlier time.
30 This will permit us to revert the above commit in a subsequent patch.
31
32 [ mingo: Minor cleanups. ]
33
34 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
35 Acked-by: Mike Rapoport <rppt@linux.ibm.com>
36 Acked-by: Will Deacon <will.deacon@arm.com>
37 Acked-by: Marc Zyngier <marc.zyngier@arm.com>
38 Cc: Andrew Morton <akpm@linux-foundation.org>
39 Cc: Linus Torvalds <torvalds@linux-foundation.org>
40 Cc: Peter Zijlstra <peterz@infradead.org>
41 Cc: Thomas Gleixner <tglx@linutronix.de>
42 Cc: linux-arm-kernel@lists.infradead.org
43 Cc: linux-efi@vger.kernel.org
44 Link: http://lkml.kernel.org/r/20190215123333.21209-2-ard.biesheuvel@linaro.org
45 Signed-off-by: Ingo Molnar <mingo@kernel.org>
46 [ ardb: Double the size of the slack to account for the lack of an
47 optimization that was introduced in mainline after the release
48 of v4.20. ]
49 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
50 Signed-off-by: Sasha Levin <sashal@kernel.org>
51 ---
52 arch/arm64/include/asm/memory.h | 11 +++++++++++
53 include/linux/memblock.h | 3 ---
54 mm/memblock.c | 11 +++++++++--
55 3 files changed, 20 insertions(+), 5 deletions(-)
56
57 diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
58 index 778af0b7f7fd5..c67081301035f 100644
59 --- a/arch/arm64/include/asm/memory.h
60 +++ b/arch/arm64/include/asm/memory.h
61 @@ -303,6 +303,17 @@ static inline void *phys_to_virt(phys_addr_t x)
62 #define virt_addr_valid(kaddr) (_virt_addr_is_linear(kaddr) && \
63 _virt_addr_valid(kaddr))
64
65 +/*
66 + * Given that the GIC architecture permits ITS implementations that can only be
67 + * configured with a LPI table address once, GICv3 systems with many CPUs may
68 + * end up reserving a lot of different regions after a kexec for their LPI
69 + * tables (one per CPU), as we are forced to reuse the same memory after kexec
70 + * (and thus reserve it persistently with EFI beforehand)
71 + */
72 +#if defined(CONFIG_EFI) && defined(CONFIG_ARM_GIC_V3_ITS)
73 +# define INIT_MEMBLOCK_RESERVED_REGIONS (INIT_MEMBLOCK_REGIONS + 2*(NR_CPUS + 1))
74 +#endif
75 +
76 #include <asm-generic/memory_model.h>
77
78 #endif
79 diff --git a/include/linux/memblock.h b/include/linux/memblock.h
80 index 3ef3086ed52f9..ecff64ff365d4 100644
81 --- a/include/linux/memblock.h
82 +++ b/include/linux/memblock.h
83 @@ -29,9 +29,6 @@ extern unsigned long max_pfn;
84 */
85 extern unsigned long long max_possible_pfn;
86
87 -#define INIT_MEMBLOCK_REGIONS 128
88 -#define INIT_PHYSMEM_REGIONS 4
89 -
90 /**
91 * enum memblock_flags - definition of memory region attributes
92 * @MEMBLOCK_NONE: no special request
93 diff --git a/mm/memblock.c b/mm/memblock.c
94 index f45a049532fea..74ac4f89018ab 100644
95 --- a/mm/memblock.c
96 +++ b/mm/memblock.c
97 @@ -26,6 +26,13 @@
98
99 #include "internal.h"
100
101 +#define INIT_MEMBLOCK_REGIONS 128
102 +#define INIT_PHYSMEM_REGIONS 4
103 +
104 +#ifndef INIT_MEMBLOCK_RESERVED_REGIONS
105 +# define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
106 +#endif
107 +
108 /**
109 * DOC: memblock overview
110 *
111 @@ -92,7 +99,7 @@ unsigned long max_pfn;
112 unsigned long long max_possible_pfn;
113
114 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
115 -static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
116 +static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
117 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
118 static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
119 #endif
120 @@ -105,7 +112,7 @@ struct memblock memblock __initdata_memblock = {
121
122 .reserved.regions = memblock_reserved_init_regions,
123 .reserved.cnt = 1, /* empty dummy entry */
124 - .reserved.max = INIT_MEMBLOCK_REGIONS,
125 + .reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS,
126 .reserved.name = "reserved",
127
128 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
129 --
130 2.19.1
131