Skip to content

Commit 74d8d9d

Browse files
joergroedelsuryasaimadhu
authored andcommitted
x86/sev-es: Setup an early #VC handler
Setup an early handler for #VC exceptions. There is no GHCB mapped yet, so just re-use the vc_no_ghcb_handler(). It can only handle CPUID exit-codes, but that should be enough to get the kernel through verify_cpu() and __startup_64() until it runs on virtual addresses. Signed-off-by: Joerg Roedel <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> [ boot failure Error: kernel_ident_mapping_init() failed. ] Reported-by: kernel test robot <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent f980f9c commit 74d8d9d

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

arch/x86/include/asm/sev-es.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,7 @@ static inline u64 lower_bits(u64 val, unsigned int bits)
7373
return (val & mask);
7474
}
7575

76+
/* Early IDT entry points for #VC handler */
77+
extern void vc_no_ghcb(void);
78+
7679
#endif

arch/x86/kernel/head64.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <asm/desc.h>
4141
#include <asm/extable.h>
4242
#include <asm/trapnr.h>
43+
#include <asm/sev-es.h>
4344

4445
/*
4546
* Manage page tables very early on.
@@ -540,12 +541,34 @@ static struct desc_ptr bringup_idt_descr = {
540541
.address = 0, /* Set at runtime */
541542
};
542543

544+
static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
545+
{
546+
#ifdef CONFIG_AMD_MEM_ENCRYPT
547+
struct idt_data data;
548+
gate_desc desc;
549+
550+
init_idt_data(&data, n, handler);
551+
idt_init_desc(&desc, &data);
552+
native_write_idt_entry(idt, n, &desc);
553+
#endif
554+
}
555+
543556
/* This runs while still in the direct mapping */
544557
static void startup_64_load_idt(unsigned long physbase)
545558
{
546559
struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
560+
gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
561+
562+
563+
if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
564+
void *handler;
565+
566+
/* VMM Communication Exception */
567+
handler = fixup_pointer(vc_no_ghcb, physbase);
568+
set_bringup_idt_handler(idt, X86_TRAP_VC, handler);
569+
}
547570

548-
desc->address = (unsigned long)fixup_pointer(bringup_idt_table, physbase);
571+
desc->address = (unsigned long)idt;
549572
native_load_idt(desc);
550573
}
551574

arch/x86/kernel/head_64.S

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,36 @@ SYM_CODE_START_LOCAL(early_idt_handler_common)
348348
jmp restore_regs_and_return_to_kernel
349349
SYM_CODE_END(early_idt_handler_common)
350350

351+
#ifdef CONFIG_AMD_MEM_ENCRYPT
352+
/*
353+
* VC Exception handler used during very early boot. The
354+
* early_idt_handler_array can't be used because it returns via the
355+
* paravirtualized INTERRUPT_RETURN and pv-ops don't work that early.
356+
*
357+
* This handler will end up in the .init.text section and not be
358+
* available to boot secondary CPUs.
359+
*/
360+
SYM_CODE_START_NOALIGN(vc_no_ghcb)
361+
UNWIND_HINT_IRET_REGS offset=8
362+
363+
/* Build pt_regs */
364+
PUSH_AND_CLEAR_REGS
365+
366+
/* Call C handler */
367+
movq %rsp, %rdi
368+
movq ORIG_RAX(%rsp), %rsi
369+
call do_vc_no_ghcb
370+
371+
/* Unwind pt_regs */
372+
POP_REGS
373+
374+
/* Remove Error Code */
375+
addq $8, %rsp
376+
377+
/* Pure iret required here - don't use INTERRUPT_RETURN */
378+
iretq
379+
SYM_CODE_END(vc_no_ghcb)
380+
#endif
351381

352382
#define SYM_DATA_START_PAGE_ALIGNED(name) \
353383
SYM_START(name, SYM_L_GLOBAL, .balign PAGE_SIZE)

0 commit comments

Comments
 (0)