Skip to content

Commit 0f7f7b6

Browse files
committed
x86/sme: Move early SME kernel encryption handling into .head.text
JIRA: https://issues.redhat.com/browse/RHEL-39439 Conflicts: Missing cd0d9d9 (x86/boot: Move mem_encrypt= parsing to the decompressor) that moves the parsing logic into the decompressor. There are more common x86 boot code changes that should all go together. Moving SME and SEV handling into .head.text are included together in this series only. commit 48204ab Author: Ard Biesheuvel <ardb@kernel.org> Date: Tue Feb 27 16:19:15 2024 +0100 x86/sme: Move early SME kernel encryption handling into .head.text The .head.text section is the initial primary entrypoint of the core kernel, and is entered with the CPU executing from a 1:1 mapping of memory. Such code must never access global variables using absolute references, as these are based on the kernel virtual mapping which is not active yet at this point. Given that the SME startup code is also called from this early execution context, move it into .head.text as well. This will allow more thorough build time checks in the future to ensure that early startup code only uses RIP-relative references to global variables. Also replace some occurrences of __pa_symbol() [which relies on the compiler generating an absolute reference, which is not guaranteed] and an open coded RIP-relative access with RIP_REL_REF(). Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://lore.kernel.org/r/20240227151907.387873-18-ardb+git@google.com Signed-off-by: Bandan Das <bsd@redhat.com>
1 parent 6022907 commit 0f7f7b6

File tree

2 files changed

+22
-29
lines changed

2 files changed

+22
-29
lines changed

arch/x86/include/asm/mem_encrypt.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ void __init sme_unmap_bootdata(char *real_mode_data);
4747

4848
void __init sme_early_init(void);
4949

50-
void __init sme_encrypt_kernel(struct boot_params *bp);
51-
void __init sme_enable(struct boot_params *bp);
50+
void sme_encrypt_kernel(struct boot_params *bp);
51+
void sme_enable(struct boot_params *bp);
5252

5353
int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
5454
int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size);
@@ -81,8 +81,8 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
8181

8282
static inline void __init sme_early_init(void) { }
8383

84-
static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
85-
static inline void __init sme_enable(struct boot_params *bp) { }
84+
static inline void sme_encrypt_kernel(struct boot_params *bp) { }
85+
static inline void sme_enable(struct boot_params *bp) { }
8686

8787
static inline void sev_es_init_vc_handling(void) { }
8888

arch/x86/mm/mem_encrypt_identity.c

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/mem_encrypt.h>
4242
#include <linux/cc_platform.h>
4343

44+
#include <asm/init.h>
4445
#include <asm/setup.h>
4546
#include <asm/sections.h>
4647
#include <asm/cmdline.h>
@@ -95,10 +96,11 @@ struct sme_populate_pgd_data {
9596
*/
9697
static char sme_workarea[2 * PMD_SIZE] __section(".init.scratch");
9798

99+
98100
static char sme_cmdline_arg[] __initdata = "mem_encrypt";
99101
static char sme_cmdline_on[] __initdata = "on";
100102

101-
static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
103+
static void __head sme_clear_pgd(struct sme_populate_pgd_data *ppd)
102104
{
103105
unsigned long pgd_start, pgd_end, pgd_size;
104106
pgd_t *pgd_p;
@@ -113,7 +115,7 @@ static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
113115
memset(pgd_p, 0, pgd_size);
114116
}
115117

116-
static pud_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
118+
static pud_t __head *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
117119
{
118120
pgd_t *pgd;
119121
p4d_t *p4d;
@@ -150,7 +152,7 @@ static pud_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
150152
return pud;
151153
}
152154

153-
static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
155+
static void __head sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
154156
{
155157
pud_t *pud;
156158
pmd_t *pmd;
@@ -166,7 +168,7 @@ static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
166168
set_pmd(pmd, __pmd(ppd->paddr | ppd->pmd_flags));
167169
}
168170

169-
static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
171+
static void __head sme_populate_pgd(struct sme_populate_pgd_data *ppd)
170172
{
171173
pud_t *pud;
172174
pmd_t *pmd;
@@ -192,7 +194,7 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
192194
set_pte(pte, __pte(ppd->paddr | ppd->pte_flags));
193195
}
194196

195-
static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
197+
static void __head __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
196198
{
197199
while (ppd->vaddr < ppd->vaddr_end) {
198200
sme_populate_pgd_large(ppd);
@@ -202,7 +204,7 @@ static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
202204
}
203205
}
204206

205-
static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
207+
static void __head __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
206208
{
207209
while (ppd->vaddr < ppd->vaddr_end) {
208210
sme_populate_pgd(ppd);
@@ -212,7 +214,7 @@ static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
212214
}
213215
}
214216

215-
static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
217+
static void __head __sme_map_range(struct sme_populate_pgd_data *ppd,
216218
pmdval_t pmd_flags, pteval_t pte_flags)
217219
{
218220
unsigned long vaddr_end;
@@ -236,22 +238,22 @@ static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
236238
__sme_map_range_pte(ppd);
237239
}
238240

239-
static void __init sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
241+
static void __head sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
240242
{
241243
__sme_map_range(ppd, PMD_FLAGS_ENC, PTE_FLAGS_ENC);
242244
}
243245

244-
static void __init sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
246+
static void __head sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
245247
{
246248
__sme_map_range(ppd, PMD_FLAGS_DEC, PTE_FLAGS_DEC);
247249
}
248250

249-
static void __init sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
251+
static void __head sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
250252
{
251253
__sme_map_range(ppd, PMD_FLAGS_DEC_WP, PTE_FLAGS_DEC_WP);
252254
}
253255

254-
static unsigned long __init sme_pgtable_calc(unsigned long len)
256+
static unsigned long __head sme_pgtable_calc(unsigned long len)
255257
{
256258
unsigned long entries = 0, tables = 0;
257259

@@ -288,7 +290,7 @@ static unsigned long __init sme_pgtable_calc(unsigned long len)
288290
return entries + tables;
289291
}
290292

291-
void __init sme_encrypt_kernel(struct boot_params *bp)
293+
void __head sme_encrypt_kernel(struct boot_params *bp)
292294
{
293295
unsigned long workarea_start, workarea_end, workarea_len;
294296
unsigned long execute_start, execute_end, execute_len;
@@ -323,9 +325,8 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
323325
* memory from being cached.
324326
*/
325327

326-
/* Physical addresses gives us the identity mapped virtual addresses */
327-
kernel_start = __pa_symbol(_text);
328-
kernel_end = ALIGN(__pa_symbol(_end), PMD_SIZE);
328+
kernel_start = (unsigned long)RIP_REL_REF(_text);
329+
kernel_end = ALIGN((unsigned long)RIP_REL_REF(_end), PMD_SIZE);
329330
kernel_len = kernel_end - kernel_start;
330331

331332
initrd_start = 0;
@@ -342,14 +343,6 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
342343
}
343344
#endif
344345

345-
/*
346-
* We're running identity mapped, so we must obtain the address to the
347-
* SME encryption workarea using rip-relative addressing.
348-
*/
349-
asm ("lea sme_workarea(%%rip), %0"
350-
: "=r" (workarea_start)
351-
: "p" (sme_workarea));
352-
353346
/*
354347
* Calculate required number of workarea bytes needed:
355348
* executable encryption area size:
@@ -359,7 +352,7 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
359352
* pagetable structures for the encryption of the kernel
360353
* pagetable structures for workarea (in case not currently mapped)
361354
*/
362-
execute_start = workarea_start;
355+
execute_start = workarea_start = (unsigned long)RIP_REL_REF(sme_workarea);
363356
execute_end = execute_start + (PAGE_SIZE * 2) + PMD_SIZE;
364357
execute_len = execute_end - execute_start;
365358

@@ -502,7 +495,7 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
502495
native_write_cr3(__native_read_cr3());
503496
}
504497

505-
void __init sme_enable(struct boot_params *bp)
498+
void __head sme_enable(struct boot_params *bp)
506499
{
507500
const char *cmdline_ptr, *cmdline_arg, *cmdline_on;
508501
unsigned int eax, ebx, ecx, edx;

0 commit comments

Comments
 (0)