Skip to content

Commit 0925dda

Browse files
Baoquan HeKAGA-KOKO
authored andcommitted
x86/mm/KASLR: Use only one PUD entry for real mode trampoline
The current code builds identity mapping for the real mode trampoline by borrowing page tables from the direct mapping section if KASLR is enabled. It copies present entries of the first PUD table in 4-level paging mode, or the first P4D table in 5-level paging mode. However, there's only a very small area under low 1 MB reserved for the real mode trampoline in reserve_real_mode() so it makes no sense to build up a really large mapping for it. Reduce it to one PUD (1GB) entry. This matches the randomization granularity in 4-level paging mode and allows to change the randomization granularity in 5-level paging mode from 512GB to 1GB later. [ tglx: Massaged changelog and comments ] Signed-off-by: Baoquan He <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Kirill A. Shutemov <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 5e7a8ca commit 0925dda

File tree

1 file changed

+37
-47
lines changed

1 file changed

+37
-47
lines changed

arch/x86/mm/kaslr.c

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -147,74 +147,64 @@ void __init kernel_randomize_memory(void)
147147

148148
static void __meminit init_trampoline_pud(void)
149149
{
150-
unsigned long paddr, paddr_next;
150+
pud_t *pud_page_tramp, *pud, *pud_tramp;
151+
p4d_t *p4d_page_tramp, *p4d, *p4d_tramp;
152+
unsigned long paddr, vaddr;
151153
pgd_t *pgd;
152-
pud_t *pud_page, *pud_page_tramp;
153-
int i;
154154

155155
pud_page_tramp = alloc_low_page();
156156

157+
/*
158+
* There are two mappings for the low 1MB area, the direct mapping
159+
* and the 1:1 mapping for the real mode trampoline:
160+
*
161+
* Direct mapping: virt_addr = phys_addr + PAGE_OFFSET
162+
* 1:1 mapping: virt_addr = phys_addr
163+
*/
157164
paddr = 0;
158-
pgd = pgd_offset_k((unsigned long)__va(paddr));
159-
pud_page = (pud_t *) pgd_page_vaddr(*pgd);
160-
161-
for (i = pud_index(paddr); i < PTRS_PER_PUD; i++, paddr = paddr_next) {
162-
pud_t *pud, *pud_tramp;
163-
unsigned long vaddr = (unsigned long)__va(paddr);
165+
vaddr = (unsigned long)__va(paddr);
166+
pgd = pgd_offset_k(vaddr);
164167

165-
pud_tramp = pud_page_tramp + pud_index(paddr);
166-
pud = pud_page + pud_index(vaddr);
167-
paddr_next = (paddr & PUD_MASK) + PUD_SIZE;
168-
169-
*pud_tramp = *pud;
170-
}
168+
p4d = p4d_offset(pgd, vaddr);
169+
pud = pud_offset(p4d, vaddr);
171170

172-
set_pgd(&trampoline_pgd_entry,
173-
__pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
174-
}
175-
176-
static void __meminit init_trampoline_p4d(void)
177-
{
178-
unsigned long paddr, paddr_next;
179-
pgd_t *pgd;
180-
p4d_t *p4d_page, *p4d_page_tramp;
181-
int i;
171+
pud_tramp = pud_page_tramp + pud_index(paddr);
172+
*pud_tramp = *pud;
182173

183-
p4d_page_tramp = alloc_low_page();
184-
185-
paddr = 0;
186-
pgd = pgd_offset_k((unsigned long)__va(paddr));
187-
p4d_page = (p4d_t *) pgd_page_vaddr(*pgd);
188-
189-
for (i = p4d_index(paddr); i < PTRS_PER_P4D; i++, paddr = paddr_next) {
190-
p4d_t *p4d, *p4d_tramp;
191-
unsigned long vaddr = (unsigned long)__va(paddr);
174+
if (pgtable_l5_enabled()) {
175+
p4d_page_tramp = alloc_low_page();
192176

193177
p4d_tramp = p4d_page_tramp + p4d_index(paddr);
194-
p4d = p4d_page + p4d_index(vaddr);
195-
paddr_next = (paddr & P4D_MASK) + P4D_SIZE;
196178

197-
*p4d_tramp = *p4d;
198-
}
179+
set_p4d(p4d_tramp,
180+
__p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
199181

200-
set_pgd(&trampoline_pgd_entry,
201-
__pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
182+
set_pgd(&trampoline_pgd_entry,
183+
__pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
184+
} else {
185+
set_pgd(&trampoline_pgd_entry,
186+
__pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
187+
}
202188
}
203189

204190
/*
205-
* Create PGD aligned trampoline table to allow real mode initialization
206-
* of additional CPUs. Consume only 1 low memory page.
191+
* The real mode trampoline, which is required for bootstrapping CPUs
192+
* occupies only a small area under the low 1MB. See reserve_real_mode()
193+
* for details.
194+
*
195+
* If KASLR is disabled the first PGD entry of the direct mapping is copied
196+
* to map the real mode trampoline.
197+
*
198+
* If KASLR is enabled, copy only the PUD which covers the low 1MB
199+
* area. This limits the randomization granularity to 1GB for both 4-level
200+
* and 5-level paging.
207201
*/
208202
void __meminit init_trampoline(void)
209203
{
210-
211204
if (!kaslr_memory_enabled()) {
212205
init_trampoline_default();
213206
return;
214207
}
215208

216-
if (pgtable_l5_enabled())
217-
init_trampoline_p4d();
218-
else
219-
init_trampoline_pud();
209+
init_trampoline_pud();
220210
}

0 commit comments

Comments
 (0)