mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
- Remove redundant GHCB initialization guards in the SEV page state and SVSM
call paths now that the GHCB helpers handle early-boot fallback internally
- Skip SNP initialization in the CCP driver immediately when the preparation
step fails rather than proceeding to an operation that will certainly fail
- Abort SNP preparation and return an error when not all CPUs are online,
since the firmware enforces that every CPU enables SNP and will fail init if
not
- Simplify the VMM communication exception entry path by replacing separate
kernel and user mode macros with a single handler that dispatches based on
the current privilege level
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmowORwACgkQEsHwGGHe
VUqphg//VVXH3Svs2K5+++WQvavXDVwB5B+W4KA5WYYz3I77nmXgb2++aGSptGfy
ckC8ESFwyRWRh6aaOMtWGdbTQryS9e72sqiZEphbAZCe2XwR/A0N60uUktUCGm1W
3ce/VRkeTJI4LTkx3g+VSPTGzDpqfbwwTAJQZt8Ny8kooQCUH+VA7JvyLOYFvyTg
4NtjP2MVTzjE1io9SpZdSAbG/wdn7l7cFI+xC1QXYKZBzHSK5e4vUwnSGd86lrCa
2Q+zVcGcA7w2J6Obx4dNde5Y7AhGmYnhDxbFtNp9iUmG/o75LpVvP+8v7wshSGiL
HjTsRy5tkjrF9MUNXZd6cwFQ9gs6wWAwxXUsPtfs2N8R6Ve0W9aR49MUp1sEFuKm
hNgRLA7idSQ0RUSrL4f3c7Zx8ML6nXM2yRgE+4UTbr5/untHCqYunHelEIy1uay5
2vbqJ5VzT+pfY9qZn+q41AM2E1+ZzLmXFuGPBSOU4G+dU0CoVo+OUrsKZh8Q/4Ff
DajeiTW1+UidZyk2nb+HoX3DIa7jsUBeA3IGAQv8wK31jj3XhKwJTFPwPGkdjcpw
iR35vPzZFh0JLm+AHGrjgLI2+DkWEKl3j6lxI94UxsugaqkywtPZ5XJhJC54YHS9
iOwlpZK37eYy6zITx1+bwfzrW4oSsEZyYHkNgYJhU/RW4MrNJiU=
=Wq1K
-----END PGP SIGNATURE-----
Merge tag 'x86_sev_for_v7.2_rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip
Pull x86 SEV updates from Borislav Petkov:
- Remove redundant GHCB initialization guards in the SEV page state and
SVSM call paths now that the GHCB helpers handle early-boot fallback
internally
- Skip SNP initialization in the CCP driver immediately when the
preparation step fails rather than proceeding to an operation that
will certainly fail
- Abort SNP preparation and return an error when not all CPUs are
online, since the firmware enforces that every CPU enables SNP and
will fail init if not
- Simplify the VMM communication exception entry path by replacing
separate kernel and user mode macros with a single handler that
dispatches based on the current privilege level
* tag 'x86_sev_for_v7.2_rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip:
x86/sev: Remove redundant ghcbs_initialized checks around __sev_{get,put}_ghcb()
crypto/ccp: Skip SNP_INIT if preparation fails
x86/sev: Do not initialize SNP if missing CPUs
x86/entry: Zap the #VC entry user and kernel macros
This commit is contained in:
commit
c61f479852
|
|
@ -367,17 +367,13 @@ static unsigned long __set_pages_state(struct snp_psc_desc *data, unsigned long
|
|||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (sev_cfg.ghcbs_initialized)
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
else
|
||||
ghcb = boot_ghcb;
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
|
||||
/* Invoke the hypervisor to perform the page state changes */
|
||||
if (!ghcb || vmgexit_psc(ghcb, data))
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
|
||||
|
||||
if (sev_cfg.ghcbs_initialized)
|
||||
__sev_put_ghcb(&state);
|
||||
__sev_put_ghcb(&state);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ void svsm_pval_pages(struct snp_psc_desc *desc);
|
|||
int svsm_perform_call_protocol(struct svsm_call *call);
|
||||
bool snp_svsm_vtpm_probe(void);
|
||||
|
||||
noinstr void kernel_exc_vmm_communication(struct pt_regs *regs, unsigned long error_code);
|
||||
noinstr void user_exc_vmm_communication(struct pt_regs *regs, unsigned long error_code);
|
||||
|
||||
static inline u64 sev_es_rd_ghcb_msr(void)
|
||||
{
|
||||
return native_rdmsrq(MSR_AMD64_SEV_ES_GHCB);
|
||||
|
|
|
|||
|
|
@ -121,8 +121,10 @@ noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
|
|||
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
if (!sev_cfg.ghcbs_initialized)
|
||||
if (!sev_cfg.ghcbs_initialized) {
|
||||
state->ghcb = NULL;
|
||||
return boot_ghcb;
|
||||
}
|
||||
|
||||
data = this_cpu_read(runtime_data);
|
||||
ghcb = &data->ghcb_page;
|
||||
|
|
|
|||
|
|
@ -74,20 +74,14 @@ int svsm_perform_call_protocol(struct svsm_call *call)
|
|||
|
||||
flags = native_local_irq_save();
|
||||
|
||||
if (sev_cfg.ghcbs_initialized)
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
else if (boot_ghcb)
|
||||
ghcb = boot_ghcb;
|
||||
else
|
||||
ghcb = NULL;
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
|
||||
do {
|
||||
ret = ghcb ? svsm_perform_ghcb_protocol(ghcb, call)
|
||||
: __pi_svsm_perform_msr_protocol(call);
|
||||
} while (ret == -EAGAIN);
|
||||
|
||||
if (sev_cfg.ghcbs_initialized)
|
||||
__sev_put_ghcb(&state);
|
||||
__sev_put_ghcb(&state);
|
||||
|
||||
native_local_irq_restore(flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -954,7 +954,7 @@ static __always_inline bool vc_is_db(unsigned long error_code)
|
|||
* Runtime #VC exception handler when raised from kernel mode. Runs in NMI mode
|
||||
* and will panic when an error happens.
|
||||
*/
|
||||
DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication)
|
||||
noinstr void kernel_exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
irqentry_state_t irq_state;
|
||||
|
||||
|
|
@ -1006,7 +1006,7 @@ DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication)
|
|||
* Runtime #VC exception handler when raised from user mode. Runs in IRQ mode
|
||||
* and will kill the current task with SIGBUS when an error happens.
|
||||
*/
|
||||
DEFINE_IDTENTRY_VC_USER(exc_vmm_communication)
|
||||
noinstr void user_exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
/*
|
||||
* Handle #DB before calling into !noinstr code to avoid recursive #DB.
|
||||
|
|
@ -1032,6 +1032,14 @@ DEFINE_IDTENTRY_VC_USER(exc_vmm_communication)
|
|||
irqentry_exit_to_user_mode(regs);
|
||||
}
|
||||
|
||||
DEFINE_IDTENTRY_RAW_ERRORCODE(exc_vmm_communication)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return user_exc_vmm_communication(regs, error_code);
|
||||
else
|
||||
return kernel_exc_vmm_communication(regs, error_code);
|
||||
}
|
||||
|
||||
bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long exit_code = regs->orig_ax;
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ SYM_CODE_START(\asmsym)
|
|||
|
||||
movq %rsp, %rdi /* pt_regs pointer */
|
||||
|
||||
call kernel_\cfunc
|
||||
call \cfunc
|
||||
|
||||
/*
|
||||
* No need to switch back to the IST stack. The current stack is either
|
||||
|
|
@ -503,7 +503,7 @@ SYM_CODE_START(\asmsym)
|
|||
|
||||
/* Switch to the regular task stack */
|
||||
.Lfrom_usermode_switch_stack_\@:
|
||||
idtentry_body user_\cfunc, has_error_code=1
|
||||
idtentry_body \cfunc, has_error_code=1
|
||||
|
||||
_ASM_NOKPROBE(\asmsym)
|
||||
SYM_CODE_END(\asmsym)
|
||||
|
|
|
|||
|
|
@ -177,16 +177,6 @@ static noinstr void fred_extint(struct pt_regs *regs)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||
noinstr void exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return user_exc_vmm_communication(regs, error_code);
|
||||
else
|
||||
return kernel_exc_vmm_communication(regs, error_code);
|
||||
}
|
||||
#endif
|
||||
|
||||
static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
/* Optimize for #PF. That's the only exception which matters performance wise */
|
||||
|
|
|
|||
|
|
@ -340,17 +340,14 @@ static __always_inline void __##func(struct pt_regs *regs)
|
|||
__visible void noist_##func(struct pt_regs *regs)
|
||||
|
||||
/**
|
||||
* DECLARE_IDTENTRY_VC - Declare functions for the VC entry point
|
||||
* DECLARE_IDTENTRY_VC - Declare a function for the VC entry point
|
||||
* @vector: Vector number (ignored for C)
|
||||
* @func: Function name of the entry point
|
||||
*
|
||||
* Maps to DECLARE_IDTENTRY_RAW_ERRORCODE, but declares also the
|
||||
* safe_stack C handler.
|
||||
* Maps to DECLARE_IDTENTRY_RAW_ERRORCODE.
|
||||
*/
|
||||
#define DECLARE_IDTENTRY_VC(vector, func) \
|
||||
DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func); \
|
||||
__visible noinstr void kernel_##func(struct pt_regs *regs, unsigned long error_code); \
|
||||
__visible noinstr void user_##func(struct pt_regs *regs, unsigned long error_code)
|
||||
DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func);
|
||||
|
||||
/**
|
||||
* DEFINE_IDTENTRY_IST - Emit code for IST entry points
|
||||
|
|
@ -391,26 +388,6 @@ static __always_inline void __##func(struct pt_regs *regs)
|
|||
#define DEFINE_IDTENTRY_DF(func) \
|
||||
DEFINE_IDTENTRY_RAW_ERRORCODE(func)
|
||||
|
||||
/**
|
||||
* DEFINE_IDTENTRY_VC_KERNEL - Emit code for VMM communication handler
|
||||
* when raised from kernel mode
|
||||
* @func: Function name of the entry point
|
||||
*
|
||||
* Maps to DEFINE_IDTENTRY_RAW_ERRORCODE
|
||||
*/
|
||||
#define DEFINE_IDTENTRY_VC_KERNEL(func) \
|
||||
DEFINE_IDTENTRY_RAW_ERRORCODE(kernel_##func)
|
||||
|
||||
/**
|
||||
* DEFINE_IDTENTRY_VC_USER - Emit code for VMM communication handler
|
||||
* when raised from user mode
|
||||
* @func: Function name of the entry point
|
||||
*
|
||||
* Maps to DEFINE_IDTENTRY_RAW_ERRORCODE
|
||||
*/
|
||||
#define DEFINE_IDTENTRY_VC_USER(func) \
|
||||
DEFINE_IDTENTRY_RAW_ERRORCODE(user_##func)
|
||||
|
||||
#else /* CONFIG_X86_64 */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ static inline void snp_leak_pages(u64 pfn, unsigned int pages)
|
|||
{
|
||||
__snp_leak_pages(pfn, pages, true);
|
||||
}
|
||||
void snp_prepare(void);
|
||||
int snp_prepare(void);
|
||||
void snp_shutdown(void);
|
||||
#else
|
||||
static inline bool snp_probe_rmptable_info(void) { return false; }
|
||||
|
|
@ -679,7 +679,7 @@ static inline void __snp_leak_pages(u64 pfn, unsigned int npages, bool dump_rmp)
|
|||
static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
|
||||
static inline void kdump_sev_callback(void) { }
|
||||
static inline void snp_fixup_e820_tables(void) {}
|
||||
static inline void snp_prepare(void) {}
|
||||
static inline int snp_prepare(void) { return -ENODEV; }
|
||||
static inline void snp_shutdown(void) {}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -511,8 +511,9 @@ static void clear_hsave_pa(void *arg)
|
|||
wrmsrq(MSR_VM_HSAVE_PA, 0);
|
||||
}
|
||||
|
||||
void snp_prepare(void)
|
||||
int snp_prepare(void)
|
||||
{
|
||||
int ret;
|
||||
u64 val;
|
||||
|
||||
/*
|
||||
|
|
@ -521,12 +522,20 @@ void snp_prepare(void)
|
|||
*/
|
||||
rdmsrq(MSR_AMD64_SYSCFG, val);
|
||||
if (val & MSR_AMD64_SYSCFG_SNP_EN)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
clear_rmp();
|
||||
|
||||
cpus_read_lock();
|
||||
|
||||
if (!cpumask_equal(cpu_online_mask, cpu_present_mask)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
pr_warn("SNP init failed: not all CPUs online. (%*pbl online <-> %*pbl present masks).\n",
|
||||
cpumask_pr_args(cpu_online_mask),
|
||||
cpumask_pr_args(cpu_present_mask));
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* MtrrFixDramModEn is not shared between threads on a core,
|
||||
* therefore it must be set on all CPUs prior to enabling SNP.
|
||||
|
|
@ -537,7 +546,12 @@ void snp_prepare(void)
|
|||
/* SNP_INIT requires MSR_VM_HSAVE_PA to be cleared on all CPUs. */
|
||||
on_each_cpu(clear_hsave_pa, NULL, 1);
|
||||
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
cpus_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_MODULES(snp_prepare, "ccp");
|
||||
|
||||
|
|
|
|||
|
|
@ -1374,7 +1374,9 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
snp_prepare();
|
||||
rc = snp_prepare();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Starting in SNP firmware v1.52, the SNP_INIT_EX command takes a list
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user