Pull x86 fixes from Borislav Petkov: - Start checking for -mindirect-branch-cs-prefix clang support too now that LLVM 16 will support it - Fix a NULL ptr deref when suspending with Xen PV - Have a SEV-SNP guest check explicitly for features enabled by the hypervisor and fail gracefully if some are unsupported by the guest instead of failing in a non-obvious and hard-to-debug way - Fix a MSI descriptor leakage under Xen - Mark Xen's MSI domain as supporting MSI-X - Prevent legacy PIC interrupts from being resent in software by marking them level triggered, as they should be, which lead to a NULL ptr deref * tag 'x86_urgent_for_v6.2_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/build: Move '-mindirect-branch-cs-prefix' out of GCC-only block acpi: Fix suspend with Xen PV x86/sev: Add SEV-SNP guest feature negotiation support x86/pci/xen: Fixup fallout from the PCI/MSI overhaul x86/pci/xen: Set MSI_FLAG_PCI_MSIX support in Xen MSI domain x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL
Unified · Split
| @@ -95,3 +95,39 @@ by supplying mem_encrypt=on on the kernel command line. However, if BIOS does · 94 unmodified lines | ||
| 95 | 95 | not enable SME, then Linux will not be able to activate memory encryption, even |
| 96 | 96 | if configured to do so by default or the mem_encrypt=on command line parameter |
| 97 | 97 | is specified. |
| 98 | + | |
| 99 | +Secure Nested Paging (SNP) | |
| 100 | +========================== | |
| 101 | + | |
| 102 | +SEV-SNP introduces new features (SEV_FEATURES[1:63]) which can be enabled | |
| 103 | +by the hypervisor for security enhancements. Some of these features need | |
| 104 | +guest side implementation to function correctly. The below table lists the | |
| 105 | +expected guest behavior with various possible scenarios of guest/hypervisor | |
| 106 | +SNP feature support. | |
| 107 | + | |
| 108 | ++-----------------+---------------+---------------+------------------+ | |
| 109 | +| Feature Enabled | Guest needs | Guest has | Guest boot | | |
| 110 | +| by the HV | implementation| implementation| behaviour | | |
| 111 | ++=================+===============+===============+==================+ | |
| 112 | +| No | No | No | Boot | | |
| 113 | +| | | | | | |
| 114 | ++-----------------+---------------+---------------+------------------+ | |
| 115 | +| No | Yes | No | Boot | | |
| 116 | +| | | | | | |
| 117 | ++-----------------+---------------+---------------+------------------+ | |
| 118 | +| No | Yes | Yes | Boot | | |
| 119 | +| | | | | | |
| 120 | ++-----------------+---------------+---------------+------------------+ | |
| 121 | +| Yes | No | No | Boot with | | |
| 122 | +| | | | feature enabled | | |
| 123 | ++-----------------+---------------+---------------+------------------+ | |
| 124 | +| Yes | Yes | No | Graceful boot | | |
| 125 | +| | | | failure | | |
| 126 | ++-----------------+---------------+---------------+------------------+ | |
| 127 | +| Yes | Yes | Yes | Boot with | | |
| 128 | +| | | | feature enabled | | |
| 129 | ++-----------------+---------------+---------------+------------------+ | |
| 130 | + | |
| 131 | +More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR | |
| 132 | + | |
| 133 | +[1] https://www.amd.com/system/files/TechDocs/40332.pdf | |
| @@ -14,13 +14,13 @@ endif · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | ifdef CONFIG_CC_IS_GCC |
| 16 | 16 | RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) |
| 17 | −RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix) | |
| 18 | 17 | RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register) |
| 19 | 18 | endif |
| 20 | 19 | ifdef CONFIG_CC_IS_CLANG |
| 21 | 20 | RETPOLINE_CFLAGS := -mretpoline-external-thunk |
| 22 | 21 | RETPOLINE_VDSO_CFLAGS := -mretpoline |
| 23 | 22 | endif |
| 23 | +RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix) | |
| 24 | 24 | |
| 25 | 25 | ifdef CONFIG_RETHUNK |
| 26 | 26 | RETHUNK_CFLAGS := -mfunction-return=thunk-extern |
| @@ -180,6 +180,12 @@ void initialize_identity_maps(void *rmode) · 179 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | /* Load the new page-table. */ |
| 182 | 182 | write_cr3(top_level_pgt); |
| 183 | + | |
| 184 | + /* | |
| 185 | + * Now that the required page table mappings are established and a | |
| 186 | + * GHCB can be used, check for SNP guest/HV feature compatibility. | |
| 187 | + */ | |
| 188 | + snp_check_features(); | |
| 183 | 189 | } |
| 184 | 190 | |
| 185 | 191 | static pte_t *split_large_pmd(struct x86_mapping_info *info, |
| @@ -126,6 +126,7 @@ static inline void console_init(void) · 125 unmodified lines | ||
| 126 | 126 | |
| 127 | 127 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 128 | 128 | void sev_enable(struct boot_params *bp); |
| 129 | +void snp_check_features(void); | |
| 129 | 130 | void sev_es_shutdown_ghcb(void); |
| 130 | 131 | extern bool sev_es_check_ghcb_fault(unsigned long address); |
| 131 | 132 | void snp_set_page_private(unsigned long paddr); |
| @@ -143,6 +144,7 @@ static inline void sev_enable(struct boot_params *bp) · 11 unmodified lines | ||
| 143 | 144 | if (bp) |
| 144 | 145 | bp->cc_blob_address = 0; |
| 145 | 146 | } |
| 147 | +static inline void snp_check_features(void) { } | |
| 146 | 148 | static inline void sev_es_shutdown_ghcb(void) { } |
| 147 | 149 | static inline bool sev_es_check_ghcb_fault(unsigned long address) |
| 148 | 150 | { |
| @@ -208,6 +208,23 @@ void sev_es_shutdown_ghcb(void) · 207 unmodified lines | ||
| 208 | 208 | error("Can't unmap GHCB page"); |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | +static void __noreturn sev_es_ghcb_terminate(struct ghcb *ghcb, unsigned int set, | |
| 212 | + unsigned int reason, u64 exit_info_2) | |
| 213 | +{ | |
| 214 | + u64 exit_info_1 = SVM_VMGEXIT_TERM_REASON(set, reason); | |
| 215 | + | |
| 216 | + vc_ghcb_invalidate(ghcb); | |
| 217 | + ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_TERM_REQUEST); | |
| 218 | + ghcb_set_sw_exit_info_1(ghcb, exit_info_1); | |
| 219 | + ghcb_set_sw_exit_info_2(ghcb, exit_info_2); | |
| 220 | + | |
| 221 | + sev_es_wr_ghcb_msr(__pa(ghcb)); | |
| 222 | + VMGEXIT(); | |
| 223 | + | |
| 224 | + while (true) | |
| 225 | + asm volatile("hlt\n" : : : "memory"); | |
| 226 | +} | |
| 227 | + | |
| 211 | 228 | bool sev_es_check_ghcb_fault(unsigned long address) |
| 212 | 229 | { |
| 213 | 230 | /* Check whether the fault was on the GHCB page */ |
| @@ -270,6 +287,59 @@ static void enforce_vmpl0(void) · 56 unmodified lines | ||
| 270 | 287 | sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0); |
| 271 | 288 | } |
| 272 | 289 | |
| 290 | +/* | |
| 291 | + * SNP_FEATURES_IMPL_REQ is the mask of SNP features that will need | |
| 292 | + * guest side implementation for proper functioning of the guest. If any | |
| 293 | + * of these features are enabled in the hypervisor but are lacking guest | |
| 294 | + * side implementation, the behavior of the guest will be undefined. The | |
| 295 | + * guest could fail in non-obvious way making it difficult to debug. | |
| 296 | + * | |
| 297 | + * As the behavior of reserved feature bits is unknown to be on the | |
| 298 | + * safe side add them to the required features mask. | |
| 299 | + */ | |
| 300 | +#define SNP_FEATURES_IMPL_REQ (MSR_AMD64_SNP_VTOM | \ | |
| 301 | + MSR_AMD64_SNP_REFLECT_VC | \ | |
| 302 | + MSR_AMD64_SNP_RESTRICTED_INJ | \ | |
| 303 | + MSR_AMD64_SNP_ALT_INJ | \ | |
| 304 | + MSR_AMD64_SNP_DEBUG_SWAP | \ | |
| 305 | + MSR_AMD64_SNP_VMPL_SSS | \ | |
| 306 | + MSR_AMD64_SNP_SECURE_TSC | \ | |
| 307 | + MSR_AMD64_SNP_VMGEXIT_PARAM | \ | |
| 308 | + MSR_AMD64_SNP_VMSA_REG_PROTECTION | \ | |
| 309 | + MSR_AMD64_SNP_RESERVED_BIT13 | \ | |
| 310 | + MSR_AMD64_SNP_RESERVED_BIT15 | \ | |
| 311 | + MSR_AMD64_SNP_RESERVED_MASK) | |
| 312 | + | |
| 313 | +/* | |
| 314 | + * SNP_FEATURES_PRESENT is the mask of SNP features that are implemented | |
| 315 | + * by the guest kernel. As and when a new feature is implemented in the | |
| 316 | + * guest kernel, a corresponding bit should be added to the mask. | |
| 317 | + */ | |
| 318 | +#define SNP_FEATURES_PRESENT (0) | |
| 319 | + | |
| 320 | +void snp_check_features(void) | |
| 321 | +{ | |
| 322 | + u64 unsupported; | |
| 323 | + | |
| 324 | + if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED)) | |
| 325 | + return; | |
| 326 | + | |
| 327 | + /* | |
| 328 | + * Terminate the boot if hypervisor has enabled any feature lacking | |
| 329 | + * guest side implementation. Pass on the unsupported features mask through | |
| 330 | + * EXIT_INFO_2 of the GHCB protocol so that those features can be reported | |
| 331 | + * as part of the guest boot failure. | |
| 332 | + */ | |
| 333 | + unsupported = sev_status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT; | |
| 334 | + if (unsupported) { | |
| 335 | + if (ghcb_version < 2 || (!boot_ghcb && !early_setup_ghcb())) | |
| 336 | + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); | |
| 337 | + | |
| 338 | + sev_es_ghcb_terminate(boot_ghcb, SEV_TERM_SET_GEN, | |
| 339 | + GHCB_SNP_UNSUPPORTED, unsupported); | |
| 340 | + } | |
| 341 | +} | |
| 342 | + | |
| 273 | 343 | void sev_enable(struct boot_params *bp) |
| 274 | 344 | { |
| 275 | 345 | unsigned int eax, ebx, ecx, edx; |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <asm/mmu.h> |
| 15 | 15 | #include <asm/mpspec.h> |
| 16 | 16 | #include <asm/x86_init.h> |
| 17 | +#include <asm/cpufeature.h> | |
| 17 | 18 | |
| 18 | 19 | #ifdef CONFIG_ACPI_APEI |
| 19 | 20 | # include <asm/pgtable_types.h> |
| @@ -63,6 +64,13 @@ extern int (*acpi_suspend_lowlevel)(void); · 43 unmodified lines | ||
| 63 | 64 | /* Physical address to resume after wakeup */ |
| 64 | 65 | unsigned long acpi_get_wakeup_address(void); |
| 65 | 66 | |
| 67 | +static inline bool acpi_skip_set_wakeup_address(void) | |
| 68 | +{ | |
| 69 | + return cpu_feature_enabled(X86_FEATURE_XENPV); | |
| 70 | +} | |
| 71 | + | |
| 72 | +#define acpi_skip_set_wakeup_address acpi_skip_set_wakeup_address | |
| 73 | + | |
| 66 | 74 | /* |
| 67 | 75 | * Check if the CPU can handle C2 and deeper |
| 68 | 76 | */ |
| @@ -566,6 +566,26 @@ · 565 unmodified lines | ||
| 566 | 566 | #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) |
| 567 | 567 | #define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT) |
| 568 | 568 | |
| 569 | +/* SNP feature bits enabled by the hypervisor */ | |
| 570 | +#define MSR_AMD64_SNP_VTOM BIT_ULL(3) | |
| 571 | +#define MSR_AMD64_SNP_REFLECT_VC BIT_ULL(4) | |
| 572 | +#define MSR_AMD64_SNP_RESTRICTED_INJ BIT_ULL(5) | |
| 573 | +#define MSR_AMD64_SNP_ALT_INJ BIT_ULL(6) | |
| 574 | +#define MSR_AMD64_SNP_DEBUG_SWAP BIT_ULL(7) | |
| 575 | +#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(8) | |
| 576 | +#define MSR_AMD64_SNP_BTB_ISOLATION BIT_ULL(9) | |
| 577 | +#define MSR_AMD64_SNP_VMPL_SSS BIT_ULL(10) | |
| 578 | +#define MSR_AMD64_SNP_SECURE_TSC BIT_ULL(11) | |
| 579 | +#define MSR_AMD64_SNP_VMGEXIT_PARAM BIT_ULL(12) | |
| 580 | +#define MSR_AMD64_SNP_IBS_VIRT BIT_ULL(14) | |
| 581 | +#define MSR_AMD64_SNP_VMSA_REG_PROTECTION BIT_ULL(16) | |
| 582 | +#define MSR_AMD64_SNP_SMT_PROTECTION BIT_ULL(17) | |
| 583 | + | |
| 584 | +/* SNP feature bits reserved for future use. */ | |
| 585 | +#define MSR_AMD64_SNP_RESERVED_BIT13 BIT_ULL(13) | |
| 586 | +#define MSR_AMD64_SNP_RESERVED_BIT15 BIT_ULL(15) | |
| 587 | +#define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, 18) | |
| 588 | + | |
| 569 | 589 | #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f |
| 570 | 590 | |
| 571 | 591 | /* AMD Collaborative Processor Performance Control MSRs */ |
| @@ -116,6 +116,12 @@ · 115 unmodified lines | ||
| 116 | 116 | #define SVM_VMGEXIT_AP_CREATE 1 |
| 117 | 117 | #define SVM_VMGEXIT_AP_DESTROY 2 |
| 118 | 118 | #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd |
| 119 | +#define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe | |
| 120 | +#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \ | |
| 121 | + /* SW_EXITINFO1[3:0] */ \ | |
| 122 | + (((((u64)reason_set) & 0xf)) | \ | |
| 123 | + /* SW_EXITINFO1[11:4] */ \ | |
| 124 | + ((((u64)reason_code) & 0xff) << 4)) | |
| 119 | 125 | #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff |
| 120 | 126 | |
| 121 | 127 | /* Exit code reserved for hypervisor/software use */ |
| @@ -114,6 +114,7 @@ static void make_8259A_irq(unsigned int irq) · 113 unmodified lines | ||
| 114 | 114 | disable_irq_nosync(irq); |
| 115 | 115 | io_apic_irqs &= ~(1<<irq); |
| 116 | 116 | irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq); |
| 117 | + irq_set_status_flags(irq, IRQ_LEVEL); | |
| 117 | 118 | enable_irq(irq); |
| 118 | 119 | lapic_assign_legacy_vector(irq, true); |
| 119 | 120 | } |
| @@ -65,8 +65,10 @@ void __init init_ISA_irqs(void) · 64 unmodified lines | ||
| 65 | 65 | |
| 66 | 66 | legacy_pic->init(0); |
| 67 | 67 | |
| 68 | − for (i = 0; i < nr_legacy_irqs(); i++) | |
| 68 | + for (i = 0; i < nr_legacy_irqs(); i++) { | |
| 69 | 69 | irq_set_chip_and_handler(i, chip, handle_level_irq); |
| 70 | + irq_set_status_flags(i, IRQ_LEVEL); | |
| 71 | + } | |
| 70 | 72 | } |
| 71 | 73 | |
| 72 | 74 | void __init init_IRQ(void) |
| @@ -392,6 +392,7 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) · 391 unmodified lines | ||
| 392 | 392 | msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_ASSOCIATED) { |
| 393 | 393 | for (i = 0; i < msidesc->nvec_used; i++) |
| 394 | 394 | xen_destroy_irq(msidesc->irq + i); |
| 395 | + msidesc->irq = 0; | |
| 395 | 396 | } |
| 396 | 397 | } |
| 397 | 398 | |
| @@ -433,6 +434,7 @@ static struct msi_domain_ops xen_pci_msi_domain_ops = { · 35 unmodified lines | ||
| 433 | 434 | }; |
| 434 | 435 | |
| 435 | 436 | static struct msi_domain_info xen_pci_msi_domain_info = { |
| 437 | + .flags = MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS | MSI_FLAG_DEV_SYSFS, | |
| 436 | 438 | .ops = &xen_pci_msi_domain_ops, |
| 437 | 439 | }; |
| 438 | 440 | |
| @@ -60,13 +60,17 @@ static struct notifier_block tts_notifier = { · 59 unmodified lines | ||
| 60 | 60 | .priority = 0, |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | +#ifndef acpi_skip_set_wakeup_address | |
| 64 | +#define acpi_skip_set_wakeup_address() false | |
| 65 | +#endif | |
| 66 | + | |
| 63 | 67 | static int acpi_sleep_prepare(u32 acpi_state) |
| 64 | 68 | { |
| 65 | 69 | #ifdef CONFIG_ACPI_SLEEP |
| 66 | 70 | unsigned long acpi_wakeup_address; |
| 67 | 71 | |
| 68 | 72 | /* do we have a wakeup address for S2 and S3? */ |
| 69 | − if (acpi_state == ACPI_STATE_S3) { | |
| 73 | + if (acpi_state == ACPI_STATE_S3 && !acpi_skip_set_wakeup_address()) { | |
| 70 | 74 | acpi_wakeup_address = acpi_get_wakeup_address(); |
| 71 | 75 | if (!acpi_wakeup_address) |
| 72 | 76 | return -EFAULT; |