1387 lines · 32.7 KB · C
RawDownload
#include <linux/bootmem.h>#include <linux/linkage.h>#include <linux/bitops.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/percpu.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/kgdb.h>#include <linux/smp.h>#include <linux/io.h> #include <asm/stackprotector.h>#include <asm/perf_event.h>#include <asm/mmu_context.h>#include <asm/archrandom.h>#include <asm/hypervisor.h>#include <asm/processor.h>#include <asm/debugreg.h>#include <asm/sections.h>#include <linux/topology.h>#include <linux/cpumask.h>#include <asm/pgtable.h>#include <linux/atomic.h>#include <asm/proto.h>#include <asm/setup.h>#include <asm/apic.h>#include <asm/desc.h>#include <asm/i387.h>#include <asm/fpu-internal.h>#include <asm/mtrr.h>#include <linux/numa.h>#include <asm/asm.h>#include <asm/cpu.h>#include <asm/mce.h>#include <asm/msr.h>#include <asm/pat.h>#include <asm/microcode.h>#include <asm/microcode_intel.h> #ifdef CONFIG_X86_LOCAL_APIC#include <asm/uv/uv.h>#endif #include "cpu.h" /* all of these masks are initialized in setup_cpu_local_masks() */cpumask_var_t cpu_initialized_mask;cpumask_var_t cpu_callout_mask;cpumask_var_t cpu_callin_mask; /* representing cpus for which sibling maps can be computed */cpumask_var_t cpu_sibling_setup_mask; /* correctly size the local cpu masks */void __init setup_cpu_local_masks(void){	alloc_bootmem_cpumask_var(&cpu_initialized_mask);	alloc_bootmem_cpumask_var(&cpu_callin_mask);	alloc_bootmem_cpumask_var(&cpu_callout_mask);	alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);} static void default_init(struct cpuinfo_x86 *c){#ifdef CONFIG_X86_64	cpu_detect_cache_sizes(c);#else	/* Not much we can do here... */	/* Check if at least it has cpuid */	if (c->cpuid_level == -1) {		/* No cpuid. It must be an ancient CPU */		if (c->x86 == 4)			strcpy(c->x86_model_id, "486");		else if (c->x86 == 3)			strcpy(c->x86_model_id, "386");	}#endif} static const struct cpu_dev default_cpu = {	.c_init		= default_init,	.c_vendor	= "Unknown",	.c_x86_vendor	= X86_VENDOR_UNKNOWN,}; static const struct cpu_dev *this_cpu = &default_cpu; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {#ifdef CONFIG_X86_64	/*	 * We need valid kernel segments for data and code in long mode too	 * IRET will check the segment types  kkeil 2000/10/28	 * Also sysret mandates a special GDT layout	 *	 * TLS descriptors are currently at a different place compared to i386.	 * Hopefully nobody expects them at a fixed place (Wine?)	 */	[GDT_ENTRY_KERNEL32_CS]		= GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc093, 0, 0xfffff),	[GDT_ENTRY_DEFAULT_USER32_CS]	= GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),#else	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff),	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),	/*	 * Segments used for calling PnP BIOS have byte granularity.	 * They code segments and data segments have fixed 64k limits,	 * the transfer segment sizes are set at run time.	 */	/* 32-bit code */	[GDT_ENTRY_PNPBIOS_CS32]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),	/* 16-bit code */	[GDT_ENTRY_PNPBIOS_CS16]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),	/* 16-bit data */	[GDT_ENTRY_PNPBIOS_DS]		= GDT_ENTRY_INIT(0x0092, 0, 0xffff),	/* 16-bit data */	[GDT_ENTRY_PNPBIOS_TS1]		= GDT_ENTRY_INIT(0x0092, 0, 0),	/* 16-bit data */	[GDT_ENTRY_PNPBIOS_TS2]		= GDT_ENTRY_INIT(0x0092, 0, 0),	/*	 * The APM segments have byte granularity and their bases	 * are set at run time.  All have 64k limits.	 */	/* 32-bit code */	[GDT_ENTRY_APMBIOS_BASE]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),	/* 16-bit code */	[GDT_ENTRY_APMBIOS_BASE+1]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),	/* data */	[GDT_ENTRY_APMBIOS_BASE+2]	= GDT_ENTRY_INIT(0x4092, 0, 0xffff), 	[GDT_ENTRY_ESPFIX_SS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),	[GDT_ENTRY_PERCPU]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),	GDT_STACK_CANARY_INIT#endif} };EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); static int __init x86_xsave_setup(char *s){	setup_clear_cpu_cap(X86_FEATURE_XSAVE);	setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);	setup_clear_cpu_cap(X86_FEATURE_AVX);	setup_clear_cpu_cap(X86_FEATURE_AVX2);	return 1;}__setup("noxsave", x86_xsave_setup); static int __init x86_xsaveopt_setup(char *s){	setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);	return 1;}__setup("noxsaveopt", x86_xsaveopt_setup); #ifdef CONFIG_X86_32static int cachesize_override = -1;static int disable_x86_serial_nr = 1; static int __init cachesize_setup(char *str){	get_option(&str, &cachesize_override);	return 1;}__setup("cachesize=", cachesize_setup); static int __init x86_fxsr_setup(char *s){	setup_clear_cpu_cap(X86_FEATURE_FXSR);	setup_clear_cpu_cap(X86_FEATURE_XMM);	return 1;}__setup("nofxsr", x86_fxsr_setup); static int __init x86_sep_setup(char *s){	setup_clear_cpu_cap(X86_FEATURE_SEP);	return 1;}__setup("nosep", x86_sep_setup); /* Standard macro to see if a specific flag is changeable */static inline int flag_is_changeable_p(u32 flag){	u32 f1, f2; 	/*	 * Cyrix and IDT cpus allow disabling of CPUID	 * so the code below may return different results	 * when it is executed before and after enabling	 * the CPUID. Add "volatile" to not allow gcc to	 * optimize the subsequent calls to this function.	 */	asm volatile ("pushfl		\n\t"		      "pushfl		\n\t"		      "popl %0		\n\t"		      "movl %0, %1	\n\t"		      "xorl %2, %0	\n\t"		      "pushl %0		\n\t"		      "popfl		\n\t"		      "pushfl		\n\t"		      "popl %0		\n\t"		      "popfl		\n\t" 		      : "=&r" (f1), "=&r" (f2)		      : "ir" (flag)); 	return ((f1^f2) & flag) != 0;} /* Probe for the CPUID instruction */int have_cpuid_p(void){	return flag_is_changeable_p(X86_EFLAGS_ID);} static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c){	unsigned long lo, hi; 	if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr)		return; 	/* Disable processor serial number: */ 	rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);	lo |= 0x200000;	wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); 	printk(KERN_NOTICE "CPU serial number disabled.\n");	clear_cpu_cap(c, X86_FEATURE_PN); 	/* Disabling the serial number may affect the cpuid level */	c->cpuid_level = cpuid_eax(0);} static int __init x86_serial_nr_setup(char *s){	disable_x86_serial_nr = 0;	return 1;}__setup("serialnumber", x86_serial_nr_setup);#elsestatic inline int flag_is_changeable_p(u32 flag){	return 1;}static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c){}#endif static __init int setup_disable_smep(char *arg){	setup_clear_cpu_cap(X86_FEATURE_SMEP);	return 1;}__setup("nosmep", setup_disable_smep); static __always_inline void setup_smep(struct cpuinfo_x86 *c){	if (cpu_has(c, X86_FEATURE_SMEP))		set_in_cr4(X86_CR4_SMEP);} static __init int setup_disable_smap(char *arg){	setup_clear_cpu_cap(X86_FEATURE_SMAP);	return 1;}__setup("nosmap", setup_disable_smap); static __always_inline void setup_smap(struct cpuinfo_x86 *c){	unsigned long eflags; 	/* This should have been cleared long ago */	raw_local_save_flags(eflags);	BUG_ON(eflags & X86_EFLAGS_AC); 	if (cpu_has(c, X86_FEATURE_SMAP))		set_in_cr4(X86_CR4_SMAP);} /* * Some CPU features depend on higher CPUID levels, which may not always * be available due to CPUID level capping or broken virtualization * software.  Add those features to this table to auto-disable them. */struct cpuid_dependent_feature {	u32 feature;	u32 level;}; static const struct cpuid_dependent_featurecpuid_dependent_features[] = {	{ X86_FEATURE_MWAIT,		0x00000005 },	{ X86_FEATURE_DCA,		0x00000009 },	{ X86_FEATURE_XSAVE,		0x0000000d },	{ 0, 0 }}; static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn){	const struct cpuid_dependent_feature *df; 	for (df = cpuid_dependent_features; df->feature; df++) { 		if (!cpu_has(c, df->feature))			continue;		/*		 * Note: cpuid_level is set to -1 if unavailable, but		 * extended_extended_level is set to 0 if unavailable		 * and the legitimate extended levels are all negative		 * when signed; hence the weird messing around with		 * signs here...		 */		if (!((s32)df->level < 0 ?		     (u32)df->level > (u32)c->extended_cpuid_level :		     (s32)df->level > (s32)c->cpuid_level))			continue; 		clear_cpu_cap(c, df->feature);		if (!warn)			continue; 		printk(KERN_WARNING		       "CPU: CPU feature %s disabled, no CPUID level 0x%x\n",				x86_cap_flags[df->feature], df->level);	}} /* * Naming convention should be: <Name> [(<Codename>)] * This table only is used unless init_<vendor>() below doesn't set it; * in particular, if CPUID levels 0x80000002..4 are supported, this * isn't used */ /* Look up CPU names by table lookup. */static const char *table_lookup_model(struct cpuinfo_x86 *c){#ifdef CONFIG_X86_32	const struct legacy_cpu_model_info *info; 	if (c->x86_model >= 16)		return NULL;	/* Range check */ 	if (!this_cpu)		return NULL; 	info = this_cpu->legacy_models; 	while (info->family) {		if (info->family == c->x86)			return info->model_names[c->x86_model];		info++;	}#endif	return NULL;		/* Not found */} __u32 cpu_caps_cleared[NCAPINTS];__u32 cpu_caps_set[NCAPINTS]; void load_percpu_segment(int cpu){#ifdef CONFIG_X86_32	loadsegment(fs, __KERNEL_PERCPU);#else	loadsegment(gs, 0);	wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));#endif	load_stack_canary_segment();} /* * Current gdt points %fs at the "master" per-cpu area: after this, * it's on the real one. */void switch_to_new_gdt(int cpu){	struct desc_ptr gdt_descr; 	gdt_descr.address = (long)get_cpu_gdt_table(cpu);	gdt_descr.size = GDT_SIZE - 1;	load_gdt(&gdt_descr);	/* Reload the per-cpu base */ 	load_percpu_segment(cpu);} static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; static void get_model_name(struct cpuinfo_x86 *c){	unsigned int *v;	char *p, *q; 	if (c->extended_cpuid_level < 0x80000004)		return; 	v = (unsigned int *)c->x86_model_id;	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);	c->x86_model_id[48] = 0; 	/*	 * Intel chips right-justify this string for some dumb reason;	 * undo that brain damage:	 */	p = q = &c->x86_model_id[0];	while (*p == ' ')		p++;	if (p != q) {		while (*p)			*q++ = *p++;		while (q <= &c->x86_model_id[48])			*q++ = '\0';	/* Zero-pad the rest */	}} void cpu_detect_cache_sizes(struct cpuinfo_x86 *c){	unsigned int n, dummy, ebx, ecx, edx, l2size; 	n = c->extended_cpuid_level; 	if (n >= 0x80000005) {		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);		c->x86_cache_size = (ecx>>24) + (edx>>24);#ifdef CONFIG_X86_64		/* On K8 L1 TLB is inclusive, so don't count it */		c->x86_tlbsize = 0;#endif	} 	if (n < 0x80000006)	/* Some chips just has a large L1. */		return; 	cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);	l2size = ecx >> 16; #ifdef CONFIG_X86_64	c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);#else	/* do processor-specific cache resizing */	if (this_cpu->legacy_cache_size)		l2size = this_cpu->legacy_cache_size(c, l2size); 	/* Allow user to override all this if necessary. */	if (cachesize_override != -1)		l2size = cachesize_override; 	if (l2size == 0)		return;		/* Again, no L2 cache is possible */#endif 	c->x86_cache_size = l2size;} u16 __read_mostly tlb_lli_4k[NR_INFO];u16 __read_mostly tlb_lli_2m[NR_INFO];u16 __read_mostly tlb_lli_4m[NR_INFO];u16 __read_mostly tlb_lld_4k[NR_INFO];u16 __read_mostly tlb_lld_2m[NR_INFO];u16 __read_mostly tlb_lld_4m[NR_INFO]; /* * tlb_flushall_shift shows the balance point in replacing cr3 write * with multiple 'invlpg'. It will do this replacement when *   flush_tlb_lines <= active_lines/2^tlb_flushall_shift. * If tlb_flushall_shift is -1, means the replacement will be disabled. */s8  __read_mostly tlb_flushall_shift = -1; void cpu_detect_tlb(struct cpuinfo_x86 *c){	if (this_cpu->c_detect_tlb)		this_cpu->c_detect_tlb(c); 	printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \		"Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n"	     \		"tlb_flushall_shift: %d\n",		tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES],		tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES],		tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES],		tlb_flushall_shift);} void detect_ht(struct cpuinfo_x86 *c){#ifdef CONFIG_X86_HT

Lines 1–500 of 1387.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t