Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 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 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 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 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 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 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | /* * include/asm-x86_64/processor.h * * 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/config.h> #include <linux/threads.h> #include <asm/msr.h> #include <asm/current.h> #include <asm/system.h> #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 #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. * 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; /* We know that wp_works_ok = 1, hlt_works_ok = 1, hard_math = 1, etc... */ 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 */ __u32 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 fdiv_bug; int f00f_bug; int coma_bug; unsigned long loops_per_jiffy; } ____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_RISE 6 #define X86_VENDOR_TRANSMETA 7 #define X86_VENDOR_UNKNOWN 0xff extern struct cpuinfo_x86 boot_cpu_data; extern struct tss_struct init_tss[NR_CPUS]; #ifdef CONFIG_SMP extern struct cpuinfo_x86 cpu_data[]; #define current_cpu_data cpu_data[smp_processor_id()] #else #define cpu_data &boot_cpu_data #define current_cpu_data boot_cpu_data #endif #define cpu_has_pge 1 #define cpu_has_pse 1 #define cpu_has_pae 1 #define cpu_has_tsc 1 #define cpu_has_de 1 #define cpu_has_vme 1 #define cpu_has_fxsr 1 #define cpu_has_xmm 1 #define cpu_has_apic 1 extern char ignore_irq13; extern void identify_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); extern void dodgy_tsc(void); /* * EFLAGS bits */ #define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ #define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ #define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ #define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ #define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ #define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ #define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ #define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ #define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ #define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ #define X86_EFLAGS_NT 0x00004000 /* Nested Task */ #define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ #define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ #define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ #define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ /* * Generic CPUID function * FIXME: This really belongs to msr.h */ extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) { __asm__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op)); } /* * CPUID functions returning a single datum */ extern inline unsigned int cpuid_eax(unsigned int op) { unsigned int eax; __asm__("cpuid" : "=a" (eax) : "0" (op) : "bx", "cx", "dx"); return eax; } extern inline unsigned int cpuid_ebx(unsigned int op) { unsigned int eax, ebx; __asm__("cpuid" : "=a" (eax), "=b" (ebx) : "0" (op) : "cx", "dx" ); return ebx; } extern inline unsigned int cpuid_ecx(unsigned int op) { unsigned int eax, ecx; __asm__("cpuid" : "=a" (eax), "=c" (ecx) : "0" (op) : "bx", "dx" ); return ecx; } extern inline unsigned int cpuid_edx(unsigned int op) { unsigned int eax, edx; __asm__("cpuid" : "=a" (eax), "=d" (edx) : "0" (op) : "bx", "cx"); return edx; } /* * Intel CPU features in CR4 */ #define X86_CR4_VME 0x0001 /* enable vm86 extensions */ #define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ #define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ #define X86_CR4_DE 0x0008 /* enable debugging extensions */ #define X86_CR4_PSE 0x0010 /* enable page size extensions */ #define X86_CR4_PAE 0x0020 /* enable physical address extensions */ #define X86_CR4_MCE 0x0040 /* Machine check enable */ #define X86_CR4_PGE 0x0080 /* enable global pages */ #define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ #define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ #define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ /* * 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"); } #define CX86_CCR0 0xc0 #define CX86_CCR1 0xc1 #define CX86_CCR2 0xc2 #define CX86_CCR3 0xc3 #define CX86_CCR4 0xe8 #define CX86_CCR5 0xe9 #define CX86_CCR6 0xea #define CX86_CCR7 0xeb #define CX86_DIR0 0xfe #define CX86_DIR1 0xff #define CX86_ARR_BASE 0xc4 #define CX86_RCR_BASE 0xdc /* * Cyrix CPU indexed register access macros */ #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) #define setCx86(reg, data) do { \ outb((reg), 0x22); \ outb((data), 0x23); \ } while (0) /* * Bus types */ #define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro /* * User space process size: 512GB - 1GB (default). */ #define TASK_SIZE (0x0000007fc0000000) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ #define TASK_UNMAPPED_32 0x40000000 #define TASK_UNMAPPED_64 (TASK_SIZE/3) #define TASK_UNMAPPED_BASE \ ((current->thread.flags & THREAD_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64) /* * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. */ #define IO_BITMAP_SIZE 32 #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define INVALID_IO_BITMAP_OFFSET 0x8000 /* We'll have to decide which format to use for floating stores, and kill all others... */ struct i387_fsave_struct { u32 cwd; u32 swd; u32 twd; u32 fip; u32 fcs; u32 foo; u32 fos; u32 st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ u32 status; /* software status information */ }; struct i387_fxsave_struct { u16 cwd; u16 swd; u16 twd; u16 fop; u32 fip; u32 fcs; u32 foo; u32 fos; u32 mxcsr; u32 reserved; u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ u32 xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ u32 padding[56]; } __attribute__ ((aligned (16))); struct i387_soft_struct { u32 cwd; u32 swd; u32 twd; u32 fip; u32 fcs; u32 foo; u32 fos; u32 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 tss_struct { u32 reserved1; u64 rsp0; u64 rsp1; u64 rsp2; u64 reserved2; u64 ist[7]; u32 reserved3; u32 reserved4; u16 reserved5; u16 io_map_base; u32 io_bitmap[IO_BITMAP_SIZE]; } __attribute__((packed)); struct thread_struct { unsigned long rsp0; unsigned long rip; 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 debugreg[8]; /* %%db0-7 debug registers */ /* fault info */ unsigned long cr2, trap_no, error_code; /* floating point info */ union i387_union i387; /* 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; u32 io_bitmap[IO_BITMAP_SIZE+1]; }; #define INIT_THREAD { \ } #define INIT_MMAP \ { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } #ifndef CONFIG_SMP extern char stackfault_stack[]; #define STACKDESC rsp2: (unsigned long)stackfault_stack, #define STACKFAULT_STACK 2 #else #define STACKFAULT_STACK 0 #define STACKDESC #endif /* Doublefault currently shares the same stack on all CPUs. Hopefully only one gets into this unfortunate condition at a time. Cannot do the same for SF because that can be easily triggered by user space. */ #define INIT_TSS { \ rsp1: (unsigned long)doublefault_stack, \ STACKDESC \ } extern char doublefault_stack[]; #define start_thread(regs,new_rip,new_rsp) do { \ __asm__("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0)); \ wrmsrl(MSR_KERNEL_GS_BASE, 0); \ (regs)->rip = (new_rip); \ (regs)->rsp = (new_rsp); \ write_pda(oldrsp, (new_rsp)); \ (regs)->cs = __USER_CS; \ (regs)->ss = __USER_DS; \ (regs)->eflags = 0x200; \ set_fs(USER_DS); \ } while(0) struct task_struct; struct mm_struct; /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); /* * create a kernel thread without removing it from tasklists */ extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* Copy and release all segment info associated with a VM */ extern void copy_segments(struct task_struct *p, struct mm_struct * mm); extern void release_segments(struct mm_struct * mm); /* * Return saved PC of a blocked thread. */ extern inline unsigned long thread_saved_pc(struct task_struct *t) { return -1; /* FIXME */ } unsigned long get_wchan(struct task_struct *p); /* FIXME: this is incorrect when the task is sleeping in a syscall entered through SYSCALL. */ #define __kstk_regs(tsk) \ ((struct pt_regs *)\ (((char *)(tsk)->thread_info) + THREAD_SIZE - sizeof(struct pt_regs))) #define KSTK_EIP(tsk) (__kstk_regs(tsk)->rip) #define KSTK_ESP(tsk) (__kstk_regs(tsk)->rsp) /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ extern inline void rep_nop(void) { __asm__ __volatile__("rep;nop"); } #define cpu_has_fpu 1 /* 3d now! prefetch instructions. Could also use the SSE flavours; not sure if it makes a difference. gcc 3.1 has __builtin_prefetch too, but I am not sure it makes sense to use them. */ #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW #define ARCH_HAS_SPINLOCK_PREFETCH extern inline void prefetch(const void *x) { __asm__ __volatile__ ("prefetch (%0)" : : "r"(x)); } extern inline void prefetchw(const void *x) { __asm__ __volatile__ ("prefetchw (%0)" : : "r"(x)); } #define spin_lock_prefetch(x) prefetchw(x) #define cpu_relax() rep_nop() #endif /* __ASM_X86_64_PROCESSOR_H */ |