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 | not enable SME, then Linux will not be able to activate memory encryption, even | 95 | not enable SME, then Linux will not be able to activate memory encryption, even |
| 96 | if configured to do so by default or the mem_encrypt=on command line parameter | 96 | if configured to do so by default or the mem_encrypt=on command line parameter |
| 97 | is specified. | 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 | ifdef CONFIG_CC_IS_GCC | 15 | ifdef CONFIG_CC_IS_GCC |
| 16 | RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) | 16 | RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register) |
| 17 | RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix) | ||
| 18 | RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register) | 17 | RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register) |
| 19 | endif | 18 | endif |
| 20 | ifdef CONFIG_CC_IS_CLANG | 19 | ifdef CONFIG_CC_IS_CLANG |
| 21 | RETPOLINE_CFLAGS := -mretpoline-external-thunk | 20 | RETPOLINE_CFLAGS := -mretpoline-external-thunk |
| 22 | RETPOLINE_VDSO_CFLAGS := -mretpoline | 21 | RETPOLINE_VDSO_CFLAGS := -mretpoline |
| 23 | endif | 22 | endif |
| 23 | RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix) | ||
| 24 | 24 | ||
| 25 | ifdef CONFIG_RETHUNK | 25 | ifdef CONFIG_RETHUNK |
| 26 | RETHUNK_CFLAGS := -mfunction-return=thunk-extern | 26 | RETHUNK_CFLAGS := -mfunction-return=thunk-extern |
| @@ -180,6 +180,12 @@ void initialize_identity_maps(void *rmode) · 179 unmodified lines | |||
| 180 | 180 | ||
| 181 | /* Load the new page-table. */ | 181 | /* Load the new page-table. */ |
| 182 | write_cr3(top_level_pgt); | 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 | static pte_t *split_large_pmd(struct x86_mapping_info *info, | 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 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 127 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 128 | void sev_enable(struct boot_params *bp); | 128 | void sev_enable(struct boot_params *bp); |
| 129 | void snp_check_features(void); | ||
| 129 | void sev_es_shutdown_ghcb(void); | 130 | void sev_es_shutdown_ghcb(void); |
| 130 | extern bool sev_es_check_ghcb_fault(unsigned long address); | 131 | extern bool sev_es_check_ghcb_fault(unsigned long address); |
| 131 | void snp_set_page_private(unsigned long paddr); | 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 | if (bp) | 144 | if (bp) |
| 144 | bp->cc_blob_address = 0; | 145 | bp->cc_blob_address = 0; |
| 145 | } | 146 | } |
| 147 | static inline void snp_check_features(void) { } | ||
| 146 | static inline void sev_es_shutdown_ghcb(void) { } | 148 | static inline void sev_es_shutdown_ghcb(void) { } |
| 147 | static inline bool sev_es_check_ghcb_fault(unsigned long address) | 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 | error("Can't unmap GHCB page"); | 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 | bool sev_es_check_ghcb_fault(unsigned long address) | 228 | bool sev_es_check_ghcb_fault(unsigned long address) |
| 212 | { | 229 | { |
| 213 | /* Check whether the fault was on the GHCB page */ | 230 | /* Check whether the fault was on the GHCB page */ |
| @@ -270,6 +287,59 @@ static void enforce_vmpl0(void) · 56 unmodified lines | |||
| 270 | sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0); | 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 | void sev_enable(struct boot_params *bp) | 343 | void sev_enable(struct boot_params *bp) |
| 274 | { | 344 | { |
| 275 | unsigned int eax, ebx, ecx, edx; | 345 | unsigned int eax, ebx, ecx, edx; |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <asm/mmu.h> | 14 | #include <asm/mmu.h> |
| 15 | #include <asm/mpspec.h> | 15 | #include <asm/mpspec.h> |
| 16 | #include <asm/x86_init.h> | 16 | #include <asm/x86_init.h> |
| 17 | #include <asm/cpufeature.h> | ||
| 17 | 18 | ||
| 18 | #ifdef CONFIG_ACPI_APEI | 19 | #ifdef CONFIG_ACPI_APEI |
| 19 | # include <asm/pgtable_types.h> | 20 | # include <asm/pgtable_types.h> |
| @@ -63,6 +64,13 @@ extern int (*acpi_suspend_lowlevel)(void); · 43 unmodified lines | |||
| 63 | /* Physical address to resume after wakeup */ | 64 | /* Physical address to resume after wakeup */ |
| 64 | unsigned long acpi_get_wakeup_address(void); | 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 | * Check if the CPU can handle C2 and deeper | 75 | * Check if the CPU can handle C2 and deeper |
| 68 | */ | 76 | */ |
| @@ -566,6 +566,26 @@ · 565 unmodified lines | |||
| 566 | #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) | 566 | #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) |
| 567 | #define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT) | 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 | #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f | 589 | #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f |
| 570 | 590 | ||
| 571 | /* AMD Collaborative Processor Performance Control MSRs */ | 591 | /* AMD Collaborative Processor Performance Control MSRs */ |
| @@ -116,6 +116,12 @@ · 115 unmodified lines | |||
| 116 | #define SVM_VMGEXIT_AP_CREATE 1 | 116 | #define SVM_VMGEXIT_AP_CREATE 1 |
| 117 | #define SVM_VMGEXIT_AP_DESTROY 2 | 117 | #define SVM_VMGEXIT_AP_DESTROY 2 |
| 118 | #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd | 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 | #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff | 125 | #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff |
| 120 | 126 | ||
| 121 | /* Exit code reserved for hypervisor/software use */ | 127 | /* Exit code reserved for hypervisor/software use */ |
| @@ -114,6 +114,7 @@ static void make_8259A_irq(unsigned int irq) · 113 unmodified lines | |||
| 114 | disable_irq_nosync(irq); | 114 | disable_irq_nosync(irq); |
| 115 | io_apic_irqs &= ~(1<<irq); | 115 | io_apic_irqs &= ~(1<<irq); |
| 116 | irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq); | 116 | irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq); |
| 117 | irq_set_status_flags(irq, IRQ_LEVEL); | ||
| 117 | enable_irq(irq); | 118 | enable_irq(irq); |
| 118 | lapic_assign_legacy_vector(irq, true); | 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 | legacy_pic->init(0); | 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 | irq_set_chip_and_handler(i, chip, handle_level_irq); | 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 | void __init init_IRQ(void) | 74 | void __init init_IRQ(void) |
| @@ -392,6 +392,7 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) · 391 unmodified lines | |||
| 392 | msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_ASSOCIATED) { | 392 | msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_ASSOCIATED) { |
| 393 | for (i = 0; i < msidesc->nvec_used; i++) | 393 | for (i = 0; i < msidesc->nvec_used; i++) |
| 394 | xen_destroy_irq(msidesc->irq + i); | 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 | static struct msi_domain_info xen_pci_msi_domain_info = { | 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 | .ops = &xen_pci_msi_domain_ops, | 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 | .priority = 0, | 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 | static int acpi_sleep_prepare(u32 acpi_state) | 67 | static int acpi_sleep_prepare(u32 acpi_state) |
| 64 | { | 68 | { |
| 65 | #ifdef CONFIG_ACPI_SLEEP | 69 | #ifdef CONFIG_ACPI_SLEEP |
| 66 | unsigned long acpi_wakeup_address; | 70 | unsigned long acpi_wakeup_address; |
| 67 | 71 | ||
| 68 | /* do we have a wakeup address for S2 and S3? */ | 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 | acpi_wakeup_address = acpi_get_wakeup_address(); | 74 | acpi_wakeup_address = acpi_get_wakeup_address(); |
| 71 | if (!acpi_wakeup_address) | 75 | if (!acpi_wakeup_address) |
| 72 | return -EFAULT; | 76 | return -EFAULT; |