diff options
Diffstat (limited to 'arch/x86/kernel/cpu/common.c')
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 77 | 
1 files changed, 47 insertions, 30 deletions
| diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 44c4ef3d989b..660d0b22e962 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -949,11 +949,11 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)  }  static const __initconst struct x86_cpu_id cpu_no_speculation[] = { -	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_CEDARVIEW,	X86_FEATURE_ANY }, -	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_CLOVERVIEW,	X86_FEATURE_ANY }, -	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_LINCROFT,	X86_FEATURE_ANY }, -	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_PENWELL,	X86_FEATURE_ANY }, -	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_PINEVIEW,	X86_FEATURE_ANY }, +	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL,	X86_FEATURE_ANY }, +	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL_TABLET,	X86_FEATURE_ANY }, +	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_BONNELL_MID,	X86_FEATURE_ANY }, +	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL_MID,	X86_FEATURE_ANY }, +	{ X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_BONNELL,	X86_FEATURE_ANY },  	{ X86_VENDOR_CENTAUR,	5 },  	{ X86_VENDOR_INTEL,	5 },  	{ X86_VENDOR_NSC,	5 }, @@ -963,15 +963,16 @@ static const __initconst struct x86_cpu_id cpu_no_speculation[] = {  static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {  	{ X86_VENDOR_AMD }, +	{ X86_VENDOR_HYGON },  	{}  };  /* Only list CPUs which speculate but are non susceptible to SSB */  static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = { -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT1	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT	},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_AIRMONT		}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT2	}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_MERRIFIELD	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_X	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_MID	},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_CORE_YONAH		},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNL		},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNM		}, @@ -984,14 +985,14 @@ static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {  static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {  	/* in addition to cpu_no_speculation */ -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT1	}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT2	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_X	},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_AIRMONT		}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_MERRIFIELD	}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_MOOREFIELD	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_MID	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_AIRMONT_MID	},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_GOLDMONT	}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_DENVERTON	}, -	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_GEMINI_LAKE	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_GOLDMONT_X	}, +	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_GOLDMONT_PLUS	},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNL		},  	{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNM		},  	{} @@ -1076,6 +1077,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)  	memset(&c->x86_capability, 0, sizeof c->x86_capability);  	c->extended_cpuid_level = 0; +	if (!have_cpuid_p()) +		identify_cpu_without_cpuid(c); +  	/* cyrix could have cpuid enabled via c_identify()*/  	if (have_cpuid_p()) {  		cpu_detect(c); @@ -1093,7 +1097,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)  		if (this_cpu->c_bsp_init)  			this_cpu->c_bsp_init(c);  	} else { -		identify_cpu_without_cpuid(c);  		setup_clear_cpu_cap(X86_FEATURE_CPUID);  	} @@ -1240,10 +1243,10 @@ static void generic_identify(struct cpuinfo_x86 *c)  	 * ESPFIX issue, we can change this.  	 */  #ifdef CONFIG_X86_32 -# ifdef CONFIG_PARAVIRT +# ifdef CONFIG_PARAVIRT_XXL  	do {  		extern void native_iret(void); -		if (pv_cpu_ops.iret == native_iret) +		if (pv_ops.cpu.iret == native_iret)  			set_cpu_bug(c, X86_BUG_ESPFIX);  	} while (0);  # else @@ -1531,19 +1534,8 @@ EXPORT_PER_CPU_SYMBOL(__preempt_count);  /* May not be marked __init: used by software suspend */  void syscall_init(void)  { -	extern char _entry_trampoline[]; -	extern char entry_SYSCALL_64_trampoline[]; - -	int cpu = smp_processor_id(); -	unsigned long SYSCALL64_entry_trampoline = -		(unsigned long)get_cpu_entry_area(cpu)->entry_trampoline + -		(entry_SYSCALL_64_trampoline - _entry_trampoline); -  	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS); -	if (static_cpu_has(X86_FEATURE_PTI)) -		wrmsrl(MSR_LSTAR, SYSCALL64_entry_trampoline); -	else -		wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64); +	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);  #ifdef CONFIG_IA32_EMULATION  	wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat); @@ -1554,7 +1546,8 @@ void syscall_init(void)  	 * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).  	 */  	wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); -	wrmsrl_safe(MSR_IA32_SYSENTER_ESP, (unsigned long)(cpu_entry_stack(cpu) + 1)); +	wrmsrl_safe(MSR_IA32_SYSENTER_ESP, +		    (unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));  	wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);  #else  	wrmsrl(MSR_CSTAR, (unsigned long)ignore_sysret); @@ -1669,6 +1662,29 @@ static void wait_for_master_cpu(int cpu)  #endif  } +#ifdef CONFIG_X86_64 +static void setup_getcpu(int cpu) +{ +	unsigned long cpudata = vdso_encode_cpunode(cpu, early_cpu_to_node(cpu)); +	struct desc_struct d = { }; + +	if (static_cpu_has(X86_FEATURE_RDTSCP)) +		write_rdtscp_aux(cpudata); + +	/* Store CPU and node number in limit. */ +	d.limit0 = cpudata; +	d.limit1 = cpudata >> 16; + +	d.type = 5;		/* RO data, expand down, accessed */ +	d.dpl = 3;		/* Visible to user code */ +	d.s = 1;		/* Not a system segment */ +	d.p = 1;		/* Present */ +	d.d = 1;		/* 32-bit */ + +	write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_CPUNODE, &d, DESCTYPE_S); +} +#endif +  /*   * cpu_init() initializes state that is per-CPU. Some data is already   * initialized (naturally) in the bootstrap process, such as the GDT @@ -1706,6 +1722,7 @@ void cpu_init(void)  	    early_cpu_to_node(cpu) != NUMA_NO_NODE)  		set_numa_node(early_cpu_to_node(cpu));  #endif +	setup_getcpu(cpu);  	me = current; |