diff options
Diffstat (limited to 'arch/x86/include/asm/processor.h')
| -rw-r--r-- | arch/x86/include/asm/processor.h | 332 | 
1 files changed, 144 insertions, 188 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index cae9c3cb95c..a4ea02351f4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -14,21 +14,29 @@ struct mm_struct;  #include <asm/sigcontext.h>  #include <asm/current.h>  #include <asm/cpufeature.h> -#include <asm/system.h>  #include <asm/page.h>  #include <asm/pgtable_types.h>  #include <asm/percpu.h>  #include <asm/msr.h>  #include <asm/desc_defs.h>  #include <asm/nops.h> +#include <asm/special_insns.h>  #include <linux/personality.h>  #include <linux/cpumask.h>  #include <linux/cache.h>  #include <linux/threads.h>  #include <linux/math64.h> -#include <linux/init.h>  #include <linux/err.h> +#include <linux/irqflags.h> + +/* + * We handle most unaligned accesses in hardware.  On the other hand + * unaligned DMA can be quite expensive on some Nehalem processors. + * + * Based on this we disable the IP header alignment in network drivers. + */ +#define NET_IP_ALIGN	0  #define HBP_NUM 4  /* @@ -52,6 +60,20 @@ static inline void *current_text_addr(void)  # define ARCH_MIN_MMSTRUCT_ALIGN	0  #endif +enum tlb_infos { +	ENTRIES, +	NR_INFO +}; + +extern u16 __read_mostly tlb_lli_4k[NR_INFO]; +extern u16 __read_mostly tlb_lli_2m[NR_INFO]; +extern u16 __read_mostly tlb_lli_4m[NR_INFO]; +extern u16 __read_mostly tlb_lld_4k[NR_INFO]; +extern u16 __read_mostly tlb_lld_2m[NR_INFO]; +extern u16 __read_mostly tlb_lld_4m[NR_INFO]; +extern u16 __read_mostly tlb_lld_1g[NR_INFO]; +extern s8  __read_mostly tlb_flushall_shift; +  /*   *  CPU type and hardware bug flags. Kept separately for each CPU.   *  Members of this structure are referenced in head.S, so think twice @@ -67,13 +89,9 @@ struct cpuinfo_x86 {  	char			wp_works_ok;	/* It doesn't on 386's */  	/* Problems on some 486Dx4's and old 386's: */ -	char			hlt_works_ok; -	char			hard_math;  	char			rfu; -	char			fdiv_bug; -	char			f00f_bug; -	char			coma_bug;  	char			pad0; +	char			pad1;  #else  	/* Number of 4K pages in DTLB/ITLB combined(in pages): */  	int			x86_tlbsize; @@ -86,7 +104,7 @@ struct cpuinfo_x86 {  	__u32			extended_cpuid_level;  	/* Maximum supported CPUID level, -1=no CPUID: */  	int			cpuid_level; -	__u32			x86_capability[NCAPINTS]; +	__u32			x86_capability[NCAPINTS + NBUGINTS];  	char			x86_vendor_id[16];  	char			x86_model_id[64];  	/* in KB - valid for CPUS which support this call: */ @@ -94,16 +112,11 @@ struct cpuinfo_x86 {  	int			x86_cache_alignment;	/* In bytes */  	int			x86_power;  	unsigned long		loops_per_jiffy; -#ifdef CONFIG_SMP -	/* cpus sharing the last level cache: */ -	cpumask_var_t		llc_shared_map; -#endif  	/* cpuid returned max cores value: */  	u16			 x86_max_cores;  	u16			apicid;  	u16			initial_apicid;  	u16			x86_clflush_size; -#ifdef CONFIG_SMP  	/* number of cores as seen by the OS: */  	u16			booted_cores;  	/* Physical processor id: */ @@ -114,7 +127,7 @@ struct cpuinfo_x86 {  	u8			compute_unit_id;  	/* Index into per_cpu list: */  	u16			cpu_index; -#endif +	u32			microcode;  } __attribute__((__aligned__(SMP_CACHE_BYTES)));  #define X86_VENDOR_INTEL	0 @@ -141,40 +154,38 @@ extern __u32			cpu_caps_set[NCAPINTS];  #ifdef CONFIG_SMP  DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);  #define cpu_data(cpu)		per_cpu(cpu_info, cpu) -#define current_cpu_data	__get_cpu_var(cpu_info)  #else +#define cpu_info		boot_cpu_data  #define cpu_data(cpu)		boot_cpu_data -#define current_cpu_data	boot_cpu_data  #endif  extern const struct seq_operations cpuinfo_op; -static inline int hlt_works(int cpu) -{ -#ifdef CONFIG_X86_32 -	return cpu_data(cpu).hlt_works_ok; -#else -	return 1; -#endif -} -  #define cache_line_size()	(boot_cpu_data.x86_cache_alignment)  extern void cpu_detect(struct cpuinfo_x86 *c); - -extern struct pt_regs *idle_regs(struct pt_regs *); +extern void fpu_detect(struct cpuinfo_x86 *c);  extern void early_cpu_init(void);  extern void identify_boot_cpu(void);  extern void identify_secondary_cpu(struct cpuinfo_x86 *);  extern void print_cpu_info(struct cpuinfo_x86 *); +void print_cpu_msr(struct cpuinfo_x86 *);  extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); -extern unsigned short num_cache_leaves; +extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);  extern void detect_extended_topology(struct cpuinfo_x86 *c);  extern void detect_ht(struct cpuinfo_x86 *c); +#ifdef CONFIG_X86_32 +extern int have_cpuid_p(void); +#else +static inline int have_cpuid_p(void) +{ +	return 1; +} +#endif  static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,  				unsigned int *ecx, unsigned int *edx)  { @@ -184,7 +195,8 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,  	      "=b" (*ebx),  	      "=c" (*ecx),  	      "=d" (*edx) -	    : "0" (*eax), "2" (*ecx)); +	    : "0" (*eax), "2" (*ecx) +	    : "memory");  }  static inline void load_cr3(pgd_t *pgdir) @@ -358,6 +370,20 @@ struct ymmh_struct {  	u32 ymmh_space[64];  }; +/* We don't support LWP yet: */ +struct lwp_struct { +	u8 reserved[128]; +}; + +struct bndregs_struct { +	u64 bndregs[8]; +} __packed; + +struct bndcsr_struct { +	u64 cfg_reg_u; +	u64 status_reg; +} __packed; +  struct xsave_hdr_struct {  	u64 xstate_bv;  	u64 reserved1[2]; @@ -368,6 +394,9 @@ struct xsave_struct {  	struct i387_fxsave_struct i387;  	struct xsave_hdr_struct xsave_hdr;  	struct ymmh_struct ymmh; +	struct lwp_struct lwp; +	struct bndregs_struct bndregs; +	struct bndcsr_struct bndcsr;  	/* new processor state extensions will go here */  } __attribute__ ((packed, aligned (64))); @@ -379,6 +408,8 @@ union thread_xstate {  };  struct fpu { +	unsigned int last_cpu; +	unsigned int has_fpu;  	union thread_xstate *state;  }; @@ -398,12 +429,11 @@ union irq_stack_union {  	};  }; -DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union); +DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union) __visible;  DECLARE_INIT_PER_CPU(irq_stack_union);  DECLARE_PER_CPU(char *, irq_stack_ptr);  DECLARE_PER_CPU(unsigned int, irq_count); -extern unsigned long kernel_eflags;  extern asmlinkage void ignore_sysret(void);  #else	/* X86_64 */  #ifdef CONFIG_CC_STACKPROTECTOR @@ -419,6 +449,15 @@ struct stack_canary {  };  DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);  #endif +/* + * per-CPU IRQ handling stacks + */ +struct irq_stack { +	u32                     stack[THREAD_SIZE/sizeof(u32)]; +} __aligned(THREAD_SIZE); + +DECLARE_PER_CPU(struct irq_stack *, hardirq_stack); +DECLARE_PER_CPU(struct irq_stack *, softirq_stack);  #endif	/* X86_64 */  extern unsigned int xstate_size; @@ -456,7 +495,7 @@ struct thread_struct {  	unsigned long           ptrace_dr7;  	/* Fault info: */  	unsigned long		cr2; -	unsigned long		trap_no; +	unsigned long		trap_nr;  	unsigned long		error_code;  	/* floating point and extended processor state */  	struct fpu		fpu; @@ -475,63 +514,17 @@ struct thread_struct {  	unsigned long		iopl;  	/* Max allowed port in the bitmap, in bytes: */  	unsigned		io_bitmap_max; +	/* +	 * fpu_counter contains the number of consecutive context switches +	 * that the FPU is used. If this is over a threshold, the lazy fpu +	 * saving becomes unlazy to save the trap. This is an unsigned char +	 * so that after 256 times the counter wraps and the behavior turns +	 * lazy again; this to deal with bursty apps that only use FPU for +	 * a short time +	 */ +	unsigned char fpu_counter;  }; -static inline unsigned long native_get_debugreg(int regno) -{ -	unsigned long val = 0;	/* Damn you, gcc! */ - -	switch (regno) { -	case 0: -		asm("mov %%db0, %0" :"=r" (val)); -		break; -	case 1: -		asm("mov %%db1, %0" :"=r" (val)); -		break; -	case 2: -		asm("mov %%db2, %0" :"=r" (val)); -		break; -	case 3: -		asm("mov %%db3, %0" :"=r" (val)); -		break; -	case 6: -		asm("mov %%db6, %0" :"=r" (val)); -		break; -	case 7: -		asm("mov %%db7, %0" :"=r" (val)); -		break; -	default: -		BUG(); -	} -	return val; -} - -static inline void native_set_debugreg(int regno, unsigned long value) -{ -	switch (regno) { -	case 0: -		asm("mov %0, %%db0"	::"r" (value)); -		break; -	case 1: -		asm("mov %0, %%db1"	::"r" (value)); -		break; -	case 2: -		asm("mov %0, %%db2"	::"r" (value)); -		break; -	case 3: -		asm("mov %0, %%db3"	::"r" (value)); -		break; -	case 6: -		asm("mov %0, %%db6"	::"r" (value)); -		break; -	case 7: -		asm("mov %0, %%db7"	::"r" (value)); -		break; -	default: -		BUG(); -	} -} -  /*   * Set IOPL bits in EFLAGS from given mask   */ @@ -577,14 +570,6 @@ static inline void native_swapgs(void)  #define __cpuid			native_cpuid  #define paravirt_enabled()	0 -/* - * These special macros can be used to get or set a debugging register - */ -#define get_debugreg(var, register)				\ -	(var) = native_get_debugreg(register) -#define set_debugreg(value, register)				\ -	native_set_debugreg(register, value) -  static inline void load_sp0(struct tss_struct *tss,  			    struct thread_struct *thread)  { @@ -600,13 +585,16 @@ static inline void load_sp0(struct tss_struct *tss,   * enable), so that any CPU's that boot up   * after us can get the correct flags.   */ -extern unsigned long		mmu_cr4_features; +extern unsigned long mmu_cr4_features; +extern u32 *trampoline_cr4_features;  static inline void set_in_cr4(unsigned long mask)  {  	unsigned long cr4;  	mmu_cr4_features |= mask; +	if (trampoline_cr4_features) +		*trampoline_cr4_features = mmu_cr4_features;  	cr4 = read_cr4();  	cr4 |= mask;  	write_cr4(cr4); @@ -617,6 +605,8 @@ static inline void clear_in_cr4(unsigned long mask)  	unsigned long cr4;  	mmu_cr4_features &= ~mask; +	if (trampoline_cr4_features) +		*trampoline_cr4_features = mmu_cr4_features;  	cr4 = read_cr4();  	cr4 &= ~mask;  	write_cr4(cr4); @@ -627,17 +617,9 @@ typedef struct {  } mm_segment_t; -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -  /* Free all resources held by a thread. */  extern void release_thread(struct task_struct *); -/* Prepare to copy thread state - unlazy all lazy state */ -extern void prepare_to_copy(struct task_struct *tsk); -  unsigned long get_wchan(struct task_struct *p);  /* @@ -719,57 +701,45 @@ static inline void sync_core(void)  {  	int tmp; -#if defined(CONFIG_M386) || defined(CONFIG_M486) -	if (boot_cpu_data.x86 < 5) -		/* There is no speculative execution. -		 * jmp is a barrier to prefetching. */ -		asm volatile("jmp 1f\n1:\n" ::: "memory"); -	else +#ifdef CONFIG_M486 +	/* +	 * Do a CPUID if available, otherwise do a jump.  The jump +	 * can conveniently enough be the jump around CPUID. +	 */ +	asm volatile("cmpl %2,%1\n\t" +		     "jl 1f\n\t" +		     "cpuid\n" +		     "1:" +		     : "=a" (tmp) +		     : "rm" (boot_cpu_data.cpuid_level), "ri" (0), "0" (1) +		     : "ebx", "ecx", "edx", "memory"); +#else +	/* +	 * CPUID is a barrier to speculative execution. +	 * Prefetched instructions are automatically +	 * invalidated when modified. +	 */ +	asm volatile("cpuid" +		     : "=a" (tmp) +		     : "0" (1) +		     : "ebx", "ecx", "edx", "memory");  #endif -		/* cpuid is a barrier to speculative execution. -		 * Prefetched instructions are automatically -		 * invalidated when modified. */ -		asm volatile("cpuid" : "=a" (tmp) : "0" (1) -			     : "ebx", "ecx", "edx", "memory"); -} - -static inline void __monitor(const void *eax, unsigned long ecx, -			     unsigned long edx) -{ -	/* "monitor %eax, %ecx, %edx;" */ -	asm volatile(".byte 0x0f, 0x01, 0xc8;" -		     :: "a" (eax), "c" (ecx), "d"(edx)); -} - -static inline void __mwait(unsigned long eax, unsigned long ecx) -{ -	/* "mwait %eax, %ecx;" */ -	asm volatile(".byte 0x0f, 0x01, 0xc9;" -		     :: "a" (eax), "c" (ecx));  } -static inline void __sti_mwait(unsigned long eax, unsigned long ecx) -{ -	trace_hardirqs_on(); -	/* "mwait %eax, %ecx;" */ -	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" -		     :: "a" (eax), "c" (ecx)); -} - -extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); -  extern void select_idle_routine(const struct cpuinfo_x86 *c); -extern void init_c1e_mask(void); +extern void init_amd_e400_c1e_mask(void);  extern unsigned long		boot_option_idle_override; -extern unsigned long		idle_halt; -extern unsigned long		idle_nomwait; -extern bool			c1e_detected; +extern bool			amd_e400_c1e_detected; + +enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, +			 IDLE_POLL};  extern void enable_sep_cpu(void);  extern int sysenter_setup(void);  extern void early_trap_init(void); +void early_trap_pf_init(void);  /* Defined in head.S */  extern struct desc_ptr		early_gdt_descr; @@ -801,6 +771,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr)  	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);  } +extern void set_task_blockstep(struct task_struct *task, bool on); +  /*   * from system description table in BIOS. Mostly for MCA use, but   * others may find it useful: @@ -902,7 +874,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);  /*   * The below -8 is to reserve 8 bytes on top of the ring0 stack.   * This is necessary to guarantee that the entire "struct pt_regs" - * is accessable even if the CPU haven't stored the SS/ESP registers + * is accessible even if the CPU haven't stored the SS/ESP registers   * on the stack (interrupt gate does not save these registers   * when switching to the same priv ring).   * Therefore beware: accessing the ss/esp fields of the @@ -930,9 +902,9 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);  #define IA32_PAGE_OFFSET	((current->personality & ADDR_LIMIT_3GB) ? \  					0xc0000000 : 0xFFFFe000) -#define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \ +#define TASK_SIZE		(test_thread_flag(TIF_ADDR32) ? \  					IA32_PAGE_OFFSET : TASK_SIZE_MAX) -#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \ +#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_ADDR32)) ? \  					IA32_PAGE_OFFSET : TASK_SIZE_MAX)  #define STACK_TOP		TASK_SIZE @@ -954,6 +926,12 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);  #define task_pt_regs(tsk)	((struct pt_regs *)(tsk)->thread.sp0 - 1)  extern unsigned long KSTK_ESP(struct task_struct *task); + +/* + * User space RSP while inside the SYSCALL fast path + */ +DECLARE_PER_CPU(unsigned long, old_rsp); +  #endif /* CONFIG_X86_64 */  extern void start_thread(struct pt_regs *regs, unsigned long new_ip, @@ -974,55 +952,33 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,  extern int get_tsc_mode(unsigned long adr);  extern int set_tsc_mode(unsigned int val); -extern int amd_get_nb_id(int cpu); +extern u16 amd_get_nb_id(int cpu); -struct aperfmperf { -	u64 aperf, mperf; -}; - -static inline void get_aperfmperf(struct aperfmperf *am) +static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)  { -	WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF)); - -	rdmsrl(MSR_IA32_APERF, am->aperf); -	rdmsrl(MSR_IA32_MPERF, am->mperf); -} - -#define APERFMPERF_SHIFT 10 +	uint32_t base, eax, signature[3]; -static inline -unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, -				    struct aperfmperf *new) -{ -	u64 aperf = new->aperf - old->aperf; -	u64 mperf = new->mperf - old->mperf; -	unsigned long ratio = aperf; +	for (base = 0x40000000; base < 0x40010000; base += 0x100) { +		cpuid(base, &eax, &signature[0], &signature[1], &signature[2]); -	mperf >>= APERFMPERF_SHIFT; -	if (mperf) -		ratio = div64_u64(aperf, mperf); +		if (!memcmp(sig, signature, 12) && +		    (leaves == 0 || ((eax - base) >= leaves))) +			return base; +	} -	return ratio; +	return 0;  } -/* - * AMD errata checking - */ -#ifdef CONFIG_CPU_SUP_AMD -extern const int amd_erratum_383[]; -extern const int amd_erratum_400[]; -extern bool cpu_has_amd_erratum(const int *); - -#define AMD_LEGACY_ERRATUM(...)		{ -1, __VA_ARGS__, 0 } -#define AMD_OSVW_ERRATUM(osvw_id, ...)	{ osvw_id, __VA_ARGS__, 0 } -#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ -	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) -#define AMD_MODEL_RANGE_FAMILY(range)	(((range) >> 24) & 0xff) -#define AMD_MODEL_RANGE_START(range)	(((range) >> 12) & 0xfff) -#define AMD_MODEL_RANGE_END(range)	((range) & 0xfff) +extern unsigned long arch_align_stack(unsigned long sp); +extern void free_init_pages(char *what, unsigned long begin, unsigned long end); +void default_idle(void); +#ifdef	CONFIG_XEN +bool xen_set_default_idle(void);  #else -#define cpu_has_amd_erratum(x)	(false) -#endif /* CONFIG_CPU_SUP_AMD */ +#define xen_set_default_idle 0 +#endif +void stop_this_cpu(void *dummy); +void df_debug(struct pt_regs *regs, long error_code);  #endif /* _ASM_X86_PROCESSOR_H */  | 
