Skip to content

Commit 533568e

Browse files
ardbiesheuvelIngo Molnar
authored andcommitted
x86/boot/64: Use RIP_REL_REF() to access early_top_pgt[]
early_top_pgt[] is assigned from code that executes from a 1:1 mapping so it cannot use a plain access from C. Replace the use of fixup_pointer() with RIP_REL_REF(), which is better and simpler. For legibility and to align with the code that populates the lower page table levels, statically initialize the root level page table with an entry pointing to level3_kernel_pgt[], and overwrite it when needed to enable 5-level paging. Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent eb54c2a commit 533568e

File tree

2 files changed

+11
-13
lines changed

2 files changed

+11
-13
lines changed

arch/x86/kernel/head64.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static struct desc_struct startup_gdt[GDT_ENTRIES] __initdata = {
7777
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(DESC_DATA64, 0, 0xfffff),
7878
};
7979

80+
#ifdef CONFIG_X86_5LEVEL
8081
static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
8182
{
8283
return ptr - (void *)_text + (void *)physaddr;
@@ -87,7 +88,6 @@ static unsigned long __head *fixup_long(void *ptr, unsigned long physaddr)
8788
return fixup_pointer(ptr, physaddr);
8889
}
8990

90-
#ifdef CONFIG_X86_5LEVEL
9191
static unsigned int __head *fixup_int(void *ptr, unsigned long physaddr)
9292
{
9393
return fixup_pointer(ptr, physaddr);
@@ -165,14 +165,14 @@ static unsigned long __head sme_postprocess_startup(struct boot_params *bp, pmdv
165165
* doesn't have to generate PC-relative relocations when accessing globals from
166166
* that function. Clang actually does not generate them, which leads to
167167
* boot-time crashes. To work around this problem, every global pointer must
168-
* be adjusted using fixup_pointer().
168+
* be accessed using RIP_REL_REF().
169169
*/
170170
unsigned long __head __startup_64(unsigned long physaddr,
171171
struct boot_params *bp)
172172
{
173173
pmd_t (*early_pgts)[PTRS_PER_PMD] = RIP_REL_REF(early_dynamic_pgts);
174-
unsigned long load_delta, *p;
175174
unsigned long pgtable_flags;
175+
unsigned long load_delta;
176176
pgdval_t *pgd;
177177
p4dval_t *p4d;
178178
pudval_t *pud;
@@ -202,17 +202,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
202202

203203
/* Fixup the physical addresses in the page table */
204204

205-
pgd = fixup_pointer(early_top_pgt, physaddr);
206-
p = pgd + pgd_index(__START_KERNEL_map);
207-
if (la57)
208-
*p = (unsigned long)level4_kernel_pgt;
209-
else
210-
*p = (unsigned long)level3_kernel_pgt;
211-
*p += _PAGE_TABLE_NOENC - __START_KERNEL_map + load_delta;
205+
pgd = &RIP_REL_REF(early_top_pgt)->pgd;
206+
pgd[pgd_index(__START_KERNEL_map)] += load_delta;
212207

213208
if (la57) {
214-
p4d = fixup_pointer(level4_kernel_pgt, physaddr);
215-
p4d[511] += load_delta;
209+
p4d = (p4dval_t *)&RIP_REL_REF(level4_kernel_pgt);
210+
p4d[MAX_PTRS_PER_P4D - 1] += load_delta;
211+
212+
pgd[pgd_index(__START_KERNEL_map)] = (pgdval_t)p4d | _PAGE_TABLE_NOENC;
216213
}
217214

218215
RIP_REL_REF(level3_kernel_pgt)[PTRS_PER_PUD - 2].pud += load_delta;

arch/x86/kernel/head_64.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,8 @@ SYM_CODE_END(vc_no_ghcb)
624624
.balign 4
625625

626626
SYM_DATA_START_PTI_ALIGNED(early_top_pgt)
627-
.fill 512,8,0
627+
.fill 511,8,0
628+
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
628629
.fill PTI_USER_PGD_FILL,8,0
629630
SYM_DATA_END(early_top_pgt)
630631

0 commit comments

Comments
 (0)