diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-16 05:57:30 +0530 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-16 05:57:30 +0530 |
| commit | c61f479852493fd2cf5ca754e42ac272b1e2d2c5 (patch) | |
| tree | 8f99e3a4c0fbecc54eb2f0631d0c58e344c5c26c /arch | |
| parent | 97cc7dc16aaee163e15173009c063fc9cd42b5ff (diff) | |
| parent | 9d8460a1c7a6b0f2dc6302e5d0f31d4e8c2a7913 (diff) | |
| download | ath-c61f479852493fd2cf5ca754e42ac272b1e2d2c5.tar.gz | |
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
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/coco/sev/core.c | 8 | ||||
| -rw-r--r-- | arch/x86/coco/sev/internal.h | 3 | ||||
| -rw-r--r-- | arch/x86/coco/sev/noinstr.c | 4 | ||||
| -rw-r--r-- | arch/x86/coco/sev/svsm.c | 10 | ||||
| -rw-r--r-- | arch/x86/coco/sev/vc-handle.c | 12 | ||||
| -rw-r--r-- | arch/x86/entry/entry_64.S | 4 | ||||
| -rw-r--r-- | arch/x86/entry/entry_fred.c | 10 | ||||
| -rw-r--r-- | arch/x86/include/asm/idtentry.h | 29 | ||||
| -rw-r--r-- | arch/x86/include/asm/sev.h | 4 | ||||
| -rw-r--r-- | arch/x86/virt/svm/sev.c | 18 |
10 files changed, 43 insertions, 59 deletions
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 7ed3da998489d..ecd77d3217f3c 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -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); diff --git a/arch/x86/coco/sev/internal.h b/arch/x86/coco/sev/internal.h index b1d0c66a651a6..b9632c0fc3916 100644 --- a/arch/x86/coco/sev/internal.h +++ b/arch/x86/coco/sev/internal.h @@ -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); diff --git a/arch/x86/coco/sev/noinstr.c b/arch/x86/coco/sev/noinstr.c index 5afd663a1c217..e1e03f12fc7bb 100644 --- a/arch/x86/coco/sev/noinstr.c +++ b/arch/x86/coco/sev/noinstr.c @@ -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; diff --git a/arch/x86/coco/sev/svsm.c b/arch/x86/coco/sev/svsm.c index 2acf4a76afe7a..916d62cd17dc7 100644 --- a/arch/x86/coco/sev/svsm.c +++ b/arch/x86/coco/sev/svsm.c @@ -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); diff --git a/arch/x86/coco/sev/vc-handle.c b/arch/x86/coco/sev/vc-handle.c index d98b5c08ef00d..96b62b49b2b53 100644 --- a/arch/x86/coco/sev/vc-handle.c +++ b/arch/x86/coco/sev/vc-handle.c @@ -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; diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 42447b1e1dffa..c6d996593f329 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -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) diff --git a/arch/x86/entry/entry_fred.c b/arch/x86/entry/entry_fred.c index fbe2d10dd737d..fb3594ddf731f 100644 --- a/arch/x86/entry/entry_fred.c +++ b/arch/x86/entry/entry_fred.c @@ -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 */ diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index 42bf6a58ec368..20f5487024042 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -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 */ /** diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 09e605c85de4c..594cfa19cbd4b 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -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 diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index 41f76f15caa13..8bcdce98f6dce 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -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"); |
