processor_64.h 11.9 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_X86_64_PROCESSOR_H
#define __ASM_X86_64_PROCESSOR_H

#include <asm/segment.h>
#include <asm/page.h>
#include <asm/types.h>
#include <asm/sigcontext.h>
#include <asm/cpufeature.h>
#include <linux/threads.h>
#include <asm/msr.h>
#include <asm/current.h>
#include <asm/system.h>
#include <asm/mmsegment.h>
#include <asm/percpu.h>
#include <linux/personality.h>
20
#include <linux/cpumask.h>
21
#include <asm/processor-flags.h>
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29 30 31 32

#define TF_MASK		0x00000100
#define IF_MASK		0x00000200
#define IOPL_MASK	0x00003000
#define NT_MASK		0x00004000
#define VM_MASK		0x00020000
#define AC_MASK		0x00040000
#define VIF_MASK	0x00080000	/* virtual interrupt flag */
#define VIP_MASK	0x00100000	/* virtual interrupt pending */
#define ID_MASK		0x00200000

R
Roland McGrath 已提交
33 34 35 36 37
static inline int desc_empty(const void *ptr)
{
	const u32 *desc = ptr;
	return !(desc[0] | desc[1]);
}
L
Linus Torvalds 已提交
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

/*
 * Default implementation of macro that returns current
 * instruction pointer ("program counter").
 */
#define current_text_addr() ({ void *pc; asm volatile("leaq 1f(%%rip),%0\n1:":"=r"(pc)); pc; })

/*
 *  CPU type and hardware bug flags. Kept separately for each CPU.
 */

struct cpuinfo_x86 {
	__u8	x86;		/* CPU family */
	__u8	x86_vendor;	/* CPU vendor */
	__u8	x86_model;
	__u8	x86_mask;
	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
	__u32	x86_capability[NCAPINTS];
	char	x86_vendor_id[16];
	char	x86_model_id[64];
	int 	x86_cache_size;  /* in KB */
	int	x86_clflush_size;
	int	x86_cache_alignment;
	int	x86_tlbsize;	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
        __u8    x86_virt_bits, x86_phys_bits;
63
	__u8	x86_max_cores;	/* cpuid returned max cores value */
64
	__u8	x86_coreid_bits; /* cpuid returned core id bits */
L
Linus Torvalds 已提交
65
        __u32   x86_power; 	
66
	__u32   extended_cpuid_level;	/* Max extended CPUID function supported */
L
Linus Torvalds 已提交
67
	unsigned long loops_per_jiffy;
68 69 70
#ifdef CONFIG_SMP
	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
#endif
71
	__u8	apicid;
72
#ifdef CONFIG_SMP
73
	__u8	booted_cores;	/* number of cores as seen by OS */
74 75
	__u8	phys_proc_id;	/* Physical Processor id. */
	__u8	cpu_core_id;	/* Core id. */
76
	__u8	cpu_index;	/* index into per_cpu list */
77
#endif
L
Linus Torvalds 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90
} ____cacheline_aligned;

#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_NUM 8
#define X86_VENDOR_UNKNOWN 0xff

#ifdef CONFIG_SMP
91 92 93
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 已提交
94
#else
95 96
#define cpu_data(cpu)		boot_cpu_data
#define current_cpu_data	boot_cpu_data
L
Linus Torvalds 已提交
97 98 99 100 101 102
#endif

extern char ignore_irq13;

extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
103
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
L
Linus Torvalds 已提交
104
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
105
extern unsigned short num_cache_leaves;
L
Linus Torvalds 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

/*
 * 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)
{
	mmu_cr4_features |= mask;
	__asm__("movq %%cr4,%%rax\n\t"
		"orq %0,%%rax\n\t"
		"movq %%rax,%%cr4\n"
		: : "irg" (mask)
		:"ax");
}

static inline void clear_in_cr4 (unsigned long mask)
{
	mmu_cr4_features &= ~mask;
	__asm__("movq %%cr4,%%rax\n\t"
		"andq %0,%%rax\n\t"
		"movq %%rax,%%cr4\n"
		: : "irg" (~mask)
		:"ax");
}


/*
137
 * User space process size. 47bits minus one guard page.
L
Linus Torvalds 已提交
138
 */
139
#define TASK_SIZE64	(0x800000000000UL - 4096)
L
Linus Torvalds 已提交
140 141 142 143 144

/* This decides where the kernel will search for a free chunk of vm
 * space during mmap's.
 */
#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
145 146 147 148 149

#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)

#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE/3)
L
Linus Torvalds 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

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

struct i387_fxsave_struct {
	u16	cwd;
	u16	swd;
	u16	twd;
	u16	fop;
	u64	rip;
	u64	rdp; 
	u32	mxcsr;
	u32	mxcsr_mask;
	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
170
	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	u32	padding[24];
} __attribute__ ((aligned (16)));

union i387_union {
	struct i387_fxsave_struct	fxsave;
};

struct tss_struct {
	u32 reserved1;
	u64 rsp0;	
	u64 rsp1;
	u64 rsp2;
	u64 reserved2;
	u64 ist[7];
	u32 reserved3;
	u32 reserved4;
	u16 reserved5;
	u16 io_bitmap_base;
	/*
	 * 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. Thus we have:
	 *
	 * 128 bytes, the bitmap itself, for ports 0..0x3ff
	 * 8 bytes, for an extra "long" of ~0UL
	 */
	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
} __attribute__((packed)) ____cacheline_aligned;

201

L
Linus Torvalds 已提交
202 203
extern struct cpuinfo_x86 boot_cpu_data;
DECLARE_PER_CPU(struct tss_struct,init_tss);
204 205 206 207 208
/* Save the original ist values for checking stack pointers during debugging */
struct orig_ist {
	unsigned long ist[7];
};
DECLARE_PER_CPU(struct orig_ist, orig_ist);
L
Linus Torvalds 已提交
209

210 211 212 213
#ifdef CONFIG_X86_VSMP
#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
#else
L
Linus Torvalds 已提交
214
#define ARCH_MIN_TASKALIGN	16
215 216
#define ARCH_MIN_MMSTRUCT_ALIGN	0
#endif
L
Linus Torvalds 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240

struct thread_struct {
	unsigned long	rsp0;
	unsigned long	rsp;
	unsigned long 	userrsp;	/* Copy from PDA */ 
	unsigned long	fs;
	unsigned long	gs;
	unsigned short	es, ds, fsindex, gsindex;	
/* Hardware debugging registers */
	unsigned long	debugreg0;  
	unsigned long	debugreg1;  
	unsigned long	debugreg2;  
	unsigned long	debugreg3;  
	unsigned long	debugreg6;  
	unsigned long	debugreg7;  
/* fault info */
	unsigned long	cr2, trap_no, error_code;
/* floating point info */
	union i387_union	i387  __attribute__((aligned(16)));
/* IO permissions. the bitmap could be moved into the GDT, that would make
   switch faster for a limited number of ioperm using tasks. -AK */
	int		ioperm;
	unsigned long	*io_bitmap_ptr;
	unsigned io_bitmap_max;
R
Roland McGrath 已提交
241 242
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
	unsigned long	debugctlmsr;
L
Linus Torvalds 已提交
243 244 245 246
/* cached TLS descriptors. */
	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
} __attribute__((aligned(16)));

247 248 249 250 251 252 253
#define INIT_THREAD  { \
	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
}

#define INIT_TSS  { \
	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
}
L
Linus Torvalds 已提交
254 255 256 257 258 259 260

#define INIT_MMAP \
{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }

#define start_thread(regs,new_rip,new_rsp) do { \
	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));	 \
	load_gs_index(0);							\
261 262
	(regs)->ip = (new_rip);						 \
	(regs)->sp = (new_rsp);						 \
L
Linus Torvalds 已提交
263 264 265
	write_pda(oldrsp, (new_rsp));						 \
	(regs)->cs = __USER_CS;							 \
	(regs)->ss = __USER_DS;							 \
266
	(regs)->flags = 0x200;							 \
L
Linus Torvalds 已提交
267 268 269
	set_fs(USER_DS);							 \
} while(0) 

270 271 272 273 274 275 276 277
#define get_debugreg(var, register)				\
		__asm__("movq %%db" #register ", %0"		\
			:"=r" (var))
#define set_debugreg(value, register)			\
		__asm__("movq %0,%%db" #register		\
			: /* no output */			\
			:"r" (value))

L
Linus Torvalds 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
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 long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);

/*
 * Return saved PC of a blocked thread.
 * What is this good for? it will be always the scheduler or ret_from_fork.
 */
#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8))

extern unsigned long get_wchan(struct task_struct *p);
A
Al Viro 已提交
299
#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1)
300
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->ip)
L
Linus Torvalds 已提交
301 302 303 304 305 306 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 334 335 336 337 338 339
#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */


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


340 341 342 343 344 345 346 347 348 349
#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2)
#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
#else
L
Linus Torvalds 已提交
350 351 352 353 354 355 356 357
#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
358
#endif
L
Linus Torvalds 已提交
359 360 361 362 363 364 365 366 367 368 369

/* Opteron nops */
#define K8_NOP1 ".byte 0x90\n"
#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

370 371 372 373 374 375 376 377 378 379 380
/* P6 nops */
/* uses eax dependencies (Intel-recommended choice) */
#define P6_NOP1	".byte 0x90\n"
#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 已提交
381 382 383
#define ASM_NOP_MAX 8

/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
384
static inline void rep_nop(void)
L
Linus Torvalds 已提交
385 386 387 388 389
{
	__asm__ __volatile__("rep;nop": : :"memory");
}

/* Stop speculative execution */
390
static inline void sync_core(void)
L
Linus Torvalds 已提交
391 392 393 394 395 396 397 398
{ 
	int tmp;
	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
} 

#define ARCH_HAS_PREFETCHW 1
static inline void prefetchw(void *x) 
{ 
399
	alternative_input("prefetcht0 (%1)",
L
Linus Torvalds 已提交
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 427
			  "prefetchw (%1)",
			  X86_FEATURE_3DNOW,
			  "r" (x));
} 

#define ARCH_HAS_SPINLOCK_PREFETCH 1

#define spin_lock_prefetch(x)  prefetchw(x)

#define cpu_relax()   rep_nop()

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

428 429 430 431 432 433 434 435
static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
{
	/* "mwait %eax,%ecx;" */
	asm volatile(
		"sti; .byte 0x0f,0x01,0xc9;"
		: :"a" (eax), "c" (ecx));
}

436 437
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);

438 439 440 441
extern int force_mwait;

extern void select_idle_routine(const struct cpuinfo_x86 *c);

L
Linus Torvalds 已提交
442 443 444 445 446 447 448 449 450 451 452 453 454
#define stack_current() \
({								\
	struct thread_info *ti;					\
	asm("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
	ti->task;					\
})

#define cache_line_size() (boot_cpu_data.x86_cache_alignment)

extern unsigned long boot_option_idle_override;
/* Boot loader type from the setup header */
extern int bootloader_type;

455 456
#define HAVE_ARCH_PICK_MMAP_LAYOUT 1

L
Linus Torvalds 已提交
457
#endif /* __ASM_X86_64_PROCESSOR_H */