processor_32.h 18.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * 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>
20
#include <linux/cpumask.h>
21
#include <linux/init.h>
22
#include <asm/processor-flags.h>
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30

/* flag for disabling the tsc */
extern int tsc_disable;

struct desc_struct {
	unsigned long a,b;
};

R
Roland McGrath 已提交
31 32 33 34 35
static inline int desc_empty(const void *ptr)
{
	const u32 *desc = ptr;
	return !(desc[0] | desc[1]);
}
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

/*
 * 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 */
65 66 67 68 69
	char	fdiv_bug;
	char	f00f_bug;
	char	coma_bug;
	char	pad0;
	int	x86_power;
L
Linus Torvalds 已提交
70
	unsigned long loops_per_jiffy;
71 72 73
#ifdef CONFIG_SMP
	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
#endif
74 75
	unsigned char x86_max_cores;	/* cpuid returned max cores value */
	unsigned char apicid;
76
	unsigned short x86_clflush_size;
77 78 79 80
#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 */
81
	__u8 cpu_index;			/* index into per_cpu list */
82
#endif
L
Linus Torvalds 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
} __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
106 107 108
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())
L
Linus Torvalds 已提交
109
#else
110 111
#define cpu_data(cpu)		boot_cpu_data
#define current_cpu_data	boot_cpu_data
L
Linus Torvalds 已提交
112 113
#endif

114 115 116 117 118
/*
 * the following now lives in the per cpu area:
 * extern	int cpu_llc_id[NR_CPUS];
 */
DECLARE_PER_CPU(u8, cpu_llc_id);
L
Linus Torvalds 已提交
119 120
extern char ignore_fpu_irq;

121 122
void __init cpu_detect(struct cpuinfo_x86 *c);

123 124
extern void identify_boot_cpu(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
L
Linus Torvalds 已提交
125
extern void print_cpu_info(struct cpuinfo_x86 *);
126
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
L
Linus Torvalds 已提交
127
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
128
extern unsigned short num_cache_leaves;
L
Linus Torvalds 已提交
129 130 131 132 133 134 135

#ifdef CONFIG_X86_HT
extern void detect_ht(struct cpuinfo_x86 *c);
#else
static inline void detect_ht(struct cpuinfo_x86 *c) {}
#endif

136
#define load_cr3(pgdir) write_cr3(__pa(pgdir))
L
Linus Torvalds 已提交
137 138 139 140 141 142 143 144 145 146 147

/*
 * 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)
{
148
	unsigned cr4;
L
Linus Torvalds 已提交
149
	mmu_cr4_features |= mask;
150 151 152
	cr4 = read_cr4();
	cr4 |= mask;
	write_cr4(cr4);
L
Linus Torvalds 已提交
153 154 155 156
}

static inline void clear_in_cr4 (unsigned long mask)
{
157
	unsigned cr4;
L
Linus Torvalds 已提交
158
	mmu_cr4_features &= ~mask;
159 160 161
	cr4 = read_cr4();
	cr4 &= ~mask;
	write_cr4(cr4);
L
Linus Torvalds 已提交
162 163
}

164 165
/* Stop speculative execution */
static inline void sync_core(void)
166
{
167 168
	int tmp;
	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
169 170
}

L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
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));
}

188 189
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);

L
Linus Torvalds 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
/* 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

212 213 214 215
extern void hard_disable_TSC(void);
extern void disable_TSC(void);
extern void hard_enable_TSC(void);

L
Linus Torvalds 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
/*
 * 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;

280 281
/* This is the TSS defined by the hardware. */
struct i386_hw_tss {
L
Linus Torvalds 已提交
282
	unsigned short	back_link,__blh;
283
	unsigned long	sp0;
L
Linus Torvalds 已提交
284
	unsigned short	ss0,__ss0h;
285
	unsigned long	sp1;
L
Linus Torvalds 已提交
286
	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
287
	unsigned long	sp2;
L
Linus Torvalds 已提交
288 289
	unsigned short	ss2,__ss2h;
	unsigned long	__cr3;
290 291 292 293
	unsigned long	ip;
	unsigned long	flags;
	unsigned long	ax, cx, dx, bx;
	unsigned long	sp, bp, si, di;
L
Linus Torvalds 已提交
294 295 296 297 298 299 300 301
	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;
302 303 304 305 306
} __attribute__((packed));

struct tss_struct {
	struct i386_hw_tss x86_tss;

L
Linus Torvalds 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	/*
	 * 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];
334
	unsigned long	sp0;
L
Linus Torvalds 已提交
335
	unsigned long	sysenter_cs;
336 337
	unsigned long	ip;
	unsigned long	sp;
L
Linus Torvalds 已提交
338 339 340
	unsigned long	fs;
	unsigned long	gs;
/* Hardware debugging registers */
341 342 343 344 345 346
	unsigned long	debugreg0;
	unsigned long	debugreg1;
	unsigned long	debugreg2;
	unsigned long	debugreg3;
	unsigned long	debugreg6;
	unsigned long	debugreg7;
L
Linus Torvalds 已提交
347 348 349 350 351 352 353
/* 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;
354
	unsigned long		v86flags, v86mask, saved_sp0;
L
Linus Torvalds 已提交
355 356 357
	unsigned int		saved_fs, saved_gs;
/* IO permissions */
	unsigned long	*io_bitmap_ptr;
Z
Zachary Amsden 已提交
358
 	unsigned long	iopl;
L
Linus Torvalds 已提交
359 360
/* max allowed port in the bitmap, in bytes: */
	unsigned long	io_bitmap_max;
R
Roland McGrath 已提交
361 362
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
	unsigned long	debugctlmsr;
L
Linus Torvalds 已提交
363 364 365
};

#define INIT_THREAD  {							\
366
	.sp0 = sizeof(init_stack) + (long)&init_stack,			\
L
Linus Torvalds 已提交
367 368 369
	.vm86_info = NULL,						\
	.sysenter_cs = __KERNEL_CS,					\
	.io_bitmap_ptr = NULL,						\
370
	.fs = __KERNEL_PERCPU,						\
L
Linus Torvalds 已提交
371 372 373 374 375 376 377 378 379
}

/*
 * 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  {							\
380
	.x86_tss = {							\
381
		.sp0		= sizeof(init_stack) + (long)&init_stack, \
382 383 384 385
		.ss0		= __KERNEL_DS,				\
		.ss1		= __KERNEL_CS,				\
		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
	 },								\
L
Linus Torvalds 已提交
386 387 388 389
	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
}

#define start_thread(regs, new_eip, new_esp) do {		\
390
	__asm__("movl %0,%%gs": :"r" (0));			\
391
	regs->fs = 0;						\
L
Linus Torvalds 已提交
392
	set_fs(USER_DS);					\
393 394 395 396 397 398
	regs->ds = __USER_DS;					\
	regs->es = __USER_DS;					\
	regs->ss = __USER_DS;					\
	regs->cs = __USER_CS;					\
	regs->ip = new_eip;					\
	regs->sp = new_esp;					\
L
Linus Torvalds 已提交
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
} 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);

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]);                     \
})

A
akpm@osdl.org 已提交
427 428 429 430 431 432
/*
 * 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).
433
 * Therefore beware: accessing the ss/esp fields of the
A
akpm@osdl.org 已提交
434 435 436
 * "struct pt_regs" is possible, but they may contain the
 * completely wrong values.
 */
L
Linus Torvalds 已提交
437 438 439
#define task_pt_regs(task)                                             \
({                                                                     \
       struct pt_regs *__regs__;                                       \
A
Al Viro 已提交
440
       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
L
Linus Torvalds 已提交
441 442 443
       __regs__ - 1;                                                   \
})

444 445
#define KSTK_EIP(task) (task_pt_regs(task)->ip)
#define KSTK_ESP(task) (task_pt_regs(task)->sp)
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490


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()

491
static inline void native_load_sp0(struct tss_struct *tss, struct thread_struct *thread)
492
{
493
	tss->x86_tss.sp0 = thread->sp0;
494
	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
495 496
	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
		tss->x86_tss.ss1 = thread->sysenter_cs;
497 498 499 500 501
		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
	}
}


502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
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();
	}
}
550 551 552 553

/*
 * Set IOPL bits in EFLAGS from given mask
 */
554
static inline void native_set_iopl_mask(unsigned mask)
555 556 557 558 559 560 561 562 563 564 565 566
{
	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));
}

567 568 569 570 571
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
#define paravirt_enabled() 0

572
static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread)
573
{
574
	native_load_sp0(tss, thread);
575 576 577 578 579 580 581 582 583 584 585 586 587
}

/*
 * 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 */

L
Linus Torvalds 已提交
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
/* 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

619 620 621 622 623 624 625 626 627 628 629
/* 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"

L
Linus Torvalds 已提交
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
#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
648 649 650 651 652 653 654 655 656 657 658
#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
L
Linus Torvalds 已提交
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
#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
678
static inline void prefetch(const void *x)
L
Linus Torvalds 已提交
679 680 681 682 683 684 685 686 687 688 689 690 691
{
	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. */
692
static inline void prefetchw(const void *x)
L
Linus Torvalds 已提交
693 694 695 696 697 698 699 700 701 702 703 704 705
{
	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;
L
Li Shaohua 已提交
706 707
extern void enable_sep_cpu(void);
extern int sysenter_setup(void);
L
Linus Torvalds 已提交
708

709 710 711
/* Defined in head.S */
extern struct Xgt_desc_struct early_gdt_descr;

712
extern void cpu_set_gdt(int);
713
extern void switch_to_new_gdt(void);
714
extern void cpu_init(void);
715
extern void init_gdt(int cpu);
716

717 718
extern int force_mwait;

L
Linus Torvalds 已提交
719
#endif /* __ASM_I386_PROCESSOR_H */