Skip to content

Commit ec1c66a

Browse files
mdrothsuryasaimadhu
authored andcommitted
x86/compressed/64: Detect/setup SEV/SME features earlier during boot
With upcoming SEV-SNP support, SEV-related features need to be initialized earlier during boot, at the same point the initial #VC handler is set up, so that the SEV-SNP CPUID table can be utilized during the initial feature checks. Also, SEV-SNP feature detection will rely on EFI helper functions to scan the EFI config table for the Confidential Computing blob, and so would need to be implemented at least partially in C. Currently set_sev_encryption_mask() is used to initialize the sev_status and sme_me_mask globals that advertise what SEV/SME features are available in a guest. Rename it to sev_enable() to better reflect that (SME is only enabled in the case of SEV guests in the boot/compressed kernel), and move it to just after the stage1 #VC handler is set up so that it can be used to initialize SEV-SNP as well in future patches. While at it, re-implement it as C code so that all SEV feature detection can be better consolidated with upcoming SEV-SNP feature detection, which will also be in C. The 32-bit entry path remains unchanged, as it never relied on the set_sev_encryption_mask() initialization to begin with. [ bp: Massage commit message. ] Signed-off-by: Michael Roth <[email protected]> Signed-off-by: Brijesh Singh <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 950d005 commit ec1c66a

File tree

4 files changed

+60
-53
lines changed

4 files changed

+60
-53
lines changed

arch/x86/boot/compressed/head_64.S

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,11 @@ SYM_FUNC_START(startup_32)
189189
subl $32, %eax /* Encryption bit is always above bit 31 */
190190
bts %eax, %edx /* Set encryption mask for page tables */
191191
/*
192-
* Mark SEV as active in sev_status so that startup32_check_sev_cbit()
193-
* will do a check. The sev_status memory will be fully initialized
194-
* with the contents of MSR_AMD_SEV_STATUS later in
195-
* set_sev_encryption_mask(). For now it is sufficient to know that SEV
196-
* is active.
192+
* Set MSR_AMD64_SEV_ENABLED_BIT in sev_status so that
193+
* startup32_check_sev_cbit() will do a check. sev_enable() will
194+
* initialize sev_status with all the bits reported by
195+
* MSR_AMD_SEV_STATUS later, but only MSR_AMD64_SEV_ENABLED_BIT
196+
* needs to be set for now.
197197
*/
198198
movl $1, rva(sev_status)(%ebp)
199199
1:
@@ -447,6 +447,23 @@ SYM_CODE_START(startup_64)
447447
call load_stage1_idt
448448
popq %rsi
449449

450+
#ifdef CONFIG_AMD_MEM_ENCRYPT
451+
/*
452+
* Now that the stage1 interrupt handlers are set up, #VC exceptions from
453+
* CPUID instructions can be properly handled for SEV-ES guests.
454+
*
455+
* For SEV-SNP, the CPUID table also needs to be set up in advance of any
456+
* CPUID instructions being issued, so go ahead and do that now via
457+
* sev_enable(), which will also handle the rest of the SEV-related
458+
* detection/setup to ensure that has been done in advance of any dependent
459+
* code.
460+
*/
461+
pushq %rsi
462+
movq %rsi, %rdi /* real mode address */
463+
call sev_enable
464+
popq %rsi
465+
#endif
466+
450467
/*
451468
* paging_prepare() sets up the trampoline and checks if we need to
452469
* enable 5-level paging.
@@ -558,17 +575,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
558575
shrq $3, %rcx
559576
rep stosq
560577

561-
/*
562-
* If running as an SEV guest, the encryption mask is required in the
563-
* page-table setup code below. When the guest also has SEV-ES enabled
564-
* set_sev_encryption_mask() will cause #VC exceptions, but the stage2
565-
* handler can't map its GHCB because the page-table is not set up yet.
566-
* So set up the encryption mask here while still on the stage1 #VC
567-
* handler. Then load stage2 IDT and switch to the kernel's own
568-
* page-table.
569-
*/
570578
pushq %rsi
571-
call set_sev_encryption_mask
572579
call load_stage2_idt
573580

574581
/* Pass boot_params to initialize_identity_maps() */

arch/x86/boot/compressed/mem_encrypt.S

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -187,42 +187,6 @@ SYM_CODE_END(startup32_vc_handler)
187187
.code64
188188

189189
#include "../../kernel/sev_verify_cbit.S"
190-
SYM_FUNC_START(set_sev_encryption_mask)
191-
#ifdef CONFIG_AMD_MEM_ENCRYPT
192-
push %rbp
193-
push %rdx
194-
195-
movq %rsp, %rbp /* Save current stack pointer */
196-
197-
call get_sev_encryption_bit /* Get the encryption bit position */
198-
testl %eax, %eax
199-
jz .Lno_sev_mask
200-
201-
bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
202-
203-
/*
204-
* Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
205-
* get_sev_encryption_bit() because this function is 32-bit code and
206-
* shared between 64-bit and 32-bit boot path.
207-
*/
208-
movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
209-
rdmsr
210-
211-
/* Store MSR value in sev_status */
212-
shlq $32, %rdx
213-
orq %rdx, %rax
214-
movq %rax, sev_status(%rip)
215-
216-
.Lno_sev_mask:
217-
movq %rbp, %rsp /* Restore original stack pointer */
218-
219-
pop %rdx
220-
pop %rbp
221-
#endif
222-
223-
xor %rax, %rax
224-
RET
225-
SYM_FUNC_END(set_sev_encryption_mask)
226190

227191
.data
228192

arch/x86/boot/compressed/misc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ static inline void console_init(void)
120120
{ }
121121
#endif
122122

123-
void set_sev_encryption_mask(void);
124-
125123
#ifdef CONFIG_AMD_MEM_ENCRYPT
124+
void sev_enable(struct boot_params *bp);
126125
void sev_es_shutdown_ghcb(void);
127126
extern bool sev_es_check_ghcb_fault(unsigned long address);
128127
#else
128+
static inline void sev_enable(struct boot_params *bp) { }
129129
static inline void sev_es_shutdown_ghcb(void) { }
130130
static inline bool sev_es_check_ghcb_fault(unsigned long address)
131131
{

arch/x86/boot/compressed/sev.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,39 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
201201
else if (result != ES_RETRY)
202202
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
203203
}
204+
205+
void sev_enable(struct boot_params *bp)
206+
{
207+
unsigned int eax, ebx, ecx, edx;
208+
struct msr m;
209+
210+
/* Check for the SME/SEV support leaf */
211+
eax = 0x80000000;
212+
ecx = 0;
213+
native_cpuid(&eax, &ebx, &ecx, &edx);
214+
if (eax < 0x8000001f)
215+
return;
216+
217+
/*
218+
* Check for the SME/SEV feature:
219+
* CPUID Fn8000_001F[EAX]
220+
* - Bit 0 - Secure Memory Encryption support
221+
* - Bit 1 - Secure Encrypted Virtualization support
222+
* CPUID Fn8000_001F[EBX]
223+
* - Bits 5:0 - Pagetable bit position used to indicate encryption
224+
*/
225+
eax = 0x8000001f;
226+
ecx = 0;
227+
native_cpuid(&eax, &ebx, &ecx, &edx);
228+
/* Check whether SEV is supported */
229+
if (!(eax & BIT(1)))
230+
return;
231+
232+
/* Set the SME mask if this is an SEV guest. */
233+
boot_rdmsr(MSR_AMD64_SEV, &m);
234+
sev_status = m.q;
235+
if (!(sev_status & MSR_AMD64_SEV_ENABLED))
236+
return;
237+
238+
sme_me_mask = BIT_ULL(ebx & 0x3f);
239+
}

0 commit comments

Comments
 (0)