Commit 74d8d9d5 authored by Joerg Roedel's avatar Joerg Roedel Committed by Borislav Petkov
Browse files

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: default avatarJoerg Roedel <jroedel@suse.de>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
[ boot failure Error: kernel_ident_mapping_init() failed. ]
Reported-by: default avatarkernel test robot <lkp@intel.com>
Link: https://lkml.kernel.org/r/20200908123517.GA3764@8bytes.org
parent f980f9c3
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -73,4 +73,7 @@ static inline u64 lower_bits(u64 val, unsigned int bits)
	return (val & mask);
}

/* Early IDT entry points for #VC handler */
extern void vc_no_ghcb(void);

#endif
+24 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <asm/desc.h>
#include <asm/extable.h>
#include <asm/trapnr.h>
#include <asm/sev-es.h>

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

static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
{
#ifdef CONFIG_AMD_MEM_ENCRYPT
	struct idt_data data;
	gate_desc desc;

	init_idt_data(&data, n, handler);
	idt_init_desc(&desc, &data);
	native_write_idt_entry(idt, n, &desc);
#endif
}

/* This runs while still in the direct mapping */
static void startup_64_load_idt(unsigned long physbase)
{
	struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
	gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);


	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
		void *handler;

		/* VMM Communication Exception */
		handler = fixup_pointer(vc_no_ghcb, physbase);
		set_bringup_idt_handler(idt, X86_TRAP_VC, handler);
	}

	desc->address = (unsigned long)fixup_pointer(bringup_idt_table, physbase);
	desc->address = (unsigned long)idt;
	native_load_idt(desc);
}

+30 −0
Original line number Diff line number Diff line
@@ -348,6 +348,36 @@ SYM_CODE_START_LOCAL(early_idt_handler_common)
	jmp restore_regs_and_return_to_kernel
SYM_CODE_END(early_idt_handler_common)

#ifdef CONFIG_AMD_MEM_ENCRYPT
/*
 * VC Exception handler used during very early boot. The
 * early_idt_handler_array can't be used because it returns via the
 * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early.
 *
 * This handler will end up in the .init.text section and not be
 * available to boot secondary CPUs.
 */
SYM_CODE_START_NOALIGN(vc_no_ghcb)
	UNWIND_HINT_IRET_REGS offset=8

	/* Build pt_regs */
	PUSH_AND_CLEAR_REGS

	/* Call C handler */
	movq    %rsp, %rdi
	movq	ORIG_RAX(%rsp), %rsi
	call    do_vc_no_ghcb

	/* Unwind pt_regs */
	POP_REGS

	/* Remove Error Code */
	addq    $8, %rsp

	/* Pure iret required here - don't use INTERRUPT_RETURN */
	iretq
SYM_CODE_END(vc_no_ghcb)
#endif

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