| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * include/asm-i386/processor.h | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1994 Linus Torvalds | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __ASM_I386_PROCESSOR_H
 | 
					
						
							|  |  |  | #define __ASM_I386_PROCESSOR_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/vm86.h>
 | 
					
						
							|  |  |  | #include <asm/math_emu.h>
 | 
					
						
							|  |  |  | #include <asm/segment.h>
 | 
					
						
							|  |  |  | #include <asm/page.h>
 | 
					
						
							|  |  |  | #include <asm/types.h>
 | 
					
						
							|  |  |  | #include <asm/sigcontext.h>
 | 
					
						
							|  |  |  | #include <asm/cpufeature.h>
 | 
					
						
							|  |  |  | #include <asm/msr.h>
 | 
					
						
							|  |  |  | #include <asm/system.h>
 | 
					
						
							|  |  |  | #include <linux/cache.h>
 | 
					
						
							|  |  |  | #include <linux/threads.h>
 | 
					
						
							|  |  |  | #include <asm/percpu.h>
 | 
					
						
							| 
									
										
										
										
											2006-03-27 01:15:22 -08:00
										 |  |  | #include <linux/cpumask.h>
 | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | #include <linux/init.h>
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | #include <asm/processor-flags.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* flag for disabling the tsc */ | 
					
						
							|  |  |  | extern int tsc_disable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct desc_struct { | 
					
						
							|  |  |  | 	unsigned long a,b; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define desc_empty(desc) \
 | 
					
						
							| 
									
										
										
										
											2005-08-16 12:05:09 -07:00
										 |  |  | 		(!((desc)->a | (desc)->b)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define desc_equal(desc1, desc2) \
 | 
					
						
							|  |  |  | 		(((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b)) | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Default implementation of macro that returns current | 
					
						
							|  |  |  |  * instruction pointer ("program counter"). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *  CPU type and hardware bug flags. Kept separately for each CPU. | 
					
						
							|  |  |  |  *  Members of this structure are referenced in head.S, so think twice | 
					
						
							|  |  |  |  *  before touching them. [mj] | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct cpuinfo_x86 { | 
					
						
							|  |  |  | 	__u8	x86;		/* CPU family */ | 
					
						
							|  |  |  | 	__u8	x86_vendor;	/* CPU vendor */ | 
					
						
							|  |  |  | 	__u8	x86_model; | 
					
						
							|  |  |  | 	__u8	x86_mask; | 
					
						
							|  |  |  | 	char	wp_works_ok;	/* It doesn't on 386's */ | 
					
						
							|  |  |  | 	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */ | 
					
						
							|  |  |  | 	char	hard_math; | 
					
						
							|  |  |  | 	char	rfu; | 
					
						
							|  |  |  |        	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */ | 
					
						
							|  |  |  | 	unsigned long	x86_capability[NCAPINTS]; | 
					
						
							|  |  |  | 	char	x86_vendor_id[16]; | 
					
						
							|  |  |  | 	char	x86_model_id[64]; | 
					
						
							|  |  |  | 	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
 | 
					
						
							|  |  |  | 				    call  */ | 
					
						
							|  |  |  | 	int 	x86_cache_alignment;	/* In bytes */ | 
					
						
							| 
									
										
										
										
											2006-01-11 22:42:51 +01:00
										 |  |  | 	char	fdiv_bug; | 
					
						
							|  |  |  | 	char	f00f_bug; | 
					
						
							|  |  |  | 	char	coma_bug; | 
					
						
							|  |  |  | 	char	pad0; | 
					
						
							|  |  |  | 	int	x86_power; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	unsigned long loops_per_jiffy; | 
					
						
							| 
									
										
										
										
											2006-03-27 01:15:22 -08:00
										 |  |  | #ifdef CONFIG_SMP
 | 
					
						
							|  |  |  | 	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-05 17:25:54 +01:00
										 |  |  | 	unsigned char x86_max_cores;	/* cpuid returned max cores value */ | 
					
						
							|  |  |  | 	unsigned char apicid; | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:05 +01:00
										 |  |  | 	unsigned short x86_clflush_size; | 
					
						
							| 
									
										
										
										
											2006-06-27 02:53:46 -07:00
										 |  |  | #ifdef CONFIG_SMP
 | 
					
						
							|  |  |  | 	unsigned char booted_cores;	/* number of cores as seen by OS */ | 
					
						
							|  |  |  | 	__u8 phys_proc_id; 		/* Physical processor id. */ | 
					
						
							|  |  |  | 	__u8 cpu_core_id;  		/* Core id */ | 
					
						
							| 
									
										
										
										
											2007-10-19 20:35:04 +02:00
										 |  |  | 	__u8 cpu_index;			/* index into per_cpu list */ | 
					
						
							| 
									
										
										
										
											2006-06-27 02:53:46 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } __attribute__((__aligned__(SMP_CACHE_BYTES))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define X86_VENDOR_INTEL 0
 | 
					
						
							|  |  |  | #define X86_VENDOR_CYRIX 1
 | 
					
						
							|  |  |  | #define X86_VENDOR_AMD 2
 | 
					
						
							|  |  |  | #define X86_VENDOR_UMC 3
 | 
					
						
							|  |  |  | #define X86_VENDOR_NEXGEN 4
 | 
					
						
							|  |  |  | #define X86_VENDOR_CENTAUR 5
 | 
					
						
							|  |  |  | #define X86_VENDOR_TRANSMETA 7
 | 
					
						
							|  |  |  | #define X86_VENDOR_NSC 8
 | 
					
						
							|  |  |  | #define X86_VENDOR_NUM 9
 | 
					
						
							|  |  |  | #define X86_VENDOR_UNKNOWN 0xff
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * capabilities of CPUs | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern struct cpuinfo_x86 boot_cpu_data; | 
					
						
							|  |  |  | extern struct cpuinfo_x86 new_cpu_data; | 
					
						
							|  |  |  | extern struct tss_struct doublefault_tss; | 
					
						
							|  |  |  | DECLARE_PER_CPU(struct tss_struct, init_tss); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_SMP
 | 
					
						
							| 
									
										
										
										
											2007-10-19 20:35:04 +02:00
										 |  |  | DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info); | 
					
						
							|  |  |  | #define cpu_data(cpu)		per_cpu(cpu_info, cpu)
 | 
					
						
							|  |  |  | #define current_cpu_data	cpu_data(smp_processor_id())
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2007-10-19 20:35:04 +02:00
										 |  |  | #define cpu_data(cpu)		boot_cpu_data
 | 
					
						
							|  |  |  | #define current_cpu_data	boot_cpu_data
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-19 20:35:03 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * the following now lives in the per cpu area: | 
					
						
							|  |  |  |  * extern	int cpu_llc_id[NR_CPUS]; | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | DECLARE_PER_CPU(u8, cpu_llc_id); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | extern char ignore_fpu_irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | void __init cpu_detect(struct cpuinfo_x86 *c); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:12 +02:00
										 |  |  | extern void identify_boot_cpu(void); | 
					
						
							|  |  |  | extern void identify_secondary_cpu(struct cpuinfo_x86 *); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | extern void print_cpu_info(struct cpuinfo_x86 *); | 
					
						
							| 
									
										
										
										
											2007-07-11 12:18:32 -07:00
										 |  |  | extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); | 
					
						
							| 
									
										
										
										
											2006-06-26 13:56:13 +02:00
										 |  |  | extern unsigned short num_cache_leaves; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_X86_HT
 | 
					
						
							|  |  |  | extern void detect_ht(struct cpuinfo_x86 *c); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | static inline void detect_ht(struct cpuinfo_x86 *c) {} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:07 +01:00
										 |  |  | 					 unsigned int *ecx, unsigned int *edx) | 
					
						
							| 
									
										
										
										
											2006-09-25 23:32:24 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* ecx is often an input as well as an output. */ | 
					
						
							|  |  |  | 	__asm__("cpuid" | 
					
						
							|  |  |  | 		: "=a" (*eax), | 
					
						
							|  |  |  | 		  "=b" (*ebx), | 
					
						
							|  |  |  | 		  "=c" (*ecx), | 
					
						
							|  |  |  | 		  "=d" (*edx) | 
					
						
							|  |  |  | 		: "0" (*eax), "2" (*ecx)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:36 -07:00
										 |  |  | #define load_cr3(pgdir) write_cr3(__pa(pgdir))
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Save the cr4 feature set we're using (ie | 
					
						
							|  |  |  |  * Pentium 4MB enable and PPro Global page | 
					
						
							|  |  |  |  * enable), so that any CPU's that boot up | 
					
						
							|  |  |  |  * after us can get the correct flags. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | extern unsigned long mmu_cr4_features; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void set_in_cr4 (unsigned long mask) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:36 -07:00
										 |  |  | 	unsigned cr4; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	mmu_cr4_features |= mask; | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:36 -07:00
										 |  |  | 	cr4 = read_cr4(); | 
					
						
							|  |  |  | 	cr4 |= mask; | 
					
						
							|  |  |  | 	write_cr4(cr4); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void clear_in_cr4 (unsigned long mask) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:36 -07:00
										 |  |  | 	unsigned cr4; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	mmu_cr4_features &= ~mask; | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:36 -07:00
										 |  |  | 	cr4 = read_cr4(); | 
					
						
							|  |  |  | 	cr4 &= ~mask; | 
					
						
							|  |  |  | 	write_cr4(cr4); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 22:45:27 +01:00
										 |  |  | /* Stop speculative execution */ | 
					
						
							|  |  |  | static inline void sync_core(void) | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:37 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-01-11 22:45:27 +01:00
										 |  |  | 	int tmp; | 
					
						
							|  |  |  | 	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory"); | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:37 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 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)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-25 16:28:13 -07:00
										 |  |  | extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* from system description table in BIOS.  Mostly for MCA use, but
 | 
					
						
							|  |  |  | others may find it useful. */ | 
					
						
							|  |  |  | extern unsigned int machine_id; | 
					
						
							|  |  |  | extern unsigned int machine_submodel_id; | 
					
						
							|  |  |  | extern unsigned int BIOS_revision; | 
					
						
							|  |  |  | extern unsigned int mca_pentium_flag; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Boot loader type from the setup header */ | 
					
						
							|  |  |  | extern int bootloader_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * User space process size: 3GB (default). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define TASK_SIZE	(PAGE_OFFSET)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This decides where the kernel will search for a free chunk of vm
 | 
					
						
							|  |  |  |  * space during mmap's. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define HAVE_ARCH_PICK_MMAP_LAYOUT
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-15 23:41:33 -07:00
										 |  |  | extern void hard_disable_TSC(void); | 
					
						
							|  |  |  | extern void disable_TSC(void); | 
					
						
							|  |  |  | extern void hard_enable_TSC(void); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Size of io_bitmap. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define IO_BITMAP_BITS  65536
 | 
					
						
							|  |  |  | #define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
 | 
					
						
							|  |  |  | #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
 | 
					
						
							|  |  |  | #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
 | 
					
						
							|  |  |  | #define INVALID_IO_BITMAP_OFFSET 0x8000
 | 
					
						
							|  |  |  | #define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct i387_fsave_struct { | 
					
						
							|  |  |  | 	long	cwd; | 
					
						
							|  |  |  | 	long	swd; | 
					
						
							|  |  |  | 	long	twd; | 
					
						
							|  |  |  | 	long	fip; | 
					
						
							|  |  |  | 	long	fcs; | 
					
						
							|  |  |  | 	long	foo; | 
					
						
							|  |  |  | 	long	fos; | 
					
						
							|  |  |  | 	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */ | 
					
						
							|  |  |  | 	long	status;		/* software status information */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct i387_fxsave_struct { | 
					
						
							|  |  |  | 	unsigned short	cwd; | 
					
						
							|  |  |  | 	unsigned short	swd; | 
					
						
							|  |  |  | 	unsigned short	twd; | 
					
						
							|  |  |  | 	unsigned short	fop; | 
					
						
							|  |  |  | 	long	fip; | 
					
						
							|  |  |  | 	long	fcs; | 
					
						
							|  |  |  | 	long	foo; | 
					
						
							|  |  |  | 	long	fos; | 
					
						
							|  |  |  | 	long	mxcsr; | 
					
						
							|  |  |  | 	long	mxcsr_mask; | 
					
						
							|  |  |  | 	long	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */ | 
					
						
							|  |  |  | 	long	xmm_space[32];	/* 8*16 bytes for each XMM-reg = 128 bytes */ | 
					
						
							|  |  |  | 	long	padding[56]; | 
					
						
							|  |  |  | } __attribute__ ((aligned (16))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct i387_soft_struct { | 
					
						
							|  |  |  | 	long	cwd; | 
					
						
							|  |  |  | 	long	swd; | 
					
						
							|  |  |  | 	long	twd; | 
					
						
							|  |  |  | 	long	fip; | 
					
						
							|  |  |  | 	long	fcs; | 
					
						
							|  |  |  | 	long	foo; | 
					
						
							|  |  |  | 	long	fos; | 
					
						
							|  |  |  | 	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */ | 
					
						
							|  |  |  | 	unsigned char	ftop, changed, lookahead, no_update, rm, alimit; | 
					
						
							|  |  |  | 	struct info	*info; | 
					
						
							|  |  |  | 	unsigned long	entry_eip; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | union i387_union { | 
					
						
							|  |  |  | 	struct i387_fsave_struct	fsave; | 
					
						
							|  |  |  | 	struct i387_fxsave_struct	fxsave; | 
					
						
							|  |  |  | 	struct i387_soft_struct soft; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	unsigned long seg; | 
					
						
							|  |  |  | } mm_segment_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct thread_struct; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:13 +02:00
										 |  |  | /* This is the TSS defined by the hardware. */ | 
					
						
							|  |  |  | struct i386_hw_tss { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	unsigned short	back_link,__blh; | 
					
						
							|  |  |  | 	unsigned long	esp0; | 
					
						
							|  |  |  | 	unsigned short	ss0,__ss0h; | 
					
						
							|  |  |  | 	unsigned long	esp1; | 
					
						
							|  |  |  | 	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */ | 
					
						
							|  |  |  | 	unsigned long	esp2; | 
					
						
							|  |  |  | 	unsigned short	ss2,__ss2h; | 
					
						
							|  |  |  | 	unsigned long	__cr3; | 
					
						
							|  |  |  | 	unsigned long	eip; | 
					
						
							|  |  |  | 	unsigned long	eflags; | 
					
						
							|  |  |  | 	unsigned long	eax,ecx,edx,ebx; | 
					
						
							|  |  |  | 	unsigned long	esp; | 
					
						
							|  |  |  | 	unsigned long	ebp; | 
					
						
							|  |  |  | 	unsigned long	esi; | 
					
						
							|  |  |  | 	unsigned long	edi; | 
					
						
							|  |  |  | 	unsigned short	es, __esh; | 
					
						
							|  |  |  | 	unsigned short	cs, __csh; | 
					
						
							|  |  |  | 	unsigned short	ss, __ssh; | 
					
						
							|  |  |  | 	unsigned short	ds, __dsh; | 
					
						
							|  |  |  | 	unsigned short	fs, __fsh; | 
					
						
							|  |  |  | 	unsigned short	gs, __gsh; | 
					
						
							|  |  |  | 	unsigned short	ldt, __ldth; | 
					
						
							|  |  |  | 	unsigned short	trace, io_bitmap_base; | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:13 +02:00
										 |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct tss_struct { | 
					
						
							|  |  |  | 	struct i386_hw_tss x86_tss; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * The extra 1 is there because the CPU will access an | 
					
						
							|  |  |  | 	 * additional byte beyond the end of the IO permission | 
					
						
							|  |  |  | 	 * bitmap. The extra byte must be all 1 bits, and must | 
					
						
							|  |  |  | 	 * be within the limit. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1]; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Cache the current maximum and the last task that used the bitmap: | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	unsigned long io_bitmap_max; | 
					
						
							|  |  |  | 	struct thread_struct *io_bitmap_owner; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * pads the TSS to be cacheline-aligned (size is 0x100) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	unsigned long __cacheline_filler[35]; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * .. and then another 0x100 bytes for emergency kernel stack | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	unsigned long stack[64]; | 
					
						
							|  |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ARCH_MIN_TASKALIGN	16
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct thread_struct { | 
					
						
							|  |  |  | /* cached TLS descriptors. */ | 
					
						
							|  |  |  | 	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; | 
					
						
							|  |  |  | 	unsigned long	esp0; | 
					
						
							|  |  |  | 	unsigned long	sysenter_cs; | 
					
						
							|  |  |  | 	unsigned long	eip; | 
					
						
							|  |  |  | 	unsigned long	esp; | 
					
						
							|  |  |  | 	unsigned long	fs; | 
					
						
							|  |  |  | 	unsigned long	gs; | 
					
						
							|  |  |  | /* Hardware debugging registers */ | 
					
						
							|  |  |  | 	unsigned long	debugreg[8];  /* %%db0-7 debug registers */ | 
					
						
							|  |  |  | /* fault info */ | 
					
						
							|  |  |  | 	unsigned long	cr2, trap_no, error_code; | 
					
						
							|  |  |  | /* floating point info */ | 
					
						
							|  |  |  | 	union i387_union	i387; | 
					
						
							|  |  |  | /* virtual 86 mode info */ | 
					
						
							|  |  |  | 	struct vm86_struct __user * vm86_info; | 
					
						
							|  |  |  | 	unsigned long		screen_bitmap; | 
					
						
							|  |  |  | 	unsigned long		v86flags, v86mask, saved_esp0; | 
					
						
							|  |  |  | 	unsigned int		saved_fs, saved_gs; | 
					
						
							|  |  |  | /* IO permissions */ | 
					
						
							|  |  |  | 	unsigned long	*io_bitmap_ptr; | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:44 -07:00
										 |  |  |  	unsigned long	iopl; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* max allowed port in the bitmap, in bytes: */ | 
					
						
							|  |  |  | 	unsigned long	io_bitmap_max; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INIT_THREAD  {							\
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:09 +02:00
										 |  |  | 	.esp0 = sizeof(init_stack) + (long)&init_stack,			\ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.vm86_info = NULL,						\ | 
					
						
							|  |  |  | 	.sysenter_cs = __KERNEL_CS,					\ | 
					
						
							|  |  |  | 	.io_bitmap_ptr = NULL,						\ | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:16 +02:00
										 |  |  | 	.fs = __KERNEL_PERCPU,						\ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Note that the .io_bitmap member must be extra-big. This is because | 
					
						
							|  |  |  |  * the CPU will access an additional byte beyond the end of the IO | 
					
						
							|  |  |  |  * permission bitmap. The extra byte must be all 1 bits, and must | 
					
						
							|  |  |  |  * be within the limit. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define INIT_TSS  {							\
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:13 +02:00
										 |  |  | 	.x86_tss = {							\ | 
					
						
							|  |  |  | 		.esp0		= sizeof(init_stack) + (long)&init_stack, \ | 
					
						
							|  |  |  | 		.ss0		= __KERNEL_DS,				\ | 
					
						
							|  |  |  | 		.ss1		= __KERNEL_CS,				\ | 
					
						
							|  |  |  | 		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\ | 
					
						
							|  |  |  | 	 },								\ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define start_thread(regs, new_eip, new_esp) do {		\
 | 
					
						
							| 
									
										
										
										
											2007-02-13 13:26:20 +01:00
										 |  |  | 	__asm__("movl %0,%%gs": :"r" (0));			\ | 
					
						
							|  |  |  | 	regs->xfs = 0;						\ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	set_fs(USER_DS);					\ | 
					
						
							|  |  |  | 	regs->xds = __USER_DS;					\ | 
					
						
							|  |  |  | 	regs->xes = __USER_DS;					\ | 
					
						
							|  |  |  | 	regs->xss = __USER_DS;					\ | 
					
						
							|  |  |  | 	regs->xcs = __USER_CS;					\ | 
					
						
							|  |  |  | 	regs->eip = new_eip;					\ | 
					
						
							|  |  |  | 	regs->esp = new_esp;					\ | 
					
						
							|  |  |  | } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Forward declaration, a strange C thing */ | 
					
						
							|  |  |  | struct task_struct; | 
					
						
							|  |  |  | struct mm_struct; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free all resources held by a thread. */ | 
					
						
							|  |  |  | extern void release_thread(struct task_struct *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Prepare to copy thread state - unlazy all lazy status */ | 
					
						
							|  |  |  | extern void prepare_to_copy(struct task_struct *tsk); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * create a kernel thread without removing it from tasklists | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern unsigned long thread_saved_pc(struct task_struct *tsk); | 
					
						
							| 
									
										
										
										
											2006-06-26 13:57:41 +02:00
										 |  |  | void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | unsigned long get_wchan(struct task_struct *p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
 | 
					
						
							|  |  |  | #define KSTK_TOP(info)                                                 \
 | 
					
						
							|  |  |  | ({                                                                     \ | 
					
						
							|  |  |  |        unsigned long *__ptr = (unsigned long *)(info);                 \ | 
					
						
							|  |  |  |        (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \ | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 01:05:41 -08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  |  * on the stack (interrupt gate does not save these registers | 
					
						
							|  |  |  |  * when switching to the same priv ring). | 
					
						
							|  |  |  |  * Therefore beware: accessing the xss/esp fields of the | 
					
						
							|  |  |  |  * "struct pt_regs" is possible, but they may contain the | 
					
						
							|  |  |  |  * completely wrong values. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define task_pt_regs(task)                                             \
 | 
					
						
							|  |  |  | ({                                                                     \ | 
					
						
							|  |  |  |        struct pt_regs *__regs__;                                       \ | 
					
						
							| 
									
										
										
										
											2006-01-12 01:05:41 -08:00
										 |  |  |        __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |        __regs__ - 1;                                                   \ | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define KSTK_EIP(task) (task_pt_regs(task)->eip)
 | 
					
						
							|  |  |  | #define KSTK_ESP(task) (task_pt_regs(task)->esp)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct microcode_header { | 
					
						
							|  |  |  | 	unsigned int hdrver; | 
					
						
							|  |  |  | 	unsigned int rev; | 
					
						
							|  |  |  | 	unsigned int date; | 
					
						
							|  |  |  | 	unsigned int sig; | 
					
						
							|  |  |  | 	unsigned int cksum; | 
					
						
							|  |  |  | 	unsigned int ldrver; | 
					
						
							|  |  |  | 	unsigned int pf; | 
					
						
							|  |  |  | 	unsigned int datasize; | 
					
						
							|  |  |  | 	unsigned int totalsize; | 
					
						
							|  |  |  | 	unsigned int reserved[3]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct microcode { | 
					
						
							|  |  |  | 	struct microcode_header hdr; | 
					
						
							|  |  |  | 	unsigned int bits[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct microcode microcode_t; | 
					
						
							|  |  |  | typedef struct microcode_header microcode_header_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* microcode format is extended from prescott processors */ | 
					
						
							|  |  |  | struct extended_signature { | 
					
						
							|  |  |  | 	unsigned int sig; | 
					
						
							|  |  |  | 	unsigned int pf; | 
					
						
							|  |  |  | 	unsigned int cksum; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct extended_sigtable { | 
					
						
							|  |  |  | 	unsigned int count; | 
					
						
							|  |  |  | 	unsigned int cksum; | 
					
						
							|  |  |  | 	unsigned int reserved[3]; | 
					
						
							|  |  |  | 	struct extended_signature sigs[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ | 
					
						
							|  |  |  | static inline void rep_nop(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	__asm__ __volatile__("rep;nop": : :"memory"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define cpu_relax()	rep_nop()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread) | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:13 +02:00
										 |  |  | 	tss->x86_tss.esp0 = thread->esp0; | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | 	/* This can only happen when SEP is enabled, no need to test "SEP"arately */ | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:13 +02:00
										 |  |  | 	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) { | 
					
						
							|  |  |  | 		tss->x86_tss.ss1 = thread->sysenter_cs; | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | 		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | static inline unsigned long native_get_debugreg(int regno) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long val = 0; 	/* Damn you, gcc! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (regno) { | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		asm("movl %%db0, %0" :"=r" (val)); break; | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		asm("movl %%db1, %0" :"=r" (val)); break; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		asm("movl %%db2, %0" :"=r" (val)); break; | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 		asm("movl %%db3, %0" :"=r" (val)); break; | 
					
						
							|  |  |  | 	case 6: | 
					
						
							|  |  |  | 		asm("movl %%db6, %0" :"=r" (val)); break; | 
					
						
							|  |  |  | 	case 7: | 
					
						
							|  |  |  | 		asm("movl %%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("movl %0,%%db0"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		asm("movl %0,%%db1"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		asm("movl %0,%%db2"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 		asm("movl %0,%%db3"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 6: | 
					
						
							|  |  |  | 		asm("movl %0,%%db6"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 7: | 
					
						
							|  |  |  | 		asm("movl %0,%%db7"	: /* no output */ :"r" (value)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		BUG(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set IOPL bits in EFLAGS from given mask | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | static inline void native_set_iopl_mask(unsigned mask) | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned int reg; | 
					
						
							|  |  |  | 	__asm__ __volatile__ ("pushfl;" | 
					
						
							|  |  |  | 			      "popl %0;" | 
					
						
							|  |  |  | 			      "andl %1, %0;" | 
					
						
							|  |  |  | 			      "orl %2, %0;" | 
					
						
							|  |  |  | 			      "pushl %0;" | 
					
						
							|  |  |  | 			      "popfl" | 
					
						
							|  |  |  | 				: "=&r" (reg) | 
					
						
							|  |  |  | 				: "i" (~X86_EFLAGS_IOPL), "r" (mask)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | #ifdef CONFIG_PARAVIRT
 | 
					
						
							|  |  |  | #include <asm/paravirt.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define paravirt_enabled() 0
 | 
					
						
							|  |  |  | #define __cpuid native_cpuid
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	native_load_esp0(tss, thread); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * 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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define set_iopl_mask native_set_iopl_mask
 | 
					
						
							|  |  |  | #endif /* CONFIG_PARAVIRT */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Generic CPUID function | 
					
						
							|  |  |  |  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx | 
					
						
							|  |  |  |  * resulting in stale register contents being returned. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-10-17 18:04:38 +02:00
										 |  |  | static inline void cpuid(unsigned int op, | 
					
						
							|  |  |  | 			 unsigned int *eax, unsigned int *ebx, | 
					
						
							|  |  |  | 			 unsigned int *ecx, unsigned int *edx) | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	*eax = op; | 
					
						
							|  |  |  | 	*ecx = 0; | 
					
						
							|  |  |  | 	__cpuid(eax, ebx, ecx, edx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Some CPUID calls want 'count' to be placed in ecx */ | 
					
						
							| 
									
										
										
										
											2007-10-17 18:04:38 +02:00
										 |  |  | static inline void cpuid_count(unsigned int op, int count, | 
					
						
							|  |  |  | 			       unsigned int *eax, unsigned int *ebx, | 
					
						
							|  |  |  | 			       unsigned int *ecx, unsigned int *edx) | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	*eax = op; | 
					
						
							|  |  |  | 	*ecx = count; | 
					
						
							|  |  |  | 	__cpuid(eax, ebx, ecx, edx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * CPUID functions returning a single datum | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline unsigned int cpuid_eax(unsigned int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int eax, ebx, ecx, edx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cpuid(op, &eax, &ebx, &ecx, &edx); | 
					
						
							|  |  |  | 	return eax; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static inline unsigned int cpuid_ebx(unsigned int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int eax, ebx, ecx, edx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cpuid(op, &eax, &ebx, &ecx, &edx); | 
					
						
							|  |  |  | 	return ebx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static inline unsigned int cpuid_ecx(unsigned int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int eax, ebx, ecx, edx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cpuid(op, &eax, &ebx, &ecx, &edx); | 
					
						
							|  |  |  | 	return ecx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static inline unsigned int cpuid_edx(unsigned int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int eax, ebx, ecx, edx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cpuid(op, &eax, &ebx, &ecx, &edx); | 
					
						
							|  |  |  | 	return edx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* generic versions from gas */ | 
					
						
							|  |  |  | #define GENERIC_NOP1	".byte 0x90\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP2    	".byte 0x89,0xf6\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP3        ".byte 0x8d,0x76,0x00\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP4        ".byte 0x8d,0x74,0x26,0x00\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP5        GENERIC_NOP1 GENERIC_NOP4
 | 
					
						
							|  |  |  | #define GENERIC_NOP6	".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP7	".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
 | 
					
						
							|  |  |  | #define GENERIC_NOP8	GENERIC_NOP1 GENERIC_NOP7
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Opteron nops */ | 
					
						
							|  |  |  | #define K8_NOP1 GENERIC_NOP1
 | 
					
						
							|  |  |  | #define K8_NOP2	".byte 0x66,0x90\n" 
 | 
					
						
							|  |  |  | #define K8_NOP3	".byte 0x66,0x66,0x90\n" 
 | 
					
						
							|  |  |  | #define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
 | 
					
						
							|  |  |  | #define K8_NOP5	K8_NOP3 K8_NOP2 
 | 
					
						
							|  |  |  | #define K8_NOP6	K8_NOP3 K8_NOP3
 | 
					
						
							|  |  |  | #define K8_NOP7	K8_NOP4 K8_NOP3
 | 
					
						
							|  |  |  | #define K8_NOP8	K8_NOP4 K8_NOP4
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* K7 nops */ | 
					
						
							|  |  |  | /* uses eax dependencies (arbitary choice) */ | 
					
						
							|  |  |  | #define K7_NOP1  GENERIC_NOP1
 | 
					
						
							|  |  |  | #define K7_NOP2	".byte 0x8b,0xc0\n" 
 | 
					
						
							|  |  |  | #define K7_NOP3	".byte 0x8d,0x04,0x20\n"
 | 
					
						
							|  |  |  | #define K7_NOP4	".byte 0x8d,0x44,0x20,0x00\n"
 | 
					
						
							|  |  |  | #define K7_NOP5	K7_NOP4 ASM_NOP1
 | 
					
						
							|  |  |  | #define K7_NOP6	".byte 0x8d,0x80,0,0,0,0\n"
 | 
					
						
							|  |  |  | #define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
 | 
					
						
							|  |  |  | #define K7_NOP8        K7_NOP7 ASM_NOP1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-17 18:04:41 +02:00
										 |  |  | /* P6 nops */ | 
					
						
							|  |  |  | /* uses eax dependencies (Intel-recommended choice) */ | 
					
						
							|  |  |  | #define P6_NOP1	GENERIC_NOP1
 | 
					
						
							|  |  |  | #define P6_NOP2	".byte 0x66,0x90\n"
 | 
					
						
							|  |  |  | #define P6_NOP3	".byte 0x0f,0x1f,0x00\n"
 | 
					
						
							|  |  |  | #define P6_NOP4	".byte 0x0f,0x1f,0x40,0\n"
 | 
					
						
							|  |  |  | #define P6_NOP5	".byte 0x0f,0x1f,0x44,0x00,0\n"
 | 
					
						
							|  |  |  | #define P6_NOP6	".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
 | 
					
						
							|  |  |  | #define P6_NOP7	".byte 0x0f,0x1f,0x80,0,0,0,0\n"
 | 
					
						
							|  |  |  | #define P6_NOP8	".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef CONFIG_MK8
 | 
					
						
							|  |  |  | #define ASM_NOP1 K8_NOP1
 | 
					
						
							|  |  |  | #define ASM_NOP2 K8_NOP2
 | 
					
						
							|  |  |  | #define ASM_NOP3 K8_NOP3
 | 
					
						
							|  |  |  | #define ASM_NOP4 K8_NOP4
 | 
					
						
							|  |  |  | #define ASM_NOP5 K8_NOP5
 | 
					
						
							|  |  |  | #define ASM_NOP6 K8_NOP6
 | 
					
						
							|  |  |  | #define ASM_NOP7 K8_NOP7
 | 
					
						
							|  |  |  | #define ASM_NOP8 K8_NOP8
 | 
					
						
							|  |  |  | #elif defined(CONFIG_MK7)
 | 
					
						
							|  |  |  | #define ASM_NOP1 K7_NOP1
 | 
					
						
							|  |  |  | #define ASM_NOP2 K7_NOP2
 | 
					
						
							|  |  |  | #define ASM_NOP3 K7_NOP3
 | 
					
						
							|  |  |  | #define ASM_NOP4 K7_NOP4
 | 
					
						
							|  |  |  | #define ASM_NOP5 K7_NOP5
 | 
					
						
							|  |  |  | #define ASM_NOP6 K7_NOP6
 | 
					
						
							|  |  |  | #define ASM_NOP7 K7_NOP7
 | 
					
						
							|  |  |  | #define ASM_NOP8 K7_NOP8
 | 
					
						
							| 
									
										
										
										
											2007-10-17 18:04:41 +02:00
										 |  |  | #elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
 | 
					
						
							|  |  |  |       defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \ | 
					
						
							|  |  |  |       defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4) | 
					
						
							|  |  |  | #define ASM_NOP1 P6_NOP1
 | 
					
						
							|  |  |  | #define ASM_NOP2 P6_NOP2
 | 
					
						
							|  |  |  | #define ASM_NOP3 P6_NOP3
 | 
					
						
							|  |  |  | #define ASM_NOP4 P6_NOP4
 | 
					
						
							|  |  |  | #define ASM_NOP5 P6_NOP5
 | 
					
						
							|  |  |  | #define ASM_NOP6 P6_NOP6
 | 
					
						
							|  |  |  | #define ASM_NOP7 P6_NOP7
 | 
					
						
							|  |  |  | #define ASM_NOP8 P6_NOP8
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #define ASM_NOP1 GENERIC_NOP1
 | 
					
						
							|  |  |  | #define ASM_NOP2 GENERIC_NOP2
 | 
					
						
							|  |  |  | #define ASM_NOP3 GENERIC_NOP3
 | 
					
						
							|  |  |  | #define ASM_NOP4 GENERIC_NOP4
 | 
					
						
							|  |  |  | #define ASM_NOP5 GENERIC_NOP5
 | 
					
						
							|  |  |  | #define ASM_NOP6 GENERIC_NOP6
 | 
					
						
							|  |  |  | #define ASM_NOP7 GENERIC_NOP7
 | 
					
						
							|  |  |  | #define ASM_NOP8 GENERIC_NOP8
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ASM_NOP_MAX 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Prefetch instructions for Pentium III and AMD Athlon */ | 
					
						
							|  |  |  | /* It's not worth to care about 3dnow! prefetches for the K6
 | 
					
						
							|  |  |  |    because they are microcoded there and very slow. | 
					
						
							|  |  |  |    However we don't do prefetches for pre XP Athlons currently | 
					
						
							|  |  |  |    That should be fixed. */ | 
					
						
							|  |  |  | #define ARCH_HAS_PREFETCH
 | 
					
						
							| 
									
										
										
										
											2005-09-10 00:27:16 -07:00
										 |  |  | static inline void prefetch(const void *x) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	alternative_input(ASM_NOP4, | 
					
						
							|  |  |  | 			  "prefetchnta (%1)", | 
					
						
							|  |  |  | 			  X86_FEATURE_XMM, | 
					
						
							|  |  |  | 			  "r" (x)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ARCH_HAS_PREFETCH
 | 
					
						
							|  |  |  | #define ARCH_HAS_PREFETCHW
 | 
					
						
							|  |  |  | #define ARCH_HAS_SPINLOCK_PREFETCH
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 3dnow! prefetch to get an exclusive cache line. Useful for 
 | 
					
						
							|  |  |  |    spinlocks to avoid one state transition in the cache coherency protocol. */ | 
					
						
							| 
									
										
										
										
											2005-09-10 00:27:16 -07:00
										 |  |  | static inline void prefetchw(const void *x) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	alternative_input(ASM_NOP4, | 
					
						
							|  |  |  | 			  "prefetchw (%1)", | 
					
						
							|  |  |  | 			  X86_FEATURE_3DNOW, | 
					
						
							|  |  |  | 			  "r" (x)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #define spin_lock_prefetch(x)	prefetchw(x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void select_idle_routine(const struct cpuinfo_x86 *c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern unsigned long boot_option_idle_override; | 
					
						
							| 
									
										
										
										
											2005-06-25 14:54:53 -07:00
										 |  |  | extern void enable_sep_cpu(void); | 
					
						
							|  |  |  | extern int sysenter_setup(void); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-15 01:41:48 -07:00
										 |  |  | /* Defined in head.S */ | 
					
						
							|  |  |  | extern struct Xgt_desc_struct early_gdt_descr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-22 09:18:31 -06:00
										 |  |  | extern void cpu_set_gdt(int); | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:16 +02:00
										 |  |  | extern void switch_to_new_gdt(void); | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:10 +02:00
										 |  |  | extern void cpu_init(void); | 
					
						
							| 
									
										
										
										
											2007-05-15 01:41:48 -07:00
										 |  |  | extern void init_gdt(int cpu); | 
					
						
							| 
									
										
										
										
											2006-12-07 02:14:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-02 19:27:12 +02:00
										 |  |  | extern int force_mwait; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #endif /* __ASM_I386_PROCESSOR_H */
 |