Commit 1aac9cb7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86_urgent_for_v6.9_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

 - Make sure single object builds in arch/x86/virt/ ala
      make ... arch/x86/virt/vmx/tdx/seamcall.o
   work again

 - Do not do ROM range scans and memory validation when the kernel is
   running as a SEV-SNP guest as those can get problematic and, before
   that, are not really needed in such a guest

 - Exclude the build-time generated vdso-image-x32.o object from objtool
   validation and in particular the return sites in there due to a
   warning which fires when an unpatched return thunk is being used

 - Improve the NMI CPUs stall message to show additional information
   about the state of each CPU wrt the NMI handler

 - Enable gcc named address spaces support only on !KCSAN configs due to
   compiler options incompatibility

 - Revert a change which was trying to use GB pages for mapping regions
   only when the regions would be large enough but that change lead to
   kexec failing

 - A documentation fixlet

* tag 'x86_urgent_for_v6.9_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/build: Use obj-y to descend into arch/x86/virt/
  x86/sev: Skip ROM range scans and validation for SEV-SNP guests
  x86/vdso: Fix rethunk patching for vdso-image-x32.o too
  x86/nmi: Upgrade NMI backtrace stall checks & messages
  x86/percpu: Disable named address spaces for KCSAN
  Revert "x86/mm/ident_map: Use gbpages only where full GB page should be mapped."
  Documentation/x86: Fix title underline length
parents 712e1425 3f1a9bc5
...@@ -574,7 +574,7 @@ Memory b/w domain is L3 cache. ...@@ -574,7 +574,7 @@ Memory b/w domain is L3 cache.
MB:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;... MB:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;...
Memory bandwidth Allocation specified in MiBps Memory bandwidth Allocation specified in MiBps
--------------------------------------------- ----------------------------------------------
Memory bandwidth domain is L3 cache. Memory bandwidth domain is L3 cache.
:: ::
......
...@@ -28,7 +28,7 @@ obj-y += net/ ...@@ -28,7 +28,7 @@ obj-y += net/
obj-$(CONFIG_KEXEC_FILE) += purgatory/ obj-$(CONFIG_KEXEC_FILE) += purgatory/
obj-y += virt/svm/ obj-y += virt/
# for cleaning # for cleaning
subdir- += boot tools subdir- += boot tools
...@@ -2439,6 +2439,8 @@ config USE_X86_SEG_SUPPORT ...@@ -2439,6 +2439,8 @@ config USE_X86_SEG_SUPPORT
# with named address spaces - see GCC PR sanitizer/111736. # with named address spaces - see GCC PR sanitizer/111736.
# #
depends on !KASAN depends on !KASAN
# -fsanitize=thread (KCSAN) is also incompatible.
depends on !KCSAN
config CC_HAS_SLS config CC_HAS_SLS
def_bool $(cc-option,-mharden-sls=all) def_bool $(cc-option,-mharden-sls=all)
......
...@@ -251,8 +251,6 @@ archheaders: ...@@ -251,8 +251,6 @@ archheaders:
libs-y += arch/x86/lib/ libs-y += arch/x86/lib/
core-y += arch/x86/virt/
# drivers-y are linked after core-y # drivers-y are linked after core-y
drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/ drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
drivers-$(CONFIG_PCI) += arch/x86/pci/ drivers-$(CONFIG_PCI) += arch/x86/pci/
......
...@@ -41,6 +41,7 @@ obj-$(CONFIG_X86_X32_ABI) += vdso-image-x32.o ...@@ -41,6 +41,7 @@ obj-$(CONFIG_X86_X32_ABI) += vdso-image-x32.o
obj-$(CONFIG_COMPAT_32) += vdso-image-32.o vdso32-setup.o obj-$(CONFIG_COMPAT_32) += vdso-image-32.o vdso32-setup.o
OBJECT_FILES_NON_STANDARD_vdso-image-32.o := n OBJECT_FILES_NON_STANDARD_vdso-image-32.o := n
OBJECT_FILES_NON_STANDARD_vdso-image-x32.o := n
OBJECT_FILES_NON_STANDARD_vdso-image-64.o := n OBJECT_FILES_NON_STANDARD_vdso-image-64.o := n
OBJECT_FILES_NON_STANDARD_vdso32-setup.o := n OBJECT_FILES_NON_STANDARD_vdso32-setup.o := n
......
...@@ -218,12 +218,12 @@ void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, ...@@ -218,12 +218,12 @@ void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
unsigned long npages); unsigned long npages);
void early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, void early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
unsigned long npages); unsigned long npages);
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op);
void snp_set_memory_shared(unsigned long vaddr, unsigned long npages); void snp_set_memory_shared(unsigned long vaddr, unsigned long npages);
void snp_set_memory_private(unsigned long vaddr, unsigned long npages); void snp_set_memory_private(unsigned long vaddr, unsigned long npages);
void snp_set_wakeup_secondary_cpu(void); void snp_set_wakeup_secondary_cpu(void);
bool snp_init(struct boot_params *bp); bool snp_init(struct boot_params *bp);
void __noreturn snp_abort(void); void __noreturn snp_abort(void);
void snp_dmi_setup(void);
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio); int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
void snp_accept_memory(phys_addr_t start, phys_addr_t end); void snp_accept_memory(phys_addr_t start, phys_addr_t end);
u64 snp_get_unsupported_features(u64 status); u64 snp_get_unsupported_features(u64 status);
...@@ -244,12 +244,12 @@ static inline void __init ...@@ -244,12 +244,12 @@ static inline void __init
early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { } early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
static inline void __init static inline void __init
early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { } early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { }
static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { } static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { }
static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { } static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { }
static inline void snp_set_wakeup_secondary_cpu(void) { } static inline void snp_set_wakeup_secondary_cpu(void) { }
static inline bool snp_init(struct boot_params *bp) { return false; } static inline bool snp_init(struct boot_params *bp) { return false; }
static inline void snp_abort(void) { } static inline void snp_abort(void) { }
static inline void snp_dmi_setup(void) { }
static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
{ {
return -ENOTTY; return -ENOTTY;
......
...@@ -30,12 +30,13 @@ struct x86_init_mpparse { ...@@ -30,12 +30,13 @@ struct x86_init_mpparse {
* @reserve_resources: reserve the standard resources for the * @reserve_resources: reserve the standard resources for the
* platform * platform
* @memory_setup: platform specific memory setup * @memory_setup: platform specific memory setup
* * @dmi_setup: platform specific DMI setup
*/ */
struct x86_init_resources { struct x86_init_resources {
void (*probe_roms)(void); void (*probe_roms)(void);
void (*reserve_resources)(void); void (*reserve_resources)(void);
char *(*memory_setup)(void); char *(*memory_setup)(void);
void (*dmi_setup)(void);
}; };
/** /**
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* /*
* EISA specific code * EISA specific code
*/ */
#include <linux/cc_platform.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/eisa.h> #include <linux/eisa.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -12,7 +13,7 @@ static __init int eisa_bus_probe(void) ...@@ -12,7 +13,7 @@ static __init int eisa_bus_probe(void)
{ {
void __iomem *p; void __iomem *p;
if (xen_pv_domain() && !xen_initial_domain()) if ((xen_pv_domain() && !xen_initial_domain()) || cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return 0; return 0;
p = ioremap(0x0FFFD9, 4); p = ioremap(0x0FFFD9, 4);
......
...@@ -580,7 +580,7 @@ EXPORT_SYMBOL_GPL(asm_exc_nmi_kvm_vmx); ...@@ -580,7 +580,7 @@ EXPORT_SYMBOL_GPL(asm_exc_nmi_kvm_vmx);
static char *nmi_check_stall_msg[] = { static char *nmi_check_stall_msg[] = {
/* */ /* */
/* +--------- nsp->idt_seq_snap & 0x1: CPU is in NMI handler. */ /* +--------- nmi_seq & 0x1: CPU is currently in NMI handler. */
/* | +------ cpu_is_offline(cpu) */ /* | +------ cpu_is_offline(cpu) */
/* | | +--- nsp->idt_calls_snap != atomic_long_read(&nsp->idt_calls): */ /* | | +--- nsp->idt_calls_snap != atomic_long_read(&nsp->idt_calls): */
/* | | | NMI handler has been invoked. */ /* | | | NMI handler has been invoked. */
...@@ -628,22 +628,26 @@ void nmi_backtrace_stall_check(const struct cpumask *btp) ...@@ -628,22 +628,26 @@ void nmi_backtrace_stall_check(const struct cpumask *btp)
nmi_seq = READ_ONCE(nsp->idt_nmi_seq); nmi_seq = READ_ONCE(nsp->idt_nmi_seq);
if (nsp->idt_nmi_seq_snap + 1 == nmi_seq && (nmi_seq & 0x1)) { if (nsp->idt_nmi_seq_snap + 1 == nmi_seq && (nmi_seq & 0x1)) {
msgp = "CPU entered NMI handler function, but has not exited"; msgp = "CPU entered NMI handler function, but has not exited";
} else if ((nsp->idt_nmi_seq_snap & 0x1) != (nmi_seq & 0x1)) { } else if (nsp->idt_nmi_seq_snap == nmi_seq ||
msgp = "CPU is handling NMIs"; nsp->idt_nmi_seq_snap + 1 == nmi_seq) {
} else { idx = ((nmi_seq & 0x1) << 2) |
idx = ((nsp->idt_seq_snap & 0x1) << 2) |
(cpu_is_offline(cpu) << 1) | (cpu_is_offline(cpu) << 1) |
(nsp->idt_calls_snap != atomic_long_read(&nsp->idt_calls)); (nsp->idt_calls_snap != atomic_long_read(&nsp->idt_calls));
msgp = nmi_check_stall_msg[idx]; msgp = nmi_check_stall_msg[idx];
if (nsp->idt_ignored_snap != READ_ONCE(nsp->idt_ignored) && (idx & 0x1)) if (nsp->idt_ignored_snap != READ_ONCE(nsp->idt_ignored) && (idx & 0x1))
modp = ", but OK because ignore_nmis was set"; modp = ", but OK because ignore_nmis was set";
if (nmi_seq & 0x1) if (nsp->idt_nmi_seq_snap + 1 == nmi_seq)
msghp = " (CPU currently in NMI handler function)";
else if (nsp->idt_nmi_seq_snap + 1 == nmi_seq)
msghp = " (CPU exited one NMI handler function)"; msghp = " (CPU exited one NMI handler function)";
else if (nmi_seq & 0x1)
msghp = " (CPU currently in NMI handler function)";
else
msghp = " (CPU was never in an NMI handler function)";
} else {
msgp = "CPU is handling NMIs";
} }
pr_alert("%s: CPU %d: %s%s%s, last activity: %lu jiffies ago.\n", pr_alert("%s: CPU %d: %s%s%s\n", __func__, cpu, msgp, modp, msghp);
__func__, cpu, msgp, modp, msghp, j - READ_ONCE(nsp->recv_jiffies)); pr_alert("%s: last activity: %lu jiffies ago.\n",
__func__, j - READ_ONCE(nsp->recv_jiffies));
} }
} }
......
...@@ -203,16 +203,6 @@ void __init probe_roms(void) ...@@ -203,16 +203,6 @@ void __init probe_roms(void)
unsigned char c; unsigned char c;
int i; int i;
/*
* The ROM memory range is not part of the e820 table and is therefore not
* pre-validated by BIOS. The kernel page table maps the ROM region as encrypted
* memory, and SNP requires encrypted memory to be validated before access.
* Do that here.
*/
snp_prep_memory(video_rom_resource.start,
((system_rom_resource.end + 1) - video_rom_resource.start),
SNP_PAGE_STATE_PRIVATE);
/* video rom */ /* video rom */
upper = adapter_rom_resources[0].start; upper = adapter_rom_resources[0].start;
for (start = video_rom_resource.start; start < upper; start += 2048) { for (start = video_rom_resource.start; start < upper; start += 2048) {
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/console.h> #include <linux/console.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/dma-map-ops.h> #include <linux/dma-map-ops.h>
#include <linux/dmi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/ima.h> #include <linux/ima.h>
#include <linux/init_ohci1394_dma.h> #include <linux/init_ohci1394_dma.h>
...@@ -902,7 +901,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -902,7 +901,7 @@ void __init setup_arch(char **cmdline_p)
efi_init(); efi_init();
reserve_ibft_region(); reserve_ibft_region();
dmi_setup(); x86_init.resources.dmi_setup();
/* /*
* VMware detection requires dmi to be available, so this * VMware detection requires dmi to be available, so this
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/psp-sev.h> #include <linux/psp-sev.h>
#include <linux/dmi.h>
#include <uapi/linux/sev-guest.h> #include <uapi/linux/sev-guest.h>
#include <asm/init.h> #include <asm/init.h>
...@@ -795,21 +796,6 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr ...@@ -795,21 +796,6 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr
early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_SHARED); early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_SHARED);
} }
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op)
{
unsigned long vaddr, npages;
vaddr = (unsigned long)__va(paddr);
npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
if (op == SNP_PAGE_STATE_PRIVATE)
early_snp_set_memory_private(vaddr, paddr, npages);
else if (op == SNP_PAGE_STATE_SHARED)
early_snp_set_memory_shared(vaddr, paddr, npages);
else
WARN(1, "invalid memory op %d\n", op);
}
static unsigned long __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr, static unsigned long __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr,
unsigned long vaddr_end, int op) unsigned long vaddr_end, int op)
{ {
...@@ -2136,6 +2122,17 @@ void __head __noreturn snp_abort(void) ...@@ -2136,6 +2122,17 @@ void __head __noreturn snp_abort(void)
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
} }
/*
* SEV-SNP guests should only execute dmi_setup() if EFI_CONFIG_TABLES are
* enabled, as the alternative (fallback) logic for DMI probing in the legacy
* ROM region can cause a crash since this region is not pre-validated.
*/
void __init snp_dmi_setup(void)
{
if (efi_enabled(EFI_CONFIG_TABLES))
dmi_setup();
}
static void dump_cpuid_table(void) static void dump_cpuid_table(void)
{ {
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table(); const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* For licencing details see kernel-base/COPYING * For licencing details see kernel-base/COPYING
*/ */
#include <linux/dmi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/export.h> #include <linux/export.h>
...@@ -66,6 +67,7 @@ struct x86_init_ops x86_init __initdata = { ...@@ -66,6 +67,7 @@ struct x86_init_ops x86_init __initdata = {
.probe_roms = probe_roms, .probe_roms = probe_roms,
.reserve_resources = reserve_standard_io_resources, .reserve_resources = reserve_standard_io_resources,
.memory_setup = e820__memory_setup_default, .memory_setup = e820__memory_setup_default,
.dmi_setup = dmi_setup,
}, },
.mpparse = { .mpparse = {
......
...@@ -26,31 +26,18 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, ...@@ -26,31 +26,18 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
for (; addr < end; addr = next) { for (; addr < end; addr = next) {
pud_t *pud = pud_page + pud_index(addr); pud_t *pud = pud_page + pud_index(addr);
pmd_t *pmd; pmd_t *pmd;
bool use_gbpage;
next = (addr & PUD_MASK) + PUD_SIZE; next = (addr & PUD_MASK) + PUD_SIZE;
if (next > end) if (next > end)
next = end; next = end;
/* if this is already a gbpage, this portion is already mapped */ if (info->direct_gbpages) {
if (pud_leaf(*pud))
continue;
/* Is using a gbpage allowed? */
use_gbpage = info->direct_gbpages;
/* Don't use gbpage if it maps more than the requested region. */
/* at the begining: */
use_gbpage &= ((addr & ~PUD_MASK) == 0);
/* ... or at the end: */
use_gbpage &= ((next & ~PUD_MASK) == 0);
/* Never overwrite existing mappings */
use_gbpage &= !pud_present(*pud);
if (use_gbpage) {
pud_t pudval; pud_t pudval;
if (pud_present(*pud))
continue;
addr &= PUD_MASK;
pudval = __pud((addr - info->offset) | info->page_flag); pudval = __pud((addr - info->offset) | info->page_flag);
set_pud(pud, pudval); set_pud(pud, pudval);
continue; continue;
......
...@@ -492,6 +492,24 @@ void __init sme_early_init(void) ...@@ -492,6 +492,24 @@ void __init sme_early_init(void)
*/ */
if (sev_status & MSR_AMD64_SEV_ENABLED) if (sev_status & MSR_AMD64_SEV_ENABLED)
ia32_disable(); ia32_disable();
/*
* Override init functions that scan the ROM region in SEV-SNP guests,
* as this memory is not pre-validated and would thus cause a crash.
*/
if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
x86_init.mpparse.find_mptable = x86_init_noop;
x86_init.pci.init_irq = x86_init_noop;
x86_init.resources.probe_roms = x86_init_noop;
/*
* DMI setup behavior for SEV-SNP guests depends on
* efi_enabled(EFI_CONFIG_TABLES), which hasn't been
* parsed yet. snp_dmi_setup() will run after that
* parsing has happened.
*/
x86_init.resources.dmi_setup = snp_dmi_setup;
}
} }
void __init mem_encrypt_free_decrypted_mem(void) void __init mem_encrypt_free_decrypted_mem(void)
......
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
obj-y += vmx/ obj-y += svm/ vmx/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment