Merge tag 'x86_sev_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 SEV updates from Borislav Petkov:

- Export sev_es_ghcb_hv_call() so that HyperV Isolation VMs can use it
too

- Non-urgent fixes and cleanups

* tag 'x86_sev_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/sev: Expose sev_es_ghcb_hv_call() for use by HyperV
x86/sev: Allow #VC exceptions on the VC2 stack
x86/sev: Fix stack type check in vc_switch_off_ist()
x86/sme: Use #define USE_EARLY_PGTABLE_L5 in mem_encrypt_identity.c
x86/sev: Carve out HV call's return value verification

+80 -39
+6
arch/x86/include/asm/sev.h
··· 53 53 54 54 struct real_mode_header; 55 55 enum stack_type; 56 + struct ghcb; 56 57 57 58 /* Early IDT entry points for #VC handler */ 58 59 extern void vc_no_ghcb(void); ··· 82 81 __sev_es_nmi_complete(); 83 82 } 84 83 extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); 84 + extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, 85 + bool set_ghcb_msr, 86 + struct es_em_ctxt *ctxt, 87 + u64 exit_code, u64 exit_info_1, 88 + u64 exit_info_2); 85 89 #else 86 90 static inline void sev_es_ist_enter(struct pt_regs *regs) { } 87 91 static inline void sev_es_ist_exit(void) { }
+40 -28
arch/x86/kernel/sev-shared.c
··· 94 94 ctxt->regs->ip += ctxt->insn.length; 95 95 } 96 96 97 - static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, 98 - struct es_em_ctxt *ctxt, 99 - u64 exit_code, u64 exit_info_1, 100 - u64 exit_info_2) 97 + static enum es_result verify_exception_info(struct ghcb *ghcb, struct es_em_ctxt *ctxt) 101 98 { 102 - enum es_result ret; 99 + u32 ret; 103 100 104 - /* Fill in protocol and format specifiers */ 105 - ghcb->protocol_version = GHCB_PROTOCOL_MAX; 106 - ghcb->ghcb_usage = GHCB_DEFAULT_USAGE; 101 + ret = ghcb->save.sw_exit_info_1 & GENMASK_ULL(31, 0); 102 + if (!ret) 103 + return ES_OK; 107 104 108 - ghcb_set_sw_exit_code(ghcb, exit_code); 109 - ghcb_set_sw_exit_info_1(ghcb, exit_info_1); 110 - ghcb_set_sw_exit_info_2(ghcb, exit_info_2); 111 - 112 - sev_es_wr_ghcb_msr(__pa(ghcb)); 113 - VMGEXIT(); 114 - 115 - if ((ghcb->save.sw_exit_info_1 & 0xffffffff) == 1) { 105 + if (ret == 1) { 116 106 u64 info = ghcb->save.sw_exit_info_2; 117 107 unsigned long v; 118 108 ··· 114 124 ((v == X86_TRAP_GP) || (v == X86_TRAP_UD)) && 115 125 ((info & SVM_EVTINJ_TYPE_MASK) == SVM_EVTINJ_TYPE_EXEPT)) { 116 126 ctxt->fi.vector = v; 127 + 117 128 if (info & SVM_EVTINJ_VALID_ERR) 118 129 ctxt->fi.error_code = info >> 32; 119 - ret = ES_EXCEPTION; 120 - } else { 121 - ret = ES_VMM_ERROR; 130 + 131 + return ES_EXCEPTION; 122 132 } 123 - } else if (ghcb->save.sw_exit_info_1 & 0xffffffff) { 124 - ret = ES_VMM_ERROR; 125 - } else { 126 - ret = ES_OK; 127 133 } 128 134 129 - return ret; 135 + return ES_VMM_ERROR; 136 + } 137 + 138 + enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, bool set_ghcb_msr, 139 + struct es_em_ctxt *ctxt, u64 exit_code, 140 + u64 exit_info_1, u64 exit_info_2) 141 + { 142 + /* Fill in protocol and format specifiers */ 143 + ghcb->protocol_version = GHCB_PROTOCOL_MAX; 144 + ghcb->ghcb_usage = GHCB_DEFAULT_USAGE; 145 + 146 + ghcb_set_sw_exit_code(ghcb, exit_code); 147 + ghcb_set_sw_exit_info_1(ghcb, exit_info_1); 148 + ghcb_set_sw_exit_info_2(ghcb, exit_info_2); 149 + 150 + /* 151 + * Hyper-V unenlightened guests use a paravisor for communicating and 152 + * GHCB pages are being allocated and set up by that paravisor. Linux 153 + * should not change the GHCB page's physical address. 154 + */ 155 + if (set_ghcb_msr) 156 + sev_es_wr_ghcb_msr(__pa(ghcb)); 157 + 158 + VMGEXIT(); 159 + 160 + return verify_exception_info(ghcb, ctxt); 130 161 } 131 162 132 163 /* ··· 424 413 */ 425 414 sw_scratch = __pa(ghcb) + offsetof(struct ghcb, shared_buffer); 426 415 ghcb_set_sw_scratch(ghcb, sw_scratch); 427 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, 416 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_IOIO, 428 417 exit_info_1, exit_info_2); 429 418 if (ret != ES_OK) 430 419 return ret; ··· 466 455 467 456 ghcb_set_rax(ghcb, rax); 468 457 469 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, exit_info_1, 0); 458 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, 459 + SVM_EXIT_IOIO, exit_info_1, 0); 470 460 if (ret != ES_OK) 471 461 return ret; 472 462 ··· 498 486 /* xgetbv will cause #GP - use reset value for xcr0 */ 499 487 ghcb_set_xcr0(ghcb, 1); 500 488 501 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0); 489 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_CPUID, 0, 0); 502 490 if (ret != ES_OK) 503 491 return ret; 504 492 ··· 523 511 bool rdtscp = (exit_code == SVM_EXIT_RDTSCP); 524 512 enum es_result ret; 525 513 526 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, exit_code, 0, 0); 514 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, 0, 0); 527 515 if (ret != ES_OK) 528 516 return ret; 529 517
+24 -10
arch/x86/kernel/sev.c
··· 648 648 ghcb_set_rdx(ghcb, regs->dx); 649 649 } 650 650 651 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, exit_info_1, 0); 651 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_MSR, 652 + exit_info_1, 0); 652 653 653 654 if ((ret == ES_OK) && (!exit_info_1)) { 654 655 regs->ax = ghcb->save.rax; ··· 868 867 869 868 ghcb_set_sw_scratch(ghcb, ghcb_pa + offsetof(struct ghcb, shared_buffer)); 870 869 871 - return sev_es_ghcb_hv_call(ghcb, ctxt, exit_code, exit_info_1, exit_info_2); 870 + return sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, exit_info_1, exit_info_2); 872 871 } 873 872 874 873 static enum es_result vc_handle_mmio_twobyte_ops(struct ghcb *ghcb, ··· 1118 1117 1119 1118 /* Using a value of 0 for ExitInfo1 means RAX holds the value */ 1120 1119 ghcb_set_rax(ghcb, val); 1121 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_WRITE_DR7, 0, 0); 1120 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_WRITE_DR7, 0, 0); 1122 1121 if (ret != ES_OK) 1123 1122 return ret; 1124 1123 ··· 1148 1147 static enum es_result vc_handle_wbinvd(struct ghcb *ghcb, 1149 1148 struct es_em_ctxt *ctxt) 1150 1149 { 1151 - return sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_WBINVD, 0, 0); 1150 + return sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_WBINVD, 0, 0); 1152 1151 } 1153 1152 1154 1153 static enum es_result vc_handle_rdpmc(struct ghcb *ghcb, struct es_em_ctxt *ctxt) ··· 1157 1156 1158 1157 ghcb_set_rcx(ghcb, ctxt->regs->cx); 1159 1158 1160 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_RDPMC, 0, 0); 1159 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_RDPMC, 0, 0); 1161 1160 if (ret != ES_OK) 1162 1161 return ret; 1163 1162 ··· 1198 1197 if (x86_platform.hyper.sev_es_hcall_prepare) 1199 1198 x86_platform.hyper.sev_es_hcall_prepare(ghcb, ctxt->regs); 1200 1199 1201 - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_VMMCALL, 0, 0); 1200 + ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_VMMCALL, 0, 0); 1202 1201 if (ret != ES_OK) 1203 1202 return ret; 1204 1203 ··· 1320 1319 } 1321 1320 } 1322 1321 1323 - static __always_inline bool on_vc_fallback_stack(struct pt_regs *regs) 1322 + static __always_inline bool is_vc2_stack(unsigned long sp) 1324 1323 { 1325 - unsigned long sp = (unsigned long)regs; 1326 - 1327 1324 return (sp >= __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_va(VC2)); 1325 + } 1326 + 1327 + static __always_inline bool vc_from_invalid_context(struct pt_regs *regs) 1328 + { 1329 + unsigned long sp, prev_sp; 1330 + 1331 + sp = (unsigned long)regs; 1332 + prev_sp = regs->sp; 1333 + 1334 + /* 1335 + * If the code was already executing on the VC2 stack when the #VC 1336 + * happened, let it proceed to the normal handling routine. This way the 1337 + * code executing on the VC2 stack can cause #VC exceptions to get handled. 1338 + */ 1339 + return is_vc2_stack(sp) && !is_vc2_stack(prev_sp); 1328 1340 } 1329 1341 1330 1342 static bool vc_raw_handle_exception(struct pt_regs *regs, unsigned long error_code) ··· 1420 1406 * But keep this here in case the noinstr annotations are violated due 1421 1407 * to bug elsewhere. 1422 1408 */ 1423 - if (unlikely(on_vc_fallback_stack(regs))) { 1409 + if (unlikely(vc_from_invalid_context(regs))) { 1424 1410 instrumentation_begin(); 1425 1411 panic("Can't handle #VC exception from unsupported context\n"); 1426 1412 instrumentation_end();
+1 -1
arch/x86/kernel/traps.c
··· 709 709 stack = (unsigned long *)sp; 710 710 711 711 if (!get_stack_info_noinstr(stack, current, &info) || info.type == STACK_TYPE_ENTRY || 712 - info.type >= STACK_TYPE_EXCEPTION_LAST) 712 + info.type > STACK_TYPE_EXCEPTION_LAST) 713 713 sp = __this_cpu_ist_top_va(VC2); 714 714 715 715 sync:
+9
arch/x86/mm/mem_encrypt_identity.c
··· 27 27 #undef CONFIG_PARAVIRT_XXL 28 28 #undef CONFIG_PARAVIRT_SPINLOCKS 29 29 30 + /* 31 + * This code runs before CPU feature bits are set. By default, the 32 + * pgtable_l5_enabled() function uses bit X86_FEATURE_LA57 to determine if 33 + * 5-level paging is active, so that won't work here. USE_EARLY_PGTABLE_L5 34 + * is provided to handle this situation and, instead, use a variable that 35 + * has been set by the early boot code. 36 + */ 37 + #define USE_EARLY_PGTABLE_L5 38 + 30 39 #include <linux/kernel.h> 31 40 #include <linux/mm.h> 32 41 #include <linux/mem_encrypt.h>