diff options
Diffstat (limited to 'arch/x86/kernel')
130 files changed, 685 insertions, 363 deletions
| diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index fd0a7895b63f..5f70044340ff 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for the linux kernel.  # diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile index 85a9e17e0dbc..f1bb57b0e41e 100644 --- a/arch/x86/kernel/acpi/Makefile +++ b/arch/x86/kernel/acpi/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  OBJECT_FILES_NON_STANDARD_wakeup_$(BITS).o := y  obj-$(CONFIG_ACPI)		+= boot.o diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index ed014814ea35..7188aea91549 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * sleep.c - x86-specific ACPI sleep support.   * diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 65c7b606b606..fbb60ca4255c 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   *	Variables and functions used by the code in sleep.c   */ diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 458da8509b75..6db28f17ff28 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -27,6 +27,8 @@ static const struct pci_device_id amd_root_ids[] = {  	{}  }; +#define PCI_DEVICE_ID_AMD_CNB17H_F4     0x1704 +  const struct pci_device_id amd_nb_misc_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, @@ -37,6 +39,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },  	{}  };  EXPORT_SYMBOL_GPL(amd_nb_misc_ids); @@ -48,6 +51,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },  	{}  }; @@ -402,11 +406,48 @@ void amd_flush_garts(void)  }  EXPORT_SYMBOL_GPL(amd_flush_garts); +static void __fix_erratum_688(void *info) +{ +#define MSR_AMD64_IC_CFG 0xC0011021 + +	msr_set_bit(MSR_AMD64_IC_CFG, 3); +	msr_set_bit(MSR_AMD64_IC_CFG, 14); +} + +/* Apply erratum 688 fix so machines without a BIOS fix work. */ +static __init void fix_erratum_688(void) +{ +	struct pci_dev *F4; +	u32 val; + +	if (boot_cpu_data.x86 != 0x14) +		return; + +	if (!amd_northbridges.num) +		return; + +	F4 = node_to_amd_nb(0)->link; +	if (!F4) +		return; + +	if (pci_read_config_dword(F4, 0x164, &val)) +		return; + +	if (val & BIT(2)) +		return; + +	on_each_cpu(__fix_erratum_688, NULL, 0); + +	pr_info("x86/cpu/AMD: CPU erratum 688 worked around\n"); +} +  static __init int init_amd_nbs(void)  {  	amd_cache_northbridges();  	amd_cache_gart(); +	fix_erratum_688(); +  	return 0;  } diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index ef2859f9fcce..f5d92bc3b884 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Firmware replacement code.   * diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index 8e63ebdcbd0b..2fb7309c6900 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for local APIC drivers and for the IO-APIC code  # diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index d705c769f77d..ff891772c9f8 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -573,11 +573,21 @@ static u32 bdx_deadline_rev(void)  	return ~0U;  } +static u32 skx_deadline_rev(void) +{ +	switch (boot_cpu_data.x86_mask) { +	case 0x03: return 0x01000136; +	case 0x04: return 0x02000014; +	} + +	return ~0U; +} +  static const struct x86_cpu_id deadline_match[] = {  	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_HASWELL_X,	hsx_deadline_rev),  	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_X,	0x0b000020),  	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_XEON_D,	bdx_deadline_rev), -	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_X,	0x02000014), +	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_SKYLAKE_X,	skx_deadline_rev),  	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_CORE,	0x22),  	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_ULT,	0x20), @@ -600,7 +610,8 @@ static void apic_check_deadline_errata(void)  	const struct x86_cpu_id *m;  	u32 rev; -	if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) +	if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) || +	    boot_cpu_has(X86_FEATURE_HYPERVISOR))  		return;  	m = x86_match_cpu(deadline_match); diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 6599f437b4ab..c8d211277315 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * NOOP APIC driver.   * diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 456e45e8bf84..e12fbcfc9571 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.   * diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index d6f387780849..d1fc62a67320 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  HW NMI watchdog support   * diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 70e48aa6af98..3b89b27945ff 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Intel IO-APIC support for multi-Pentium hosts.   * diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index 3a205d4a12d0..82f9244fe61f 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/cpumask.h>  #include <linux/interrupt.h> diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 481237cb1544..e216cf3d64d2 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/threads.h>  #include <linux/cpumask.h>  #include <linux/string.h> diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 3baf0c3dc875..b94d35320f85 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/threads.h>  #include <linux/cpumask.h>  #include <linux/string.h> diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index de827d6ac8c2..8ea78275480d 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Generate definitions needed by assembly language modules.   * This code generates raw asm output which is post-processed to extract diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 710edab9e644..dedf428b20b6 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #ifndef __LINUX_KBUILD_H  # error "Please do not build this file directly, build asm-offsets.c instead"  #endif diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index cf42206926af..630212fa9b9d 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #ifndef __LINUX_KBUILD_H  # error "Please do not build this file directly, build asm-offsets.c instead"  #endif diff --git a/arch/x86/kernel/audit_64.c b/arch/x86/kernel/audit_64.c index f3672508b249..e1efe44ebefc 100644 --- a/arch/x86/kernel/audit_64.c +++ b/arch/x86/kernel/audit_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/init.h>  #include <linux/types.h>  #include <linux/audit.h> diff --git a/arch/x86/kernel/bootflag.c b/arch/x86/kernel/bootflag.c index 52c8e3c7789d..3fed7ae58b60 100644 --- a/arch/x86/kernel/bootflag.c +++ b/arch/x86/kernel/bootflag.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Implement 'Simple Boot Flag Specification 2.0'   */ diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c index 145863d4d343..33399426793e 100644 --- a/arch/x86/kernel/check.c +++ b/arch/x86/kernel/check.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/init.h>  #include <linux/sched.h>  #include <linux/kthread.h> diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index e17942c131c8..236999c54edc 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for x86-compatible CPU details, features and quirks  # @@ -21,7 +22,7 @@ obj-y			+= common.o  obj-y			+= rdrand.o  obj-y			+= match.o  obj-y			+= bugs.o -obj-$(CONFIG_CPU_FREQ)	+= aperfmperf.o +obj-y			+= aperfmperf.o  obj-$(CONFIG_PROC_FS)	+= proc.o  obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9862e2cd6d93..d58184b7cd44 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -763,6 +763,16 @@ static void init_amd_bd(struct cpuinfo_x86 *c)  	}  } +static void init_amd_zn(struct cpuinfo_x86 *c) +{ +	/* +	 * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects +	 * all up to and including B1. +	 */ +	if (c->x86_model <= 1 && c->x86_mask <= 1) +		set_cpu_cap(c, X86_FEATURE_CPB); +} +  static void init_amd(struct cpuinfo_x86 *c)  {  	early_init_amd(c); @@ -791,6 +801,7 @@ static void init_amd(struct cpuinfo_x86 *c)  	case 0x10: init_amd_gh(c); break;  	case 0x12: init_amd_ln(c); break;  	case 0x15: init_amd_bd(c); break; +	case 0x17: init_amd_zn(c); break;  	}  	/* Enable workaround for FXSAVE leak */ diff --git a/arch/x86/kernel/cpu/aperfmperf.c b/arch/x86/kernel/cpu/aperfmperf.c index 0ee83321a313..957813e0180d 100644 --- a/arch/x86/kernel/cpu/aperfmperf.c +++ b/arch/x86/kernel/cpu/aperfmperf.c @@ -42,10 +42,6 @@ static void aperfmperf_snapshot_khz(void *dummy)  	s64 time_delta = ktime_ms_delta(now, s->time);  	unsigned long flags; -	/* Don't bother re-computing within the cache threshold time. */ -	if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS) -		return; -  	local_irq_save(flags);  	rdmsrl(MSR_IA32_APERF, aperf);  	rdmsrl(MSR_IA32_MPERF, mperf); @@ -74,6 +70,7 @@ static void aperfmperf_snapshot_khz(void *dummy)  unsigned int arch_freq_get_on_cpu(int cpu)  { +	s64 time_delta;  	unsigned int khz;  	if (!cpu_khz) @@ -82,6 +79,12 @@ unsigned int arch_freq_get_on_cpu(int cpu)  	if (!static_cpu_has(X86_FEATURE_APERFMPERF))  		return 0; +	/* Don't bother re-computing within the cache threshold time. */ +	time_delta = ktime_ms_delta(ktime_get(), per_cpu(samples.time, cpu)); +	khz = per_cpu(samples.khz, cpu); +	if (khz && time_delta < APERFMPERF_CACHE_THRESHOLD_MS) +		return khz; +  	smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);  	khz = per_cpu(samples.khz, cpu);  	if (khz) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index db684880d74a..ba0b2424c9b0 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (C) 1994  Linus Torvalds   * @@ -21,14 +22,6 @@  void __init check_bugs(void)  { -#ifdef CONFIG_X86_32 -	/* -	 * Regardless of whether PCID is enumerated, the SDM says -	 * that it can't be enabled in 32-bit mode. -	 */ -	setup_clear_cpu_cap(X86_FEATURE_PCID); -#endif -  	identify_boot_cpu();  	if (!IS_ENABLED(CONFIG_SMP)) { diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 44207b71fee1..68bc6d9b3132 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/sched.h>  #include <linux/sched/clock.h> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 775f10100d7f..c9176bae7fd8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -904,6 +904,14 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)  	setup_force_cpu_cap(X86_FEATURE_ALWAYS);  	fpu__init_system(c); + +#ifdef CONFIG_X86_32 +	/* +	 * Regardless of whether PCID is enumerated, the SDM says +	 * that it can't be enabled in 32-bit mode. +	 */ +	setup_clear_cpu_cap(X86_FEATURE_PCID); +#endif  }  void __init early_cpu_init(void) diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 2584265d4745..f52a370b6c00 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef ARCH_X86_CPU_H  #define ARCH_X86_CPU_H diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 6f077445647a..6b4bb335641f 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/bitops.h>  #include <linux/delay.h>  #include <linux/pci.h> diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index dfa90a3a5145..b720dacac051 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 24f749324c0f..54d04d574148 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Routines to identify caches on Intel CPU.   * @@ -831,7 +832,6 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,  	} else if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {  		unsigned int apicid, nshared, first, last; -		this_leaf = this_cpu_ci->info_list + index;  		nshared = base->eax.split.num_threads_sharing + 1;  		apicid = cpu_data(cpu).apicid;  		first = apicid - (apicid % nshared); diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h index ebaddaeef023..a43a72d8e88e 100644 --- a/arch/x86/kernel/cpu/intel_rdt.h +++ b/arch/x86/kernel/cpu/intel_rdt.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef _ASM_X86_INTEL_RDT_H  #define _ASM_X86_INTEL_RDT_H diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index e42117d5f4d7..3fed38812eea 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <asm/cpu_device_id.h>  #include <asm/cpufeature.h>  #include <linux/cpu.h> diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index 43051f0777d4..bcc7c54c7041 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  obj-y				=  mce.o mce-severity.o mce-genpool.o  obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip.o p5.o diff --git a/arch/x86/kernel/cpu/mcheck/dev-mcelog.c b/arch/x86/kernel/cpu/mcheck/dev-mcelog.c index 10cec43aac38..7f85b76f43bc 100644 --- a/arch/x86/kernel/cpu/mcheck/dev-mcelog.c +++ b/arch/x86/kernel/cpu/mcheck/dev-mcelog.c @@ -24,14 +24,6 @@ static DEFINE_MUTEX(mce_chrdev_read_mutex);  static char mce_helper[128];  static char *mce_helper_argv[2] = { mce_helper, NULL }; -#define mce_log_get_idx_check(p) \ -({ \ -	RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held() && \ -			 !lockdep_is_held(&mce_chrdev_read_mutex), \ -			 "suspicious mce_log_get_idx_check() usage"); \ -	smp_load_acquire(&(p)); \ -}) -  /*   * Lockless MCE logging infrastructure.   * This avoids deadlocks on printk locks without having to break locks. Also @@ -53,43 +45,32 @@ static int dev_mce_log(struct notifier_block *nb, unsigned long val,  				void *data)  {  	struct mce *mce = (struct mce *)data; -	unsigned int next, entry; - -	wmb(); -	for (;;) { -		entry = mce_log_get_idx_check(mcelog.next); -		for (;;) { - -			/* -			 * When the buffer fills up discard new entries. -			 * Assume that the earlier errors are the more -			 * interesting ones: -			 */ -			if (entry >= MCE_LOG_LEN) { -				set_bit(MCE_OVERFLOW, -					(unsigned long *)&mcelog.flags); -				return NOTIFY_OK; -			} -			/* Old left over entry. Skip: */ -			if (mcelog.entry[entry].finished) { -				entry++; -				continue; -			} -			break; -		} -		smp_rmb(); -		next = entry + 1; -		if (cmpxchg(&mcelog.next, entry, next) == entry) -			break; +	unsigned int entry; + +	mutex_lock(&mce_chrdev_read_mutex); + +	entry = mcelog.next; + +	/* +	 * When the buffer fills up discard new entries. Assume that the +	 * earlier errors are the more interesting ones: +	 */ +	if (entry >= MCE_LOG_LEN) { +		set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags); +		goto unlock;  	} + +	mcelog.next = entry + 1; +  	memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); -	wmb();  	mcelog.entry[entry].finished = 1; -	wmb();  	/* wake processes polling /dev/mcelog */  	wake_up_interruptible(&mce_chrdev_wait); +unlock: +	mutex_unlock(&mce_chrdev_read_mutex); +  	return NOTIFY_OK;  } @@ -177,13 +158,6 @@ static int mce_chrdev_release(struct inode *inode, struct file *file)  	return 0;  } -static void collect_tscs(void *data) -{ -	unsigned long *cpu_tsc = (unsigned long *)data; - -	cpu_tsc[smp_processor_id()] = rdtsc(); -} -  static int mce_apei_read_done;  /* Collect MCE record of previous boot in persistent storage via APEI ERST. */ @@ -231,14 +205,9 @@ static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,  				size_t usize, loff_t *off)  {  	char __user *buf = ubuf; -	unsigned long *cpu_tsc; -	unsigned prev, next; +	unsigned next;  	int i, err; -	cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL); -	if (!cpu_tsc) -		return -ENOMEM; -  	mutex_lock(&mce_chrdev_read_mutex);  	if (!mce_apei_read_done) { @@ -247,65 +216,29 @@ static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,  			goto out;  	} -	next = mce_log_get_idx_check(mcelog.next); -  	/* Only supports full reads right now */  	err = -EINVAL;  	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce))  		goto out; +	next = mcelog.next;  	err = 0; -	prev = 0; -	do { -		for (i = prev; i < next; i++) { -			unsigned long start = jiffies; -			struct mce *m = &mcelog.entry[i]; - -			while (!m->finished) { -				if (time_after_eq(jiffies, start + 2)) { -					memset(m, 0, sizeof(*m)); -					goto timeout; -				} -				cpu_relax(); -			} -			smp_rmb(); -			err |= copy_to_user(buf, m, sizeof(*m)); -			buf += sizeof(*m); -timeout: -			; -		} - -		memset(mcelog.entry + prev, 0, -		       (next - prev) * sizeof(struct mce)); -		prev = next; -		next = cmpxchg(&mcelog.next, prev, 0); -	} while (next != prev); - -	synchronize_sched(); -	/* -	 * Collect entries that were still getting written before the -	 * synchronize. -	 */ -	on_each_cpu(collect_tscs, cpu_tsc, 1); - -	for (i = next; i < MCE_LOG_LEN; i++) { +	for (i = 0; i < next; i++) {  		struct mce *m = &mcelog.entry[i]; -		if (m->finished && m->tsc < cpu_tsc[m->cpu]) { -			err |= copy_to_user(buf, m, sizeof(*m)); -			smp_rmb(); -			buf += sizeof(*m); -			memset(m, 0, sizeof(*m)); -		} +		err |= copy_to_user(buf, m, sizeof(*m)); +		buf += sizeof(*m);  	} +	memset(mcelog.entry, 0, next * sizeof(struct mce)); +	mcelog.next = 0; +  	if (err)  		err = -EFAULT;  out:  	mutex_unlock(&mce_chrdev_read_mutex); -	kfree(cpu_tsc);  	return err ? err : buf - ubuf;  } diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h index 098530a93bb7..aa0d5df9dc60 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h @@ -1,3 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __X86_MCE_INTERNAL_H__ +#define __X86_MCE_INTERNAL_H__ +  #include <linux/device.h>  #include <asm/mce.h> @@ -108,3 +112,7 @@ static inline void mce_work_trigger(void)	{ }  static inline void mce_register_injector_chain(struct notifier_block *nb)	{ }  static inline void mce_unregister_injector_chain(struct notifier_block *nb)	{ }  #endif + +extern struct mca_config mca_cfg; + +#endif /* __X86_MCE_INTERNAL_H__ */ diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 40e28ed77fbf..486f640b02ef 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -28,6 +28,8 @@  #include <asm/msr.h>  #include <asm/trace/irq_vectors.h> +#include "mce-internal.h" +  #define NR_BLOCKS         5  #define THRESHOLD_MAX     0xFFF  #define INT_TYPE_APIC     0x00020000 diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index e84db79ef272..d05be307d081 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Intel specific MCE features.   * Copyright 2004 Zwane Mwaikambo <[email protected]> diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index 2a0717bf8033..5cddf831720f 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * P5 specific Machine Check Exception Reporting   * (C) Copyright 2002 Alan Cox <[email protected]> diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index 5e7249e42f8f..2b584b319eff 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Common corrected MCE threshold handler code:   */ diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index c6a722e1d011..3b45b270a865 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * IDT Winchip specific Machine Check Exception Reporting   * (C) Copyright 2002 Alan Cox <[email protected]> diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 86e8f0b2537b..c4fa4a85d4cb 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -122,9 +122,6 @@ static bool __init check_loader_disabled_bsp(void)  	bool *res = &dis_ucode_ldr;  #endif -	if (!have_cpuid_p()) -		return *res; -  	/*  	 * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not  	 * completely accurate as xen pv guests don't see that CPUID bit set but @@ -166,24 +163,36 @@ bool get_builtin_firmware(struct cpio_data *cd, const char *name)  void __init load_ucode_bsp(void)  {  	unsigned int cpuid_1_eax; +	bool intel = true; -	if (check_loader_disabled_bsp()) +	if (!have_cpuid_p())  		return;  	cpuid_1_eax = native_cpuid_eax(1);  	switch (x86_cpuid_vendor()) {  	case X86_VENDOR_INTEL: -		if (x86_family(cpuid_1_eax) >= 6) -			load_ucode_intel_bsp(); +		if (x86_family(cpuid_1_eax) < 6) +			return;  		break; +  	case X86_VENDOR_AMD: -		if (x86_family(cpuid_1_eax) >= 0x10) -			load_ucode_amd_bsp(cpuid_1_eax); +		if (x86_family(cpuid_1_eax) < 0x10) +			return; +		intel = false;  		break; +  	default: -		break; +		return;  	} + +	if (check_loader_disabled_bsp()) +		return; + +	if (intel) +		load_ucode_intel_bsp(); +	else +		load_ucode_amd_bsp(cpuid_1_eax);  }  static bool check_loader_disabled_ap(void) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 8f7a9bbad514..7dbcb7adf797 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -34,6 +34,7 @@  #include <linux/mm.h>  #include <asm/microcode_intel.h> +#include <asm/intel-family.h>  #include <asm/processor.h>  #include <asm/tlbflush.h>  #include <asm/setup.h> @@ -918,6 +919,18 @@ static int get_ucode_fw(void *to, const void *from, size_t n)  	return 0;  } +static bool is_blacklisted(unsigned int cpu) +{ +	struct cpuinfo_x86 *c = &cpu_data(cpu); + +	if (c->x86 == 6 && c->x86_model == INTEL_FAM6_BROADWELL_X) { +		pr_err_once("late loading on model 79 is disabled.\n"); +		return true; +	} + +	return false; +} +  static enum ucode_state request_microcode_fw(int cpu, struct device *device,  					     bool refresh_fw)  { @@ -926,6 +939,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,  	const struct firmware *firmware;  	enum ucode_state ret; +	if (is_blacklisted(cpu)) +		return UCODE_NFOUND; +  	sprintf(name, "intel-ucode/%02x-%02x-%02x",  		c->x86, c->x86_model, c->x86_mask); @@ -950,6 +966,9 @@ static int get_ucode_user(void *to, const void *from, size_t n)  static enum ucode_state  request_microcode_user(int cpu, const void __user *buf, size_t size)  { +	if (is_blacklisted(cpu)) +		return UCODE_NFOUND; +  	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);  } diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh index 6988c74409a8..d0dfb892c72f 100644 --- a/arch/x86/kernel/cpu/mkcapflags.sh +++ b/arch/x86/kernel/cpu/mkcapflags.sh @@ -1,4 +1,5 @@  #!/bin/sh +# SPDX-License-Identifier: GPL-2.0  #  # Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h  # diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c index 92ba9cd31c9a..a65a0272096d 100644 --- a/arch/x86/kernel/cpu/mtrr/amd.c +++ b/arch/x86/kernel/cpu/mtrr/amd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/init.h>  #include <linux/mm.h>  #include <asm/mtrr.h> diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c index 3d689937fc1b..f27177816569 100644 --- a/arch/x86/kernel/cpu/mtrr/centaur.c +++ b/arch/x86/kernel/cpu/mtrr/centaur.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/init.h>  #include <linux/mm.h> diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index b1086f79e57e..4296c702a3f7 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/init.h>  #include <linux/io.h>  #include <linux/mm.h> diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 6d9b45549109..558444b23923 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/capability.h>  #include <linux/seq_file.h>  #include <linux/uaccess.h> diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index ad8bd763efa5..2ac99e561181 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   * local MTRR defines.   */ diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 181eabecae25..d389083330c5 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * local apic based NMI watchdog for various CPUs.   * diff --git a/arch/x86/kernel/cpu/powerflags.c b/arch/x86/kernel/cpu/powerflags.c index 1dd8294fd730..fd6ec2aa0303 100644 --- a/arch/x86/kernel/cpu/powerflags.c +++ b/arch/x86/kernel/cpu/powerflags.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Strings for the various x86 power flags   * diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 218f79825b3c..4378a729b933 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -1,7 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/smp.h>  #include <linux/timex.h>  #include <linux/string.h>  #include <linux/seq_file.h> +#include <linux/cpufreq.h>  /*   *	Get CPU information for use by the procfs. @@ -75,9 +77,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)  	if (c->microcode)  		seq_printf(m, "microcode\t: 0x%x\n", c->microcode); -	if (cpu_has(c, X86_FEATURE_TSC)) +	if (cpu_has(c, X86_FEATURE_TSC)) { +		unsigned int freq = arch_freq_get_on_cpu(cpu); + +		if (!freq) +			freq = cpufreq_quick_get(cpu); +		if (!freq) +			freq = cpu_khz;  		seq_printf(m, "cpu MHz\t\t: %u.%03u\n", -			   cpu_khz / 1000, (cpu_khz % 1000)); +			   freq / 1000, (freq % 1000)); +	}  	/* Cache size */  	if (c->x86_cache_size >= 0) diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index cd531355e838..b099024d339c 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Check for extended topology enumeration cpuid leaf 0xb and if it   * exists, use it for populating initial_apicid and cpu topology diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index d77d07ab310b..42c939827621 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <linux/sched.h>  #include <linux/sched/clock.h> diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index ef9c2a0078bd..65a58a390fc3 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <asm/processor.h>  #include "cpu.h" diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c index 538fedea9b3f..33ee47670b99 100644 --- a/arch/x86/kernel/crash_dump_32.c +++ b/arch/x86/kernel/crash_dump_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Memory preserving reboot related code.   * diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index afa64adb75ee..4f2e0778feac 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Memory preserving reboot related code.   * diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index cbf1f6ba39a8..76e07698e6d1 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Architecture specific OF callbacks.   */ diff --git a/arch/x86/kernel/doublefault.c b/arch/x86/kernel/doublefault.c index f9c324e08d85..0e662c55ae90 100644 --- a/arch/x86/kernel/doublefault.c +++ b/arch/x86/kernel/doublefault.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/mm.h>  #include <linux/sched.h>  #include <linux/sched/debug.h> diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 4f0481474903..daefae83a3aa 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (C) 1991, 1992  Linus Torvalds   *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 225af4184f06..88ce2ffdb110 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (C) 1991, 1992  Linus Torvalds   *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 927abeaf63e2..1e82f787c160 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /* Various workarounds for chipset bugs.     This code runs very early and can't use the regular PCI subsystem     The entries are keyed to PCI bridges which usually identify chipsets diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 0f0840304452..5e801c8c8ce7 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/console.h>  #include <linux/kernel.h>  #include <linux/init.h> diff --git a/arch/x86/kernel/ebda.c b/arch/x86/kernel/ebda.c index 4312f8ae71b7..38e7d597b660 100644 --- a/arch/x86/kernel/ebda.c +++ b/arch/x86/kernel/ebda.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/memblock.h> diff --git a/arch/x86/kernel/fpu/bugs.c b/arch/x86/kernel/fpu/bugs.c index d913047f832c..2954fab15e51 100644 --- a/arch/x86/kernel/fpu/bugs.c +++ b/arch/x86/kernel/fpu/bugs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * x86 FPU bug checks:   */ diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index e1114f070c2d..f92a6593de1e 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -100,7 +100,7 @@ void __kernel_fpu_begin(void)  	kernel_fpu_disable(); -	if (fpu->fpregs_active) { +	if (fpu->initialized) {  		/*  		 * Ignore return value -- we don't care if reg state  		 * is clobbered. @@ -116,7 +116,7 @@ void __kernel_fpu_end(void)  {  	struct fpu *fpu = ¤t->thread.fpu; -	if (fpu->fpregs_active) +	if (fpu->initialized)  		copy_kernel_to_fpregs(&fpu->state);  	kernel_fpu_enable(); @@ -148,7 +148,7 @@ void fpu__save(struct fpu *fpu)  	preempt_disable();  	trace_x86_fpu_before_save(fpu); -	if (fpu->fpregs_active) { +	if (fpu->initialized) {  		if (!copy_fpregs_to_fpstate(fpu)) {  			copy_kernel_to_fpregs(&fpu->state);  		} @@ -189,10 +189,9 @@ EXPORT_SYMBOL_GPL(fpstate_init);  int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)  { -	dst_fpu->fpregs_active = 0;  	dst_fpu->last_cpu = -1; -	if (!src_fpu->fpstate_active || !static_cpu_has(X86_FEATURE_FPU)) +	if (!src_fpu->initialized || !static_cpu_has(X86_FEATURE_FPU))  		return 0;  	WARN_ON_FPU(src_fpu != ¤t->thread.fpu); @@ -206,26 +205,14 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)  	/*  	 * Save current FPU registers directly into the child  	 * FPU context, without any memory-to-memory copying. -	 * In lazy mode, if the FPU context isn't loaded into -	 * fpregs, CR0.TS will be set and do_device_not_available -	 * will load the FPU context.  	 * -	 * We have to do all this with preemption disabled, -	 * mostly because of the FNSAVE case, because in that -	 * case we must not allow preemption in the window -	 * between the FNSAVE and us marking the context lazy. -	 * -	 * It shouldn't be an issue as even FNSAVE is plenty -	 * fast in terms of critical section length. +	 * ( The function 'fails' in the FNSAVE case, which destroys +	 *   register contents so we have to copy them back. )  	 */ -	preempt_disable();  	if (!copy_fpregs_to_fpstate(dst_fpu)) { -		memcpy(&src_fpu->state, &dst_fpu->state, -		       fpu_kernel_xstate_size); - +		memcpy(&src_fpu->state, &dst_fpu->state, fpu_kernel_xstate_size);  		copy_kernel_to_fpregs(&src_fpu->state);  	} -	preempt_enable();  	trace_x86_fpu_copy_src(src_fpu);  	trace_x86_fpu_copy_dst(dst_fpu); @@ -237,45 +224,48 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)   * Activate the current task's in-memory FPU context,   * if it has not been used before:   */ -void fpu__activate_curr(struct fpu *fpu) +void fpu__initialize(struct fpu *fpu)  {  	WARN_ON_FPU(fpu != ¤t->thread.fpu); -	if (!fpu->fpstate_active) { +	if (!fpu->initialized) {  		fpstate_init(&fpu->state);  		trace_x86_fpu_init_state(fpu);  		trace_x86_fpu_activate_state(fpu);  		/* Safe to do for the current task: */ -		fpu->fpstate_active = 1; +		fpu->initialized = 1;  	}  } -EXPORT_SYMBOL_GPL(fpu__activate_curr); +EXPORT_SYMBOL_GPL(fpu__initialize);  /*   * This function must be called before we read a task's fpstate.   * - * If the task has not used the FPU before then initialize its - * fpstate. + * There's two cases where this gets called: + * + * - for the current task (when coredumping), in which case we have + *   to save the latest FPU registers into the fpstate, + * + * - or it's called for stopped tasks (ptrace), in which case the + *   registers were already saved by the context-switch code when + *   the task scheduled out - we only have to initialize the registers + *   if they've never been initialized.   *   * If the task has used the FPU before then save it.   */ -void fpu__activate_fpstate_read(struct fpu *fpu) +void fpu__prepare_read(struct fpu *fpu)  { -	/* -	 * If fpregs are active (in the current CPU), then -	 * copy them to the fpstate: -	 */ -	if (fpu->fpregs_active) { +	if (fpu == ¤t->thread.fpu) {  		fpu__save(fpu);  	} else { -		if (!fpu->fpstate_active) { +		if (!fpu->initialized) {  			fpstate_init(&fpu->state);  			trace_x86_fpu_init_state(fpu);  			trace_x86_fpu_activate_state(fpu);  			/* Safe to do for current and for stopped child tasks: */ -			fpu->fpstate_active = 1; +			fpu->initialized = 1;  		}  	}  } @@ -283,17 +273,17 @@ void fpu__activate_fpstate_read(struct fpu *fpu)  /*   * This function must be called before we write a task's fpstate.   * - * If the task has used the FPU before then unlazy it. + * If the task has used the FPU before then invalidate any cached FPU registers.   * If the task has not used the FPU before then initialize its fpstate.   *   * After this function call, after registers in the fpstate are   * modified and the child task has woken up, the child task will   * restore the modified FPU state from the modified context. If we - * didn't clear its lazy status here then the lazy in-registers + * didn't clear its cached status here then the cached in-registers   * state pending on its former CPU could be restored, corrupting   * the modifications.   */ -void fpu__activate_fpstate_write(struct fpu *fpu) +void fpu__prepare_write(struct fpu *fpu)  {  	/*  	 * Only stopped child tasks can be used to modify the FPU @@ -301,8 +291,8 @@ void fpu__activate_fpstate_write(struct fpu *fpu)  	 */  	WARN_ON_FPU(fpu == ¤t->thread.fpu); -	if (fpu->fpstate_active) { -		/* Invalidate any lazy state: */ +	if (fpu->initialized) { +		/* Invalidate any cached state: */  		__fpu_invalidate_fpregs_state(fpu);  	} else {  		fpstate_init(&fpu->state); @@ -310,74 +300,11 @@ void fpu__activate_fpstate_write(struct fpu *fpu)  		trace_x86_fpu_activate_state(fpu);  		/* Safe to do for stopped child tasks: */ -		fpu->fpstate_active = 1; +		fpu->initialized = 1;  	}  }  /* - * This function must be called before we write the current - * task's fpstate. - * - * This call gets the current FPU register state and moves - * it in to the 'fpstate'.  Preemption is disabled so that - * no writes to the 'fpstate' can occur from context - * swiches. - * - * Must be followed by a fpu__current_fpstate_write_end(). - */ -void fpu__current_fpstate_write_begin(void) -{ -	struct fpu *fpu = ¤t->thread.fpu; - -	/* -	 * Ensure that the context-switching code does not write -	 * over the fpstate while we are doing our update. -	 */ -	preempt_disable(); - -	/* -	 * Move the fpregs in to the fpu's 'fpstate'. -	 */ -	fpu__activate_fpstate_read(fpu); - -	/* -	 * The caller is about to write to 'fpu'.  Ensure that no -	 * CPU thinks that its fpregs match the fpstate.  This -	 * ensures we will not be lazy and skip a XRSTOR in the -	 * future. -	 */ -	__fpu_invalidate_fpregs_state(fpu); -} - -/* - * This function must be paired with fpu__current_fpstate_write_begin() - * - * This will ensure that the modified fpstate gets placed back in - * the fpregs if necessary. - * - * Note: This function may be called whether or not an _actual_ - * write to the fpstate occurred. - */ -void fpu__current_fpstate_write_end(void) -{ -	struct fpu *fpu = ¤t->thread.fpu; - -	/* -	 * 'fpu' now has an updated copy of the state, but the -	 * registers may still be out of date.  Update them with -	 * an XRSTOR if they are active. -	 */ -	if (fpregs_active()) -		copy_kernel_to_fpregs(&fpu->state); - -	/* -	 * Our update is done and the fpregs/fpstate are in sync -	 * if necessary.  Context switches can happen again. -	 */ -	preempt_enable(); -} - -/*   * 'fpu__restore()' is called to copy FPU registers from   * the FPU fpstate to the live hw registers and to activate   * access to the hardware registers, so that FPU instructions @@ -389,7 +316,7 @@ void fpu__current_fpstate_write_end(void)   */  void fpu__restore(struct fpu *fpu)  { -	fpu__activate_curr(fpu); +	fpu__initialize(fpu);  	/* Avoid __kernel_fpu_begin() right after fpregs_activate() */  	kernel_fpu_disable(); @@ -414,15 +341,17 @@ void fpu__drop(struct fpu *fpu)  {  	preempt_disable(); -	if (fpu->fpregs_active) { -		/* Ignore delayed exceptions from user space */ -		asm volatile("1: fwait\n" -			     "2:\n" -			     _ASM_EXTABLE(1b, 2b)); -		fpregs_deactivate(fpu); +	if (fpu == ¤t->thread.fpu) { +		if (fpu->initialized) { +			/* Ignore delayed exceptions from user space */ +			asm volatile("1: fwait\n" +				     "2:\n" +				     _ASM_EXTABLE(1b, 2b)); +			fpregs_deactivate(fpu); +		}  	} -	fpu->fpstate_active = 0; +	fpu->initialized = 0;  	trace_x86_fpu_dropped(fpu); @@ -462,9 +391,11 @@ void fpu__clear(struct fpu *fpu)  	 * Make sure fpstate is cleared and initialized.  	 */  	if (static_cpu_has(X86_FEATURE_FPU)) { -		fpu__activate_curr(fpu); +		preempt_disable(); +		fpu__initialize(fpu);  		user_fpu_begin();  		copy_init_fpstate_to_fpregs(); +		preempt_enable();  	}  } diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index d5d44c452624..7affb7e3d9a5 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -240,7 +240,7 @@ static void __init fpu__init_system_ctx_switch(void)  	WARN_ON_FPU(!on_boot_cpu);  	on_boot_cpu = 0; -	WARN_ON_FPU(current->thread.fpu.fpstate_active); +	WARN_ON_FPU(current->thread.fpu.initialized);  }  /* diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index b188b16841e3..bc02f5144b95 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * FPU register's regset abstraction, for ptrace, core dumps, etc.   */ @@ -16,14 +17,14 @@ int regset_fpregs_active(struct task_struct *target, const struct user_regset *r  {  	struct fpu *target_fpu = &target->thread.fpu; -	return target_fpu->fpstate_active ? regset->n : 0; +	return target_fpu->initialized ? regset->n : 0;  }  int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset)  {  	struct fpu *target_fpu = &target->thread.fpu; -	if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->fpstate_active) +	if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->initialized)  		return regset->n;  	else  		return 0; @@ -38,7 +39,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,  	if (!boot_cpu_has(X86_FEATURE_FXSR))  		return -ENODEV; -	fpu__activate_fpstate_read(fpu); +	fpu__prepare_read(fpu);  	fpstate_sanitize_xstate(fpu);  	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, @@ -55,7 +56,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,  	if (!boot_cpu_has(X86_FEATURE_FXSR))  		return -ENODEV; -	fpu__activate_fpstate_write(fpu); +	fpu__prepare_write(fpu);  	fpstate_sanitize_xstate(fpu);  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, @@ -89,10 +90,13 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,  	xsave = &fpu->state.xsave; -	fpu__activate_fpstate_read(fpu); +	fpu__prepare_read(fpu);  	if (using_compacted_format()) { -		ret = copyout_from_xsaves(pos, count, kbuf, ubuf, xsave); +		if (kbuf) +			ret = copy_xstate_to_kernel(kbuf, xsave, pos, count); +		else +			ret = copy_xstate_to_user(ubuf, xsave, pos, count);  	} else {  		fpstate_sanitize_xstate(fpu);  		/* @@ -129,28 +133,29 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,  	xsave = &fpu->state.xsave; -	fpu__activate_fpstate_write(fpu); +	fpu__prepare_write(fpu); -	if (boot_cpu_has(X86_FEATURE_XSAVES)) -		ret = copyin_to_xsaves(kbuf, ubuf, xsave); -	else +	if (using_compacted_format()) { +		if (kbuf) +			ret = copy_kernel_to_xstate(xsave, kbuf); +		else +			ret = copy_user_to_xstate(xsave, ubuf); +	} else {  		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); - -	/* -	 * In case of failure, mark all states as init: -	 */ -	if (ret) -		fpstate_init(&fpu->state); +		if (!ret) +			ret = validate_xstate_header(&xsave->header); +	}  	/*  	 * mxcsr reserved bits must be masked to zero for security reasons.  	 */  	xsave->i387.mxcsr &= mxcsr_feature_mask; -	xsave->header.xfeatures &= xfeatures_mask; +  	/* -	 * These bits must be zero. +	 * In case of failure, mark all states as init:  	 */ -	memset(&xsave->header.reserved, 0, 48); +	if (ret) +		fpstate_init(&fpu->state);  	return ret;  } @@ -299,7 +304,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,  	struct fpu *fpu = &target->thread.fpu;  	struct user_i387_ia32_struct env; -	fpu__activate_fpstate_read(fpu); +	fpu__prepare_read(fpu);  	if (!boot_cpu_has(X86_FEATURE_FPU))  		return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf); @@ -329,7 +334,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,  	struct user_i387_ia32_struct env;  	int ret; -	fpu__activate_fpstate_write(fpu); +	fpu__prepare_write(fpu);  	fpstate_sanitize_xstate(fpu);  	if (!boot_cpu_has(X86_FEATURE_FPU)) @@ -369,7 +374,7 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu)  	struct fpu *fpu = &tsk->thread.fpu;  	int fpvalid; -	fpvalid = fpu->fpstate_active; +	fpvalid = fpu->initialized;  	if (fpvalid)  		fpvalid = !fpregs_get(tsk, NULL,  				      0, sizeof(struct user_i387_ia32_struct), diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 83c23c230b4c..23f1691670b6 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * FPU signal frame handling routines.   */ @@ -155,7 +156,8 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)   */  int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)  { -	struct xregs_state *xsave = ¤t->thread.fpu.state.xsave; +	struct fpu *fpu = ¤t->thread.fpu; +	struct xregs_state *xsave = &fpu->state.xsave;  	struct task_struct *tsk = current;  	int ia32_fxstate = (buf != buf_fx); @@ -170,13 +172,13 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)  			sizeof(struct user_i387_ia32_struct), NULL,  			(struct _fpstate_32 __user *) buf) ? -1 : 1; -	if (fpregs_active() || using_compacted_format()) { +	if (fpu->initialized || using_compacted_format()) {  		/* Save the live register state to the user directly. */  		if (copy_fpregs_to_sigframe(buf_fx))  			return -1;  		/* Update the thread's fxstate to save the fsave header. */  		if (ia32_fxstate) -			copy_fxregs_to_kernel(&tsk->thread.fpu); +			copy_fxregs_to_kernel(fpu);  	} else {  		/*  		 * It is a *bug* if kernel uses compacted-format for xsave @@ -189,7 +191,7 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)  			return -1;  		} -		fpstate_sanitize_xstate(&tsk->thread.fpu); +		fpstate_sanitize_xstate(fpu);  		if (__copy_to_user(buf_fx, xsave, fpu_user_xstate_size))  			return -1;  	} @@ -213,8 +215,11 @@ sanitize_restored_xstate(struct task_struct *tsk,  	struct xstate_header *header = &xsave->header;  	if (use_xsave()) { -		/* These bits must be zero. */ -		memset(header->reserved, 0, 48); +		/* +		 * Note: we don't need to zero the reserved bits in the +		 * xstate_header here because we either didn't copy them at all, +		 * or we checked earlier that they aren't set. +		 */  		/*  		 * Init the state that is not present in the memory @@ -223,7 +228,7 @@ sanitize_restored_xstate(struct task_struct *tsk,  		if (fx_only)  			header->xfeatures = XFEATURE_MASK_FPSSE;  		else -			header->xfeatures &= (xfeatures_mask & xfeatures); +			header->xfeatures &= xfeatures;  	}  	if (use_fxsr()) { @@ -279,7 +284,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)  	if (!access_ok(VERIFY_READ, buf, size))  		return -EACCES; -	fpu__activate_curr(fpu); +	fpu__initialize(fpu);  	if (!static_cpu_has(X86_FEATURE_FPU))  		return fpregs_soft_set(current, NULL, @@ -307,28 +312,29 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)  		/*  		 * For 32-bit frames with fxstate, copy the user state to the  		 * thread's fpu state, reconstruct fxstate from the fsave -		 * header. Sanitize the copied state etc. +		 * header. Validate and sanitize the copied state.  		 */  		struct fpu *fpu = &tsk->thread.fpu;  		struct user_i387_ia32_struct env;  		int err = 0;  		/* -		 * Drop the current fpu which clears fpu->fpstate_active. This ensures +		 * Drop the current fpu which clears fpu->initialized. This ensures  		 * that any context-switch during the copy of the new state,  		 * avoids the intermediate state from getting restored/saved.  		 * Thus avoiding the new restored state from getting corrupted.  		 * We will be ready to restore/save the state only after -		 * fpu->fpstate_active is again set. +		 * fpu->initialized is again set.  		 */  		fpu__drop(fpu);  		if (using_compacted_format()) { -			err = copyin_to_xsaves(NULL, buf_fx, -					       &fpu->state.xsave); +			err = copy_user_to_xstate(&fpu->state.xsave, buf_fx);  		} else { -			err = __copy_from_user(&fpu->state.xsave, -					       buf_fx, state_size); +			err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size); + +			if (!err && state_size > offsetof(struct xregs_state, header)) +				err = validate_xstate_header(&fpu->state.xsave.header);  		}  		if (err || __copy_from_user(&env, buf, sizeof(env))) { @@ -339,7 +345,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)  			sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);  		} -		fpu->fpstate_active = 1; +		fpu->initialized = 1;  		preempt_disable();  		fpu__restore(fpu);  		preempt_enable(); diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index c24ac1efb12d..f1d5476c9022 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -483,6 +483,30 @@ int using_compacted_format(void)  	return boot_cpu_has(X86_FEATURE_XSAVES);  } +/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */ +int validate_xstate_header(const struct xstate_header *hdr) +{ +	/* No unknown or supervisor features may be set */ +	if (hdr->xfeatures & (~xfeatures_mask | XFEATURE_MASK_SUPERVISOR)) +		return -EINVAL; + +	/* Userspace must use the uncompacted format */ +	if (hdr->xcomp_bv) +		return -EINVAL; + +	/* +	 * If 'reserved' is shrunken to add a new field, make sure to validate +	 * that new field here! +	 */ +	BUILD_BUG_ON(sizeof(hdr->reserved) != 48); + +	/* No reserved bits may be set */ +	if (memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved))) +		return -EINVAL; + +	return 0; +} +  static void __xstate_dump_leaves(void)  {  	int i; @@ -867,7 +891,7 @@ const void *get_xsave_field_ptr(int xsave_state)  {  	struct fpu *fpu = ¤t->thread.fpu; -	if (!fpu->fpstate_active) +	if (!fpu->initialized)  		return NULL;  	/*  	 * fpu__save() takes the CPU's xstate registers @@ -921,38 +945,129 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,  #endif /* ! CONFIG_ARCH_HAS_PKEYS */  /* + * Weird legacy quirk: SSE and YMM states store information in the + * MXCSR and MXCSR_FLAGS fields of the FP area. That means if the FP + * area is marked as unused in the xfeatures header, we need to copy + * MXCSR and MXCSR_FLAGS if either SSE or YMM are in use. + */ +static inline bool xfeatures_mxcsr_quirk(u64 xfeatures) +{ +	if (!(xfeatures & (XFEATURE_MASK_SSE|XFEATURE_MASK_YMM))) +		return false; + +	if (xfeatures & XFEATURE_MASK_FP) +		return false; + +	return true; +} + +/*   * This is similar to user_regset_copyout(), but will not add offset to   * the source data pointer or increment pos, count, kbuf, and ubuf.   */ -static inline int xstate_copyout(unsigned int pos, unsigned int count, -				 void *kbuf, void __user *ubuf, -				 const void *data, const int start_pos, -				 const int end_pos) +static inline void +__copy_xstate_to_kernel(void *kbuf, const void *data, +			unsigned int offset, unsigned int size, unsigned int size_total)  { -	if ((count == 0) || (pos < start_pos)) -		return 0; +	if (offset < size_total) { +		unsigned int copy = min(size, size_total - offset); -	if (end_pos < 0 || pos < end_pos) { -		unsigned int copy = (end_pos < 0 ? count : min(count, end_pos - pos)); +		memcpy(kbuf + offset, data, copy); +	} +} -		if (kbuf) { -			memcpy(kbuf + pos, data, copy); -		} else { -			if (__copy_to_user(ubuf + pos, data, copy)) -				return -EFAULT; +/* + * Convert from kernel XSAVES compacted format to standard format and copy + * to a kernel-space ptrace buffer. + * + * It supports partial copy but pos always starts from zero. This is called + * from xstateregs_get() and there we check the CPU has XSAVES. + */ +int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total) +{ +	unsigned int offset, size; +	struct xstate_header header; +	int i; + +	/* +	 * Currently copy_regset_to_user() starts from pos 0: +	 */ +	if (unlikely(offset_start != 0)) +		return -EFAULT; + +	/* +	 * The destination is a ptrace buffer; we put in only user xstates: +	 */ +	memset(&header, 0, sizeof(header)); +	header.xfeatures = xsave->header.xfeatures; +	header.xfeatures &= ~XFEATURE_MASK_SUPERVISOR; + +	/* +	 * Copy xregs_state->header: +	 */ +	offset = offsetof(struct xregs_state, header); +	size = sizeof(header); + +	__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total); + +	for (i = 0; i < XFEATURE_MAX; i++) { +		/* +		 * Copy only in-use xstates: +		 */ +		if ((header.xfeatures >> i) & 1) { +			void *src = __raw_xsave_addr(xsave, 1 << i); + +			offset = xstate_offsets[i]; +			size = xstate_sizes[i]; + +			/* The next component has to fit fully into the output buffer: */ +			if (offset + size > size_total) +				break; + +			__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);  		} + +	} + +	if (xfeatures_mxcsr_quirk(header.xfeatures)) { +		offset = offsetof(struct fxregs_state, mxcsr); +		size = MXCSR_AND_FLAGS_SIZE; +		__copy_xstate_to_kernel(kbuf, &xsave->i387.mxcsr, offset, size, size_total); +	} + +	/* +	 * Fill xsave->i387.sw_reserved value for ptrace frame: +	 */ +	offset = offsetof(struct fxregs_state, sw_reserved); +	size = sizeof(xstate_fx_sw_bytes); + +	__copy_xstate_to_kernel(kbuf, xstate_fx_sw_bytes, offset, size, size_total); + +	return 0; +} + +static inline int +__copy_xstate_to_user(void __user *ubuf, const void *data, unsigned int offset, unsigned int size, unsigned int size_total) +{ +	if (!size) +		return 0; + +	if (offset < size_total) { +		unsigned int copy = min(size, size_total - offset); + +		if (__copy_to_user(ubuf + offset, data, copy)) +			return -EFAULT;  	}  	return 0;  }  /*   * Convert from kernel XSAVES compacted format to standard format and copy - * to a ptrace buffer. It supports partial copy but pos always starts from + * to a user-space buffer. It supports partial copy but pos always starts from   * zero. This is called from xstateregs_get() and there we check the CPU   * has XSAVES.   */ -int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf, -			void __user *ubuf, struct xregs_state *xsave) +int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)  {  	unsigned int offset, size;  	int ret, i; @@ -961,7 +1076,7 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,  	/*  	 * Currently copy_regset_to_user() starts from pos 0:  	 */ -	if (unlikely(pos != 0)) +	if (unlikely(offset_start != 0))  		return -EFAULT;  	/* @@ -977,8 +1092,7 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,  	offset = offsetof(struct xregs_state, header);  	size = sizeof(header); -	ret = xstate_copyout(offset, size, kbuf, ubuf, &header, 0, count); - +	ret = __copy_xstate_to_user(ubuf, &header, offset, size, size_total);  	if (ret)  		return ret; @@ -992,25 +1106,30 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,  			offset = xstate_offsets[i];  			size = xstate_sizes[i]; -			ret = xstate_copyout(offset, size, kbuf, ubuf, src, 0, count); +			/* The next component has to fit fully into the output buffer: */ +			if (offset + size > size_total) +				break; +			ret = __copy_xstate_to_user(ubuf, src, offset, size, size_total);  			if (ret)  				return ret; - -			if (offset + size >= count) -				break;  		}  	} +	if (xfeatures_mxcsr_quirk(header.xfeatures)) { +		offset = offsetof(struct fxregs_state, mxcsr); +		size = MXCSR_AND_FLAGS_SIZE; +		__copy_xstate_to_user(ubuf, &xsave->i387.mxcsr, offset, size, size_total); +	} +  	/*  	 * Fill xsave->i387.sw_reserved value for ptrace frame:  	 */  	offset = offsetof(struct fxregs_state, sw_reserved);  	size = sizeof(xstate_fx_sw_bytes); -	ret = xstate_copyout(offset, size, kbuf, ubuf, xstate_fx_sw_bytes, 0, count); - +	ret = __copy_xstate_to_user(ubuf, xstate_fx_sw_bytes, offset, size, size_total);  	if (ret)  		return ret; @@ -1018,55 +1137,98 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,  }  /* - * Convert from a ptrace standard-format buffer to kernel XSAVES format - * and copy to the target thread. This is called from xstateregs_set() and - * there we check the CPU has XSAVES and a whole standard-sized buffer - * exists. + * Convert from a ptrace standard-format kernel buffer to kernel XSAVES format + * and copy to the target thread. This is called from xstateregs_set().   */ -int copyin_to_xsaves(const void *kbuf, const void __user *ubuf, -		     struct xregs_state *xsave) +int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)  {  	unsigned int offset, size;  	int i; -	u64 xfeatures; -	u64 allowed_features; +	struct xstate_header hdr;  	offset = offsetof(struct xregs_state, header); -	size = sizeof(xfeatures); +	size = sizeof(hdr); -	if (kbuf) { -		memcpy(&xfeatures, kbuf + offset, size); -	} else { -		if (__copy_from_user(&xfeatures, ubuf + offset, size)) -			return -EFAULT; +	memcpy(&hdr, kbuf + offset, size); + +	if (validate_xstate_header(&hdr)) +		return -EINVAL; + +	for (i = 0; i < XFEATURE_MAX; i++) { +		u64 mask = ((u64)1 << i); + +		if (hdr.xfeatures & mask) { +			void *dst = __raw_xsave_addr(xsave, 1 << i); + +			offset = xstate_offsets[i]; +			size = xstate_sizes[i]; + +			memcpy(dst, kbuf + offset, size); +		} +	} + +	if (xfeatures_mxcsr_quirk(hdr.xfeatures)) { +		offset = offsetof(struct fxregs_state, mxcsr); +		size = MXCSR_AND_FLAGS_SIZE; +		memcpy(&xsave->i387.mxcsr, kbuf + offset, size);  	}  	/* -	 * Reject if the user sets any disabled or supervisor features: +	 * The state that came in from userspace was user-state only. +	 * Mask all the user states out of 'xfeatures': +	 */ +	xsave->header.xfeatures &= XFEATURE_MASK_SUPERVISOR; + +	/* +	 * Add back in the features that came in from userspace:  	 */ -	allowed_features = xfeatures_mask & ~XFEATURE_MASK_SUPERVISOR; +	xsave->header.xfeatures |= hdr.xfeatures; -	if (xfeatures & ~allowed_features) +	return 0; +} + +/* + * Convert from a ptrace or sigreturn standard-format user-space buffer to + * kernel XSAVES format and copy to the target thread. This is called from + * xstateregs_set(), as well as potentially from the sigreturn() and + * rt_sigreturn() system calls. + */ +int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf) +{ +	unsigned int offset, size; +	int i; +	struct xstate_header hdr; + +	offset = offsetof(struct xregs_state, header); +	size = sizeof(hdr); + +	if (__copy_from_user(&hdr, ubuf + offset, size)) +		return -EFAULT; + +	if (validate_xstate_header(&hdr))  		return -EINVAL;  	for (i = 0; i < XFEATURE_MAX; i++) {  		u64 mask = ((u64)1 << i); -		if (xfeatures & mask) { +		if (hdr.xfeatures & mask) {  			void *dst = __raw_xsave_addr(xsave, 1 << i);  			offset = xstate_offsets[i];  			size = xstate_sizes[i]; -			if (kbuf) { -				memcpy(dst, kbuf + offset, size); -			} else { -				if (__copy_from_user(dst, ubuf + offset, size)) -					return -EFAULT; -			} +			if (__copy_from_user(dst, ubuf + offset, size)) +				return -EFAULT;  		}  	} +	if (xfeatures_mxcsr_quirk(hdr.xfeatures)) { +		offset = offsetof(struct fxregs_state, mxcsr); +		size = MXCSR_AND_FLAGS_SIZE; +		if (__copy_from_user(&xsave->i387.mxcsr, ubuf + offset, size)) +			return -EFAULT; +	} +  	/*  	 * The state that came in from userspace was user-state only.  	 * Mask all the user states out of 'xfeatures': @@ -1076,7 +1238,7 @@ int copyin_to_xsaves(const void *kbuf, const void __user *ubuf,  	/*  	 * Add back in the features that came in from userspace:  	 */ -	xsave->header.xfeatures |= xfeatures; +	xsave->header.xfeatures |= hdr.xfeatures;  	return 0;  } diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 9bef1bbeba63..01ebcb6f263e 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Dynamic function tracing support.   * diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index 722a145b4139..b6c6468e10bc 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   *  Copyright (C) 2017  Steven Rostedt, VMware Inc.   */ diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S index 1dfac634bbf7..c832291d948a 100644 --- a/arch/x86/kernel/ftrace_64.S +++ b/arch/x86/kernel/ftrace_64.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   *  Copyright (C) 2014  Steven Rostedt, Red Hat Inc   */ diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index cf2ce063f65a..ec6fefbfd3c0 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  linux/arch/i386/kernel/head32.c -- prepare to run common code   * @@ -30,10 +31,11 @@ static void __init i386_default_early_setup(void)  asmlinkage __visible void __init i386_start_kernel(void)  { -	cr4_init_shadow(); - +	/* Make sure IDT is set up before any exception happens */  	idt_setup_early_handler(); +	cr4_init_shadow(); +  	sanitize_boot_params(&boot_params);  	x86_early_init_platform_quirks(); diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index bab4fa579450..6a5d757b9cfd 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  prepare to run common code   * diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 9ed3074d0d27..f1d528bb66a6 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   *   *  Copyright (C) 1991, 1992  Linus Torvalds diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 513cbb012ecc..6dde3f3fc1f8 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   *  linux/arch/x86/kernel/head_64.S -- start in 32bit and switch to 64bit   * diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 6ebe00cb4a3b..0d307a657abb 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * 8253/PIT functions   * diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 4e3b8a587c88..8f5cb2c7060c 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/linkage.h>  #include <linux/errno.h>  #include <linux/signal.h> diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index 7ebcc4a74438..805b7a341aca 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * I/O delay strategies for inb_p/outb_p   * diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 9c3cf0944bce..3feb648781c4 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * This contains the io-permission bitmap code - written by obz, with changes   * by Linus. 32/64 bits code unification by Miguel Botón. diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 1f38d9a4d9de..a83b3346a0e1 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar   * @@ -64,7 +65,7 @@ static void call_on_stack(void *func, void *stack)  static inline void *current_stack(void)  { -	return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1)); +	return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1));  }  static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc) @@ -88,7 +89,7 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)  	/* Save the next esp at the bottom of the stack */  	prev_esp = (u32 *)irqstk; -	*prev_esp = current_stack_pointer(); +	*prev_esp = current_stack_pointer;  	if (unlikely(overflow))  		call_on_stack(print_stack_overflow, isp); @@ -139,7 +140,7 @@ void do_softirq_own_stack(void)  	/* Push the previous esp onto the stack */  	prev_esp = (u32 *)irqstk; -	*prev_esp = current_stack_pointer(); +	*prev_esp = current_stack_pointer;  	call_on_stack(__do_softirq, isp);  } diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 3be74fbdeff2..020efbf5786b 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar   * diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c index 70dee056f92b..80bee7695a20 100644 --- a/arch/x86/kernel/irq_work.c +++ b/arch/x86/kernel/irq_work.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * x86 specific code for irq_work   * diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 1add9e08e83e..1e4094eba15e 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/linkage.h>  #include <linux/errno.h>  #include <linux/signal.h> diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index ab4f491da2a9..e56c95be2808 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * jump label x86 support   * diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h index db2182d63ed0..615105cf7d58 100644 --- a/arch/x86/kernel/kprobes/common.h +++ b/arch/x86/kernel/kprobes/common.h @@ -1,8 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef __X86_KERNEL_KPROBES_COMMON_H  #define __X86_KERNEL_KPROBES_COMMON_H  /* Kprobes and Optprobes common header */ +#include <asm/asm.h> + +#ifdef CONFIG_FRAME_POINTER +# define SAVE_RBP_STRING "	push %" _ASM_BP "\n" \ +			 "	mov  %" _ASM_SP ", %" _ASM_BP "\n" +#else +# define SAVE_RBP_STRING "	push %" _ASM_BP "\n" +#endif +  #ifdef CONFIG_X86_64  #define SAVE_REGS_STRING			\  	/* Skip cs, ip, orig_ax. */		\ @@ -17,7 +27,7 @@  	"	pushq %r10\n"			\  	"	pushq %r11\n"			\  	"	pushq %rbx\n"			\ -	"	pushq %rbp\n"			\ +	SAVE_RBP_STRING				\  	"	pushq %r12\n"			\  	"	pushq %r13\n"			\  	"	pushq %r14\n"			\ @@ -48,7 +58,7 @@  	"	pushl %es\n"			\  	"	pushl %ds\n"			\  	"	pushl %eax\n"			\ -	"	pushl %ebp\n"			\ +	SAVE_RBP_STRING				\  	"	pushl %edi\n"			\  	"	pushl %esi\n"			\  	"	pushl %edx\n"			\ diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index f0153714ddac..0742491cbb73 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1080,8 +1080,6 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)  	 * raw stack chunk with redzones:  	 */  	__memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, MIN_STACK_SIZE(addr)); -	regs->flags &= ~X86_EFLAGS_IF; -	trace_hardirqs_off();  	regs->ip = (unsigned long)(jp->entry);  	/* diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c index 4b0592ca9e47..8c1cc08f514f 100644 --- a/arch/x86/kernel/ksysfs.c +++ b/arch/x86/kernel/ksysfs.c @@ -299,7 +299,7 @@ static int __init create_setup_data_nodes(struct kobject *parent)  	return 0;  out_clean_nodes: -	for (j = i - 1; j > 0; j--) +	for (j = i - 1; j >= 0; j--)  		cleanup_setup_data_node(*(kobjp + j));  	kfree(kobjp);  out_setup_data_kobj: diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index aa60a08b65b1..8bb9594d0761 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -117,7 +117,11 @@ static struct kvm_task_sleep_node *_find_apf_task(struct kvm_task_sleep_head *b,  	return NULL;  } -void kvm_async_pf_task_wait(u32 token) +/* + * @interrupt_kernel: Is this called from a routine which interrupts the kernel + * 		      (other than user space)? + */ +void kvm_async_pf_task_wait(u32 token, int interrupt_kernel)  {  	u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS);  	struct kvm_task_sleep_head *b = &async_pf_sleepers[key]; @@ -140,7 +144,10 @@ void kvm_async_pf_task_wait(u32 token)  	n.token = token;  	n.cpu = smp_processor_id(); -	n.halted = is_idle_task(current) || preempt_count() > 1; +	n.halted = is_idle_task(current) || +		   (IS_ENABLED(CONFIG_PREEMPT_COUNT) +		    ? preempt_count() > 1 || rcu_preempt_depth() +		    : interrupt_kernel);  	init_swait_queue_head(&n.wq);  	hlist_add_head(&n.link, &b->list);  	raw_spin_unlock(&b->lock); @@ -268,7 +275,7 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)  	case KVM_PV_REASON_PAGE_NOT_PRESENT:  		/* page is swapped out by the host. */  		prev_state = exception_enter(); -		kvm_async_pf_task_wait((u32)read_cr2()); +		kvm_async_pf_task_wait((u32)read_cr2(), !user_mode(regs));  		exception_exit(prev_state);  		break;  	case KVM_PV_REASON_PAGE_READY: diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index d88967659098..5b609e28ce3f 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -79,7 +79,7 @@ static void kvm_get_wallclock(struct timespec *now)  static int kvm_set_wallclock(const struct timespec *now)  { -	return -1; +	return -ENODEV;  }  static u64 kvm_clock_read(void) diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index f0e64db18ac8..4d17bacf4030 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds   * Copyright (C) 1999 Ingo Molnar <[email protected]> diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index f4c886d9165c..b5cb49e57df8 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * AMD Family 10h mmconfig enablement   */ diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 62e7d70aadd5..da0c160e5589 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -172,19 +172,27 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  		case R_X86_64_NONE:  			break;  		case R_X86_64_64: +			if (*(u64 *)loc != 0) +				goto invalid_relocation;  			*(u64 *)loc = val;  			break;  		case R_X86_64_32: +			if (*(u32 *)loc != 0) +				goto invalid_relocation;  			*(u32 *)loc = val;  			if (val != *(u32 *)loc)  				goto overflow;  			break;  		case R_X86_64_32S: +			if (*(s32 *)loc != 0) +				goto invalid_relocation;  			*(s32 *)loc = val;  			if ((s64)val != *(s32 *)loc)  				goto overflow;  			break;  		case R_X86_64_PC32: +			if (*(u32 *)loc != 0) +				goto invalid_relocation;  			val -= (u64)loc;  			*(u32 *)loc = val;  #if 0 @@ -200,6 +208,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  	}  	return 0; +invalid_relocation: +	pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", +	       (int)ELF64_R_TYPE(rel[i].r_info), loc, val); +	return -ENOEXEC; +  overflow:  	pr_err("overflow in relocation type %d val %Lx\n",  	       (int)ELF64_R_TYPE(rel[i].r_info), val); diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 5cbb3177ed17..410c5dadcee3 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *	Intel Multiprocessor Specification 1.1 and 1.4   *	compliant MP-table parsing routines. diff --git a/arch/x86/kernel/nmi_selftest.c b/arch/x86/kernel/nmi_selftest.c index d27f8d84c4ff..a1a96df3dff1 100644 --- a/arch/x86/kernel/nmi_selftest.c +++ b/arch/x86/kernel/nmi_selftest.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * arch/x86/kernel/nmi-selftest.c   * diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c index 8f2d1c9d43a8..71f2d1125ec0 100644 --- a/arch/x86/kernel/paravirt-spinlocks.c +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Split spinlock implementation out into its own file, so it can be   * compiled in a FTRACE-compatible way. diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c index 553acbbb4d32..758e69d72ebf 100644 --- a/arch/x86/kernel/paravirt_patch_32.c +++ b/arch/x86/kernel/paravirt_patch_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <asm/paravirt.h>  DEF_NATIVE(pv_irq_ops, irq_disable, "cli"); diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c index 11aaf1eaa0e4..ac0be8283325 100644 --- a/arch/x86/kernel/paravirt_patch_64.c +++ b/arch/x86/kernel/paravirt_patch_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <asm/paravirt.h>  #include <asm/asm-offsets.h>  #include <linux/stringify.h> diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0accc2404b92..599d7462eccc 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/dma-mapping.h>  #include <linux/dma-debug.h>  #include <linux/dmar.h> diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c index f712dfdf1357..4dfd90a75e63 100644 --- a/arch/x86/kernel/pci-iommu_table.c +++ b/arch/x86/kernel/pci-iommu_table.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/dma-mapping.h>  #include <asm/iommu_table.h>  #include <linux/string.h> diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 4fc3cb60ea11..b0caae27e1b7 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /* Fallback functions when the main IOMMU code is not compiled in. This     code is roughly equivalent to i386. */  #include <linux/dma-mapping.h> diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index 677077510e30..53bd05ea90d8 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /* Glue code to lib/swiotlb.c */  #include <linux/pci.h> diff --git a/arch/x86/kernel/pcspeaker.c b/arch/x86/kernel/pcspeaker.c index a311ffcaad16..da5190a1ea16 100644 --- a/arch/x86/kernel/pcspeaker.c +++ b/arch/x86/kernel/pcspeaker.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/platform_device.h>  #include <linux/err.h>  #include <linux/init.h> diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 587d887f7f17..e47b2dbbdef3 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/errno.h>  #include <linux/kernel.h>  #include <linux/sched.h> diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index 502a77d0adb0..39a59299bfa0 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <linux/init.h> diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c index 0c5315d322c8..3fe690067802 100644 --- a/arch/x86/kernel/pmem.c +++ b/arch/x86/kernel/pmem.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Copyright (c) 2015, Christoph Hellwig.   * Copyright (c) 2015, Intel Corporation. diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c index 963e3fb56437..ee0286390a4c 100644 --- a/arch/x86/kernel/probe_roms.c +++ b/arch/x86/kernel/probe_roms.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/sched.h>  #include <linux/mm.h>  #include <linux/uaccess.h> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index bd6b85fac666..c67685337c5a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/errno.h> diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index eaa591cfd98b..697a4ce04308 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * This file contains work-arounds for x86 and x86_64 platform bugs.   */ diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 54180fa6f66f..2126b9d27c34 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/export.h> @@ -105,6 +106,10 @@ void __noreturn machine_real_restart(unsigned int type)  	load_cr3(initial_page_table);  #else  	write_cr3(real_mode_header->trampoline_pgd); + +	/* Exiting long mode will fail if CR4.PCIDE is set. */ +	if (static_cpu_has(X86_FEATURE_PCID)) +		cr4_clear_bits(X86_CR4_PCIDE);  #endif  	/* Jump to the identity-mapped low memory code */ diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index c8e41e90f59c..b7c0f142d026 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * This is a good place to put board specific reboot fixups.   * diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 5ab3895516ac..9b9fb7882c20 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/ioport.h>  #include <asm/e820/api.h> diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 5b21cb7d84d6..69ac9cb9cac6 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * RTC related functions   */ diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 28dafed6c682..497aa766fab3 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/kernel.h> diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index e04442345fc0..b9e00e8f1c9b 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (C) 1991, 1992  Linus Torvalds   *  Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs @@ -263,7 +264,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,  		sp = (unsigned long) ka->sa.sa_restorer;  	} -	if (fpu->fpstate_active) { +	if (fpu->initialized) {  		sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),  					  &buf_fx, &math_size);  		*fpstate = (void __user *)sp; @@ -279,7 +280,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,  		return (void __user *)-1L;  	/* save i387 and extended state */ -	if (fpu->fpstate_active && +	if (fpu->initialized &&  	    copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size) < 0)  		return (void __user *)-1L; @@ -755,7 +756,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)  		/*  		 * Ensure the signal handler starts with the new fpu state.  		 */ -		if (fpu->fpstate_active) +		if (fpu->initialized)  			fpu__clear(fpu);  	}  	signal_setup_done(failed, ksig, stepping); diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c index ab9feb5887b1..8c6da1a643da 100644 --- a/arch/x86/kernel/signal_compat.c +++ b/arch/x86/kernel/signal_compat.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/compat.h>  #include <linux/uaccess.h>  #include <linux/ptrace.h> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0854ff169274..ad59edd84de7 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -232,12 +232,6 @@ static void notrace start_secondary(void *unused)  	 */  	if (boot_cpu_has(X86_FEATURE_PCID))  		__write_cr4(__read_cr4() | X86_CR4_PCIDE); -	cpu_init(); -	x86_cpuinit.early_percpu_clock_init(); -	preempt_disable(); -	smp_callin(); - -	enable_start_cpu0 = 0;  #ifdef CONFIG_X86_32  	/* switch away from the initial page table */ @@ -245,6 +239,13 @@ static void notrace start_secondary(void *unused)  	__flush_tlb_all();  #endif +	cpu_init(); +	x86_cpuinit.early_percpu_clock_init(); +	preempt_disable(); +	smp_callin(); + +	enable_start_cpu0 = 0; +  	/* otherwise gcc will move up smp_processor_id before the cpu_init */  	barrier();  	/* diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 5ee663836c08..60d2c3798ba2 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * x86 single-step support code, common to 32-bit and 64-bit.   */ diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 73e4d28112f8..a63fe77b3217 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/errno.h>  #include <linux/sched.h>  #include <linux/sched/mm.h> diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index e0754cdbad37..879af864d99a 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (c) 1991,1992,1995  Linus Torvalds   *  Copyright (c) 1994  Alan Modra diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index a106b9719c58..9a9c9b076955 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/sched.h> diff --git a/arch/x86/kernel/trace_clock.c b/arch/x86/kernel/trace_clock.c index 80bb24d9b880..b8e7abe00b06 100644 --- a/arch/x86/kernel/trace_clock.c +++ b/arch/x86/kernel/trace_clock.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * X86 trace clocks   */ diff --git a/arch/x86/kernel/tracepoint.c b/arch/x86/kernel/tracepoint.c index c6636d1f60b9..5bd30c442794 100644 --- a/arch/x86/kernel/tracepoint.c +++ b/arch/x86/kernel/tracepoint.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Code for supporting irq vector tracepoints.   * diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 34ea3651362e..67db4f43309e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -142,7 +142,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)  	 * from double_fault.  	 */  	BUG_ON((unsigned long)(current_top_of_stack() - -			       current_stack_pointer()) >= THREAD_SIZE); +			       current_stack_pointer) >= THREAD_SIZE);  	preempt_enable_no_resched();  } diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 7842371bc9e4..e76a9881306b 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * check TSC synchronization.   * diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index d145a0b1f529..3dc26f95d46e 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c @@ -44,7 +44,8 @@ static void unwind_dump(struct unwind_state *state)  			state->stack_info.type, state->stack_info.next_sp,  			state->stack_mask, state->graph_idx); -	for (sp = state->orig_sp; sp; sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { +	for (sp = PTR_ALIGN(state->orig_sp, sizeof(long)); sp; +	     sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {  		if (get_stack_info(sp, state->task, &stack_info, &visit_mask))  			break; @@ -174,6 +175,7 @@ static bool is_last_task_frame(struct unwind_state *state)   * This determines if the frame pointer actually contains an encoded pointer to   * pt_regs on the stack.  See ENCODE_FRAME_POINTER.   */ +#ifdef CONFIG_X86_64  static struct pt_regs *decode_frame_pointer(unsigned long *bp)  {  	unsigned long regs = (unsigned long)bp; @@ -183,6 +185,23 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp)  	return (struct pt_regs *)(regs & ~0x1);  } +#else +static struct pt_regs *decode_frame_pointer(unsigned long *bp) +{ +	unsigned long regs = (unsigned long)bp; + +	if (regs & 0x80000000) +		return NULL; + +	return (struct pt_regs *)(regs | 0x80000000); +} +#endif + +#ifdef CONFIG_X86_32 +#define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long)) +#else +#define KERNEL_REGS_SIZE (sizeof(struct pt_regs)) +#endif  static bool update_stack_state(struct unwind_state *state,  			       unsigned long *next_bp) @@ -202,7 +221,7 @@ static bool update_stack_state(struct unwind_state *state,  	regs = decode_frame_pointer(next_bp);  	if (regs) {  		frame = (unsigned long *)regs; -		len = regs_size(regs); +		len = KERNEL_REGS_SIZE;  		state->got_irq = true;  	} else {  		frame = next_bp; @@ -226,6 +245,14 @@ static bool update_stack_state(struct unwind_state *state,  	    frame < prev_frame_end)  		return false; +	/* +	 * On 32-bit with user mode regs, make sure the last two regs are safe +	 * to access: +	 */ +	if (IS_ENABLED(CONFIG_X86_32) && regs && user_mode(regs) && +	    !on_stack(info, frame, len + 2*sizeof(long))) +		return false; +  	/* Move state to the next frame: */  	if (regs) {  		state->regs = regs; @@ -328,6 +355,13 @@ bad_address:  	    state->regs->sp < (unsigned long)task_pt_regs(state->task))  		goto the_end; +	/* +	 * There are some known frame pointer issues on 32-bit.  Disable +	 * unwinder warnings on 32-bit until it gets objtool support. +	 */ +	if (IS_ENABLED(CONFIG_X86_32)) +		goto the_end; +  	if (state->regs) {  		printk_deferred_once(KERN_WARNING  			"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n", diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 570b70d3f604..b95007e7c1b3 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -86,8 +86,8 @@ static struct orc_entry *orc_find(unsigned long ip)  		idx = (ip - LOOKUP_START_IP) / LOOKUP_BLOCK_SIZE;  		if (unlikely((idx >= lookup_num_blocks-1))) { -			orc_warn("WARNING: bad lookup idx: idx=%u num=%u ip=%lx\n", -				 idx, lookup_num_blocks, ip); +			orc_warn("WARNING: bad lookup idx: idx=%u num=%u ip=%pB\n", +				 idx, lookup_num_blocks, (void *)ip);  			return NULL;  		} @@ -96,8 +96,8 @@ static struct orc_entry *orc_find(unsigned long ip)  		if (unlikely((__start_orc_unwind + start >= __stop_orc_unwind) ||  			     (__start_orc_unwind + stop > __stop_orc_unwind))) { -			orc_warn("WARNING: bad lookup value: idx=%u num=%u start=%u stop=%u ip=%lx\n", -				 idx, lookup_num_blocks, start, stop, ip); +			orc_warn("WARNING: bad lookup value: idx=%u num=%u start=%u stop=%u ip=%pB\n", +				 idx, lookup_num_blocks, start, stop, (void *)ip);  			return NULL;  		} @@ -373,7 +373,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_REG_R10:  		if (!state->regs || !state->full_regs) { -			orc_warn("missing regs for base reg R10 at ip %p\n", +			orc_warn("missing regs for base reg R10 at ip %pB\n",  				 (void *)state->ip);  			goto done;  		} @@ -382,7 +382,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_REG_R13:  		if (!state->regs || !state->full_regs) { -			orc_warn("missing regs for base reg R13 at ip %p\n", +			orc_warn("missing regs for base reg R13 at ip %pB\n",  				 (void *)state->ip);  			goto done;  		} @@ -391,7 +391,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_REG_DI:  		if (!state->regs || !state->full_regs) { -			orc_warn("missing regs for base reg DI at ip %p\n", +			orc_warn("missing regs for base reg DI at ip %pB\n",  				 (void *)state->ip);  			goto done;  		} @@ -400,7 +400,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_REG_DX:  		if (!state->regs || !state->full_regs) { -			orc_warn("missing regs for base reg DX at ip %p\n", +			orc_warn("missing regs for base reg DX at ip %pB\n",  				 (void *)state->ip);  			goto done;  		} @@ -408,7 +408,7 @@ bool unwind_next_frame(struct unwind_state *state)  		break;  	default: -		orc_warn("unknown SP base reg %d for ip %p\n", +		orc_warn("unknown SP base reg %d for ip %pB\n",  			 orc->sp_reg, (void *)state->ip);  		goto done;  	} @@ -436,7 +436,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_TYPE_REGS:  		if (!deref_stack_regs(state, sp, &state->ip, &state->sp, true)) { -			orc_warn("can't dereference registers at %p for ip %p\n", +			orc_warn("can't dereference registers at %p for ip %pB\n",  				 (void *)sp, (void *)orig_ip);  			goto done;  		} @@ -448,7 +448,7 @@ bool unwind_next_frame(struct unwind_state *state)  	case ORC_TYPE_REGS_IRET:  		if (!deref_stack_regs(state, sp, &state->ip, &state->sp, false)) { -			orc_warn("can't dereference iret registers at %p for ip %p\n", +			orc_warn("can't dereference iret registers at %p for ip %pB\n",  				 (void *)sp, (void *)orig_ip);  			goto done;  		} @@ -465,7 +465,8 @@ bool unwind_next_frame(struct unwind_state *state)  		break;  	default: -		orc_warn("unknown .orc_unwind entry type %d\n", orc->type); +		orc_warn("unknown .orc_unwind entry type %d for ip %pB\n", +			 orc->type, (void *)orig_ip);  		break;  	} @@ -487,7 +488,7 @@ bool unwind_next_frame(struct unwind_state *state)  		break;  	default: -		orc_warn("unknown BP base reg %d for ip %p\n", +		orc_warn("unknown BP base reg %d for ip %pB\n",  			 orc->bp_reg, (void *)orig_ip);  		goto done;  	} @@ -496,7 +497,7 @@ bool unwind_next_frame(struct unwind_state *state)  	if (state->stack_info.type == prev_type &&  	    on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&  	    state->sp <= prev_sp) { -		orc_warn("stack going in the wrong direction? ip=%p\n", +		orc_warn("stack going in the wrong direction? ip=%pB\n",  			 (void *)orig_ip);  		goto done;  	} diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 7924a5356c8a..68244742ecb0 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   *  Copyright (C) 1994  Linus Torvalds   * diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index f05f00acac89..a4009fb9be87 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   * ld script for the x86 kernel   * |