Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16-rc2 387 lines 11 kB view raw
1/* $Id: system.h,v 1.69 2002/02/09 19:49:31 davem Exp $ */ 2#ifndef __SPARC64_SYSTEM_H 3#define __SPARC64_SYSTEM_H 4 5#include <linux/config.h> 6#include <asm/ptrace.h> 7#include <asm/processor.h> 8#include <asm/visasm.h> 9 10#ifndef __ASSEMBLY__ 11/* 12 * Sparc (general) CPU types 13 */ 14enum sparc_cpu { 15 sun4 = 0x00, 16 sun4c = 0x01, 17 sun4m = 0x02, 18 sun4d = 0x03, 19 sun4e = 0x04, 20 sun4u = 0x05, /* V8 ploos ploos */ 21 sun_unknown = 0x06, 22 ap1000 = 0x07, /* almost a sun4m */ 23}; 24 25#define sparc_cpu_model sun4u 26 27/* This cannot ever be a sun4c nor sun4 :) That's just history. */ 28#define ARCH_SUN4C_SUN4 0 29#define ARCH_SUN4 0 30 31/* These are here in an effort to more fully work around Spitfire Errata 32 * #51. Essentially, if a memory barrier occurs soon after a mispredicted 33 * branch, the chip can stop executing instructions until a trap occurs. 34 * Therefore, if interrupts are disabled, the chip can hang forever. 35 * 36 * It used to be believed that the memory barrier had to be right in the 37 * delay slot, but a case has been traced recently wherein the memory barrier 38 * was one instruction after the branch delay slot and the chip still hung. 39 * The offending sequence was the following in sym_wakeup_done() of the 40 * sym53c8xx_2 driver: 41 * 42 * call sym_ccb_from_dsa, 0 43 * movge %icc, 0, %l0 44 * brz,pn %o0, .LL1303 45 * mov %o0, %l2 46 * membar #LoadLoad 47 * 48 * The branch has to be mispredicted for the bug to occur. Therefore, we put 49 * the memory barrier explicitly into a "branch always, predicted taken" 50 * delay slot to avoid the problem case. 51 */ 52#define membar_safe(type) \ 53do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ 54 " membar " type "\n" \ 55 "1:\n" \ 56 : : : "memory"); \ 57} while (0) 58 59#define mb() \ 60 membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad") 61#define rmb() \ 62 membar_safe("#LoadLoad") 63#define wmb() \ 64 membar_safe("#StoreStore") 65#define membar_storeload() \ 66 membar_safe("#StoreLoad") 67#define membar_storeload_storestore() \ 68 membar_safe("#StoreLoad | #StoreStore") 69#define membar_storeload_loadload() \ 70 membar_safe("#StoreLoad | #LoadLoad") 71#define membar_storestore_loadstore() \ 72 membar_safe("#StoreStore | #LoadStore") 73 74#endif 75 76#define setipl(__new_ipl) \ 77 __asm__ __volatile__("wrpr %0, %%pil" : : "r" (__new_ipl) : "memory") 78 79#define local_irq_disable() \ 80 __asm__ __volatile__("wrpr 15, %%pil" : : : "memory") 81 82#define local_irq_enable() \ 83 __asm__ __volatile__("wrpr 0, %%pil" : : : "memory") 84 85#define getipl() \ 86({ unsigned long retval; __asm__ __volatile__("rdpr %%pil, %0" : "=r" (retval)); retval; }) 87 88#define swap_pil(__new_pil) \ 89({ unsigned long retval; \ 90 __asm__ __volatile__("rdpr %%pil, %0\n\t" \ 91 "wrpr %1, %%pil" \ 92 : "=&r" (retval) \ 93 : "r" (__new_pil) \ 94 : "memory"); \ 95 retval; \ 96}) 97 98#define read_pil_and_cli() \ 99({ unsigned long retval; \ 100 __asm__ __volatile__("rdpr %%pil, %0\n\t" \ 101 "wrpr 15, %%pil" \ 102 : "=r" (retval) \ 103 : : "memory"); \ 104 retval; \ 105}) 106 107#define local_save_flags(flags) ((flags) = getipl()) 108#define local_irq_save(flags) ((flags) = read_pil_and_cli()) 109#define local_irq_restore(flags) setipl((flags)) 110 111/* On sparc64 IRQ flags are the PIL register. A value of zero 112 * means all interrupt levels are enabled, any other value means 113 * only IRQ levels greater than that value will be received. 114 * Consequently this means that the lowest IRQ level is one. 115 */ 116#define irqs_disabled() \ 117({ unsigned long flags; \ 118 local_save_flags(flags);\ 119 (flags > 0); \ 120}) 121 122#define nop() __asm__ __volatile__ ("nop") 123 124#define read_barrier_depends() do { } while(0) 125#define set_mb(__var, __value) \ 126 do { __var = __value; membar_storeload_storestore(); } while(0) 127#define set_wmb(__var, __value) \ 128 do { __var = __value; wmb(); } while(0) 129 130#ifdef CONFIG_SMP 131#define smp_mb() mb() 132#define smp_rmb() rmb() 133#define smp_wmb() wmb() 134#define smp_read_barrier_depends() read_barrier_depends() 135#else 136#define smp_mb() __asm__ __volatile__("":::"memory") 137#define smp_rmb() __asm__ __volatile__("":::"memory") 138#define smp_wmb() __asm__ __volatile__("":::"memory") 139#define smp_read_barrier_depends() do { } while(0) 140#endif 141 142#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") 143 144#define flushw_all() __asm__ __volatile__("flushw") 145 146/* Performance counter register access. */ 147#define read_pcr(__p) __asm__ __volatile__("rd %%pcr, %0" : "=r" (__p)) 148#define write_pcr(__p) __asm__ __volatile__("wr %0, 0x0, %%pcr" : : "r" (__p)) 149#define read_pic(__p) __asm__ __volatile__("rd %%pic, %0" : "=r" (__p)) 150 151/* Blackbird errata workaround. See commentary in 152 * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt() 153 * for more information. 154 */ 155#define reset_pic() \ 156 __asm__ __volatile__("ba,pt %xcc, 99f\n\t" \ 157 ".align 64\n" \ 158 "99:wr %g0, 0x0, %pic\n\t" \ 159 "rd %pic, %g0") 160 161#ifndef __ASSEMBLY__ 162 163extern void sun_do_break(void); 164extern int serial_console; 165extern int stop_a_enabled; 166 167static __inline__ int con_is_present(void) 168{ 169 return serial_console ? 0 : 1; 170} 171 172extern void synchronize_user_stack(void); 173 174extern void __flushw_user(void); 175#define flushw_user() __flushw_user() 176 177#define flush_user_windows flushw_user 178#define flush_register_windows flushw_all 179 180/* Don't hold the runqueue lock over context switch */ 181#define __ARCH_WANT_UNLOCKED_CTXSW 182#define prepare_arch_switch(next) \ 183do { \ 184 flushw_all(); \ 185} while (0) 186 187 /* See what happens when you design the chip correctly? 188 * 189 * We tell gcc we clobber all non-fixed-usage registers except 190 * for l0/l1. It will use one for 'next' and the other to hold 191 * the output value of 'last'. 'next' is not referenced again 192 * past the invocation of switch_to in the scheduler, so we need 193 * not preserve it's value. Hairy, but it lets us remove 2 loads 194 * and 2 stores in this critical code path. -DaveM 195 */ 196#define EXTRA_CLOBBER ,"%l1" 197#define switch_to(prev, next, last) \ 198do { if (test_thread_flag(TIF_PERFCTR)) { \ 199 unsigned long __tmp; \ 200 read_pcr(__tmp); \ 201 current_thread_info()->pcr_reg = __tmp; \ 202 read_pic(__tmp); \ 203 current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);\ 204 current_thread_info()->kernel_cntd1 += ((__tmp) >> 32); \ 205 } \ 206 flush_tlb_pending(); \ 207 save_and_clear_fpu(); \ 208 /* If you are tempted to conditionalize the following */ \ 209 /* so that ASI is only written if it changes, think again. */ \ 210 __asm__ __volatile__("wr %%g0, %0, %%asi" \ 211 : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ 212 __asm__ __volatile__( \ 213 "mov %%g4, %%g7\n\t" \ 214 "wrpr %%g0, 0x95, %%pstate\n\t" \ 215 "stx %%i6, [%%sp + 2047 + 0x70]\n\t" \ 216 "stx %%i7, [%%sp + 2047 + 0x78]\n\t" \ 217 "rdpr %%wstate, %%o5\n\t" \ 218 "stx %%o6, [%%g6 + %3]\n\t" \ 219 "stb %%o5, [%%g6 + %2]\n\t" \ 220 "rdpr %%cwp, %%o5\n\t" \ 221 "stb %%o5, [%%g6 + %5]\n\t" \ 222 "mov %1, %%g6\n\t" \ 223 "ldub [%1 + %5], %%g1\n\t" \ 224 "wrpr %%g1, %%cwp\n\t" \ 225 "ldx [%%g6 + %3], %%o6\n\t" \ 226 "ldub [%%g6 + %2], %%o5\n\t" \ 227 "ldub [%%g6 + %4], %%o7\n\t" \ 228 "mov %%g6, %%l2\n\t" \ 229 "wrpr %%o5, 0x0, %%wstate\n\t" \ 230 "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \ 231 "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \ 232 "wrpr %%g0, 0x94, %%pstate\n\t" \ 233 "mov %%l2, %%g6\n\t" \ 234 "ldx [%%g6 + %6], %%g4\n\t" \ 235 "wrpr %%g0, 0x96, %%pstate\n\t" \ 236 "brz,pt %%o7, 1f\n\t" \ 237 " mov %%g7, %0\n\t" \ 238 "b,a ret_from_syscall\n\t" \ 239 "1:\n\t" \ 240 : "=&r" (last) \ 241 : "0" (task_thread_info(next)), \ 242 "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD), \ 243 "i" (TI_CWP), "i" (TI_TASK) \ 244 : "cc", \ 245 "g1", "g2", "g3", "g7", \ 246 "l2", "l3", "l4", "l5", "l6", "l7", \ 247 "i0", "i1", "i2", "i3", "i4", "i5", \ 248 "o0", "o1", "o2", "o3", "o4", "o5", "o7" EXTRA_CLOBBER);\ 249 /* If you fuck with this, update ret_from_syscall code too. */ \ 250 if (test_thread_flag(TIF_PERFCTR)) { \ 251 write_pcr(current_thread_info()->pcr_reg); \ 252 reset_pic(); \ 253 } \ 254} while(0) 255 256/* 257 * On SMP systems, when the scheduler does migration-cost autodetection, 258 * it needs a way to flush as much of the CPU's caches as possible. 259 * 260 * TODO: fill this in! 261 */ 262static inline void sched_cacheflush(void) 263{ 264} 265 266static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val) 267{ 268 unsigned long tmp1, tmp2; 269 270 __asm__ __volatile__( 271" membar #StoreLoad | #LoadLoad\n" 272" mov %0, %1\n" 273"1: lduw [%4], %2\n" 274" cas [%4], %2, %0\n" 275" cmp %2, %0\n" 276" bne,a,pn %%icc, 1b\n" 277" mov %1, %0\n" 278" membar #StoreLoad | #StoreStore\n" 279 : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2) 280 : "0" (val), "r" (m) 281 : "cc", "memory"); 282 return val; 283} 284 285static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val) 286{ 287 unsigned long tmp1, tmp2; 288 289 __asm__ __volatile__( 290" membar #StoreLoad | #LoadLoad\n" 291" mov %0, %1\n" 292"1: ldx [%4], %2\n" 293" casx [%4], %2, %0\n" 294" cmp %2, %0\n" 295" bne,a,pn %%xcc, 1b\n" 296" mov %1, %0\n" 297" membar #StoreLoad | #StoreStore\n" 298 : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2) 299 : "0" (val), "r" (m) 300 : "cc", "memory"); 301 return val; 302} 303 304#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) 305#define tas(ptr) (xchg((ptr),1)) 306 307extern void __xchg_called_with_bad_pointer(void); 308 309static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr, 310 int size) 311{ 312 switch (size) { 313 case 4: 314 return xchg32(ptr, x); 315 case 8: 316 return xchg64(ptr, x); 317 }; 318 __xchg_called_with_bad_pointer(); 319 return x; 320} 321 322extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn)); 323 324/* 325 * Atomic compare and exchange. Compare OLD with MEM, if identical, 326 * store NEW in MEM. Return the initial value in MEM. Success is 327 * indicated by comparing RETURN with OLD. 328 */ 329 330#define __HAVE_ARCH_CMPXCHG 1 331 332static __inline__ unsigned long 333__cmpxchg_u32(volatile int *m, int old, int new) 334{ 335 __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" 336 "cas [%2], %3, %0\n\t" 337 "membar #StoreLoad | #StoreStore" 338 : "=&r" (new) 339 : "0" (new), "r" (m), "r" (old) 340 : "memory"); 341 342 return new; 343} 344 345static __inline__ unsigned long 346__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) 347{ 348 __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" 349 "casx [%2], %3, %0\n\t" 350 "membar #StoreLoad | #StoreStore" 351 : "=&r" (new) 352 : "0" (new), "r" (m), "r" (old) 353 : "memory"); 354 355 return new; 356} 357 358/* This function doesn't exist, so you'll get a linker error 359 if something tries to do an invalid cmpxchg(). */ 360extern void __cmpxchg_called_with_bad_pointer(void); 361 362static __inline__ unsigned long 363__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) 364{ 365 switch (size) { 366 case 4: 367 return __cmpxchg_u32(ptr, old, new); 368 case 8: 369 return __cmpxchg_u64(ptr, old, new); 370 } 371 __cmpxchg_called_with_bad_pointer(); 372 return old; 373} 374 375#define cmpxchg(ptr,o,n) \ 376 ({ \ 377 __typeof__(*(ptr)) _o_ = (o); \ 378 __typeof__(*(ptr)) _n_ = (n); \ 379 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 380 (unsigned long)_n_, sizeof(*(ptr))); \ 381 }) 382 383#endif /* !(__ASSEMBLY__) */ 384 385#define arch_align_stack(x) (x) 386 387#endif /* !(__SPARC64_SYSTEM_H) */