| Paul Mundt | af3c7df | 2007-11-09 17:08:54 +0900 | [diff] [blame] | 1 | /* | 
|  | 2 | * include/asm-sh/processor.h | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 1999, 2000  Niibe Yutaka | 
|  | 5 | * Copyright (C) 2002, 2003  Paul Mundt | 
|  | 6 | */ | 
|  | 7 |  | 
|  | 8 | #ifndef __ASM_SH_PROCESSOR_32_H | 
|  | 9 | #define __ASM_SH_PROCESSOR_32_H | 
|  | 10 | #ifdef __KERNEL__ | 
|  | 11 |  | 
|  | 12 | #include <linux/compiler.h> | 
|  | 13 | #include <asm/page.h> | 
|  | 14 | #include <asm/types.h> | 
|  | 15 | #include <asm/cache.h> | 
|  | 16 | #include <asm/ptrace.h> | 
| Paul Mundt | af3c7df | 2007-11-09 17:08:54 +0900 | [diff] [blame] | 17 |  | 
|  | 18 | /* | 
|  | 19 | * Default implementation of macro that returns current | 
|  | 20 | * instruction pointer ("program counter"). | 
|  | 21 | */ | 
|  | 22 | #define current_text_addr() ({ void *pc; __asm__("mova	1f, %0\n1:":"=z" (pc)); pc; }) | 
|  | 23 |  | 
|  | 24 | /* Core Processor Version Register */ | 
|  | 25 | #define CCN_PVR		0xff000030 | 
|  | 26 | #define CCN_CVR		0xff000040 | 
|  | 27 | #define CCN_PRR		0xff000044 | 
|  | 28 |  | 
|  | 29 | struct sh_cpuinfo { | 
|  | 30 | unsigned int type; | 
|  | 31 | unsigned long loops_per_jiffy; | 
|  | 32 | unsigned long asid_cache; | 
|  | 33 |  | 
|  | 34 | struct cache_info icache;	/* Primary I-cache */ | 
|  | 35 | struct cache_info dcache;	/* Primary D-cache */ | 
|  | 36 | struct cache_info scache;	/* Secondary cache */ | 
|  | 37 |  | 
|  | 38 | unsigned long flags; | 
|  | 39 | } __attribute__ ((aligned(L1_CACHE_BYTES))); | 
|  | 40 |  | 
|  | 41 | extern struct sh_cpuinfo cpu_data[]; | 
|  | 42 | #define boot_cpu_data cpu_data[0] | 
|  | 43 | #define current_cpu_data cpu_data[smp_processor_id()] | 
|  | 44 | #define raw_current_cpu_data cpu_data[raw_smp_processor_id()] | 
|  | 45 |  | 
|  | 46 | /* | 
|  | 47 | * User space process size: 2GB. | 
|  | 48 | * | 
|  | 49 | * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff | 
|  | 50 | */ | 
|  | 51 | #define TASK_SIZE	0x7c000000UL | 
|  | 52 |  | 
|  | 53 | /* This decides where the kernel will search for a free chunk of vm | 
|  | 54 | * space during mmap's. | 
|  | 55 | */ | 
|  | 56 | #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3) | 
|  | 57 |  | 
|  | 58 | /* | 
|  | 59 | * Bit of SR register | 
|  | 60 | * | 
|  | 61 | * FD-bit: | 
|  | 62 | *     When it's set, it means the processor doesn't have right to use FPU, | 
|  | 63 | *     and it results exception when the floating operation is executed. | 
|  | 64 | * | 
|  | 65 | * IMASK-bit: | 
|  | 66 | *     Interrupt level mask | 
|  | 67 | */ | 
| Paul Mundt | af3c7df | 2007-11-09 17:08:54 +0900 | [diff] [blame] | 68 | #define SR_DSP		0x00001000 | 
|  | 69 | #define SR_IMASK	0x000000f0 | 
|  | 70 |  | 
|  | 71 | /* | 
|  | 72 | * FPU structure and data | 
|  | 73 | */ | 
|  | 74 |  | 
|  | 75 | struct sh_fpu_hard_struct { | 
|  | 76 | unsigned long fp_regs[16]; | 
|  | 77 | unsigned long xfp_regs[16]; | 
|  | 78 | unsigned long fpscr; | 
|  | 79 | unsigned long fpul; | 
|  | 80 |  | 
|  | 81 | long status; /* software status information */ | 
|  | 82 | }; | 
|  | 83 |  | 
|  | 84 | /* Dummy fpu emulator  */ | 
|  | 85 | struct sh_fpu_soft_struct { | 
|  | 86 | unsigned long fp_regs[16]; | 
|  | 87 | unsigned long xfp_regs[16]; | 
|  | 88 | unsigned long fpscr; | 
|  | 89 | unsigned long fpul; | 
|  | 90 |  | 
|  | 91 | unsigned char lookahead; | 
|  | 92 | unsigned long entry_pc; | 
|  | 93 | }; | 
|  | 94 |  | 
|  | 95 | union sh_fpu_union { | 
|  | 96 | struct sh_fpu_hard_struct hard; | 
|  | 97 | struct sh_fpu_soft_struct soft; | 
|  | 98 | }; | 
|  | 99 |  | 
|  | 100 | struct thread_struct { | 
|  | 101 | /* Saved registers when thread is descheduled */ | 
|  | 102 | unsigned long sp; | 
|  | 103 | unsigned long pc; | 
|  | 104 |  | 
|  | 105 | /* Hardware debugging registers */ | 
|  | 106 | unsigned long ubc_pc; | 
|  | 107 |  | 
|  | 108 | /* floating point info */ | 
|  | 109 | union sh_fpu_union fpu; | 
|  | 110 | }; | 
|  | 111 |  | 
|  | 112 | typedef struct { | 
|  | 113 | unsigned long seg; | 
|  | 114 | } mm_segment_t; | 
|  | 115 |  | 
|  | 116 | /* Count of active tasks with UBC settings */ | 
|  | 117 | extern int ubc_usercnt; | 
|  | 118 |  | 
|  | 119 | #define INIT_THREAD  {						\ | 
|  | 120 | .sp = sizeof(init_stack) + (long) &init_stack,		\ | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | /* | 
|  | 124 | * Do necessary setup to start up a newly executed thread. | 
|  | 125 | */ | 
|  | 126 | #define start_thread(regs, new_pc, new_sp)	 \ | 
|  | 127 | set_fs(USER_DS);			 \ | 
|  | 128 | regs->pr = 0;				 \ | 
|  | 129 | regs->sr = SR_FD;	/* User mode. */ \ | 
|  | 130 | regs->pc = new_pc;			 \ | 
|  | 131 | regs->regs[15] = new_sp | 
|  | 132 |  | 
|  | 133 | /* Forward declaration, a strange C thing */ | 
|  | 134 | struct task_struct; | 
|  | 135 | struct mm_struct; | 
|  | 136 |  | 
|  | 137 | /* Free all resources held by a thread. */ | 
|  | 138 | extern void release_thread(struct task_struct *); | 
|  | 139 |  | 
|  | 140 | /* Prepare to copy thread state - unlazy all lazy status */ | 
|  | 141 | #define prepare_to_copy(tsk)	do { } while (0) | 
|  | 142 |  | 
|  | 143 | /* | 
|  | 144 | * create a kernel thread without removing it from tasklists | 
|  | 145 | */ | 
|  | 146 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 
|  | 147 |  | 
|  | 148 | /* Copy and release all segment info associated with a VM */ | 
|  | 149 | #define copy_segments(p, mm)	do { } while(0) | 
|  | 150 | #define release_segments(mm)	do { } while(0) | 
|  | 151 |  | 
|  | 152 | /* | 
|  | 153 | * FPU lazy state save handling. | 
|  | 154 | */ | 
|  | 155 |  | 
|  | 156 | static __inline__ void disable_fpu(void) | 
|  | 157 | { | 
|  | 158 | unsigned long __dummy; | 
|  | 159 |  | 
|  | 160 | /* Set FD flag in SR */ | 
|  | 161 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 162 | "or	%1, %0\n\t" | 
|  | 163 | "ldc	%0, sr" | 
|  | 164 | : "=&r" (__dummy) | 
|  | 165 | : "r" (SR_FD)); | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | static __inline__ void enable_fpu(void) | 
|  | 169 | { | 
|  | 170 | unsigned long __dummy; | 
|  | 171 |  | 
|  | 172 | /* Clear out FD flag in SR */ | 
|  | 173 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 174 | "and	%1, %0\n\t" | 
|  | 175 | "ldc	%0, sr" | 
|  | 176 | : "=&r" (__dummy) | 
|  | 177 | : "r" (~SR_FD)); | 
|  | 178 | } | 
|  | 179 |  | 
| Paul Mundt | af3c7df | 2007-11-09 17:08:54 +0900 | [diff] [blame] | 180 | /* Double presision, NANS as NANS, rounding to nearest, no exceptions */ | 
|  | 181 | #define FPSCR_INIT  0x00080000 | 
|  | 182 |  | 
|  | 183 | #define	FPSCR_CAUSE_MASK	0x0001f000	/* Cause bits */ | 
|  | 184 | #define	FPSCR_FLAG_MASK		0x0000007c	/* Flag bits */ | 
|  | 185 |  | 
|  | 186 | /* | 
|  | 187 | * Return saved PC of a blocked thread. | 
|  | 188 | */ | 
|  | 189 | #define thread_saved_pc(tsk)	(tsk->thread.pc) | 
|  | 190 |  | 
|  | 191 | void show_trace(struct task_struct *tsk, unsigned long *sp, | 
|  | 192 | struct pt_regs *regs); | 
|  | 193 | extern unsigned long get_wchan(struct task_struct *p); | 
|  | 194 |  | 
|  | 195 | #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc) | 
|  | 196 | #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15]) | 
|  | 197 |  | 
|  | 198 | #define cpu_sleep()	__asm__ __volatile__ ("sleep" : : : "memory") | 
|  | 199 | #define cpu_relax()	barrier() | 
|  | 200 |  | 
|  | 201 | #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ | 
|  | 202 | defined(CONFIG_CPU_SH4) | 
|  | 203 | #define PREFETCH_STRIDE		L1_CACHE_BYTES | 
|  | 204 | #define ARCH_HAS_PREFETCH | 
|  | 205 | #define ARCH_HAS_PREFETCHW | 
|  | 206 | static inline void prefetch(void *x) | 
|  | 207 | { | 
|  | 208 | __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory"); | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | #define prefetchw(x)	prefetch(x) | 
|  | 212 | #endif | 
|  | 213 |  | 
| Paul Mundt | af3c7df | 2007-11-09 17:08:54 +0900 | [diff] [blame] | 214 | #endif /* __KERNEL__ */ | 
|  | 215 | #endif /* __ASM_SH_PROCESSOR_32_H */ |