Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
trap_block.h
Go to the documentation of this file.
1 #ifndef _SPARC_TRAP_BLOCK_H
2 #define _SPARC_TRAP_BLOCK_H
3 
4 #include <asm/hypervisor.h>
5 #include <asm/asi.h>
6 
7 #ifndef __ASSEMBLY__
8 
9 /* Trap handling code needs to get at a few critical values upon
10  * trap entry and to process TSB misses. These cannot be in the
11  * per_cpu() area as we really need to lock them into the TLB and
12  * thus make them part of the main kernel image. As a result we
13  * try to make this as small as possible.
14  *
15  * This is padded out and aligned to 64-bytes to avoid false sharing
16  * on SMP.
17  */
18 
19 /* If you modify the size of this structure, please update
20  * TRAP_BLOCK_SZ_SHIFT below.
21  */
22 struct thread_info;
23 struct trap_per_cpu {
24 /* D-cache line 1: Basic thread information, cpu and device mondo queues */
26  unsigned long pgd_paddr;
27  unsigned long cpu_mondo_pa;
28  unsigned long dev_mondo_pa;
29 
30 /* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
31  unsigned long resum_mondo_pa;
32  unsigned long resum_kernel_buf_pa;
33  unsigned long nonresum_mondo_pa;
34  unsigned long nonresum_kernel_buf_pa;
35 
36 /* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
38 
39 /* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */
40  unsigned long cpu_mondo_block_pa;
41  unsigned long cpu_list_pa;
42  unsigned long tsb_huge;
43  unsigned long tsb_huge_temp;
44 
45 /* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */
46  unsigned long irq_worklist_pa;
47  unsigned int cpu_mondo_qmask;
48  unsigned int dev_mondo_qmask;
49  unsigned int resum_qmask;
50  unsigned int nonresum_qmask;
51  unsigned long __per_cpu_base;
52 } __attribute__((aligned(64)));
53 extern struct trap_per_cpu trap_block[NR_CPUS];
54 extern void init_cur_cpu_trap(struct thread_info *);
55 extern void setup_tba(void);
56 extern int ncpus_probed;
57 
58 extern unsigned long real_hard_smp_processor_id(void);
59 
61  unsigned int addr;
62  unsigned int cheetah_safari[4];
63  unsigned int cheetah_jbus[4];
64  unsigned int starfire[4];
65  unsigned int sun4v[4];
66 };
67 extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
68 
70  unsigned int addr;
71  unsigned int insn;
72 };
73 extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
75 
77  unsigned int addr;
78  unsigned int insns[2];
79 };
80 extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
82 
83 
84 #endif /* !(__ASSEMBLY__) */
85 
86 #define TRAP_PER_CPU_THREAD 0x00
87 #define TRAP_PER_CPU_PGD_PADDR 0x08
88 #define TRAP_PER_CPU_CPU_MONDO_PA 0x10
89 #define TRAP_PER_CPU_DEV_MONDO_PA 0x18
90 #define TRAP_PER_CPU_RESUM_MONDO_PA 0x20
91 #define TRAP_PER_CPU_RESUM_KBUF_PA 0x28
92 #define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30
93 #define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38
94 #define TRAP_PER_CPU_FAULT_INFO 0x40
95 #define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0
96 #define TRAP_PER_CPU_CPU_LIST_PA 0xc8
97 #define TRAP_PER_CPU_TSB_HUGE 0xd0
98 #define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8
99 #define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0
100 #define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8
101 #define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec
102 #define TRAP_PER_CPU_RESUM_QMASK 0xf0
103 #define TRAP_PER_CPU_NONRESUM_QMASK 0xf4
104 #define TRAP_PER_CPU_PER_CPU_BASE 0xf8
105 
106 #define TRAP_BLOCK_SZ_SHIFT 8
107 
108 #include <asm/scratchpad.h>
109 
110 #define __GET_CPUID(REG) \
111  /* Spitfire implementation (default). */ \
112 661: ldxa [%g0] ASI_UPA_CONFIG, REG; \
113  srlx REG, 17, REG; \
114  and REG, 0x1f, REG; \
115  nop; \
116  .section .cpuid_patch, "ax"; \
117  /* Instruction location. */ \
118  .word 661b; \
119  /* Cheetah Safari implementation. */ \
120  ldxa [%g0] ASI_SAFARI_CONFIG, REG; \
121  srlx REG, 17, REG; \
122  and REG, 0x3ff, REG; \
123  nop; \
124  /* Cheetah JBUS implementation. */ \
125  ldxa [%g0] ASI_JBUS_CONFIG, REG; \
126  srlx REG, 17, REG; \
127  and REG, 0x1f, REG; \
128  nop; \
129  /* Starfire implementation. */ \
130  sethi %hi(0x1fff40000d0 >> 9), REG; \
131  sllx REG, 9, REG; \
132  or REG, 0xd0, REG; \
133  lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\
134  /* sun4v implementation. */ \
135  mov SCRATCHPAD_CPUID, REG; \
136  ldxa [REG] ASI_SCRATCHPAD, REG; \
137  nop; \
138  nop; \
139  .previous;
140 
141 #ifdef CONFIG_SMP
142 
143 #define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
144  __GET_CPUID(TMP) \
145  sethi %hi(trap_block), DEST; \
146  sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \
147  or DEST, %lo(trap_block), DEST; \
148  add DEST, TMP, DEST; \
149 
150 /* Clobbers TMP, current address space PGD phys address into DEST. */
151 #define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
152  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
153  ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
154 
155 /* Clobbers TMP, loads local processor's IRQ work area into DEST. */
156 #define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
157  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
158  add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
159 
160 /* Clobbers TMP, loads DEST with current thread info pointer. */
161 #define TRAP_LOAD_THREAD_REG(DEST, TMP) \
162  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
163  ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
164 
165 /* Given the current thread info pointer in THR, load the per-cpu
166  * area base of the current processor into DEST. REG1, REG2, and REG3 are
167  * clobbered.
168  *
169  * You absolutely cannot use DEST as a temporary in this code. The
170  * reason is that traps can happen during execution, and return from
171  * trap will load the fully resolved DEST per-cpu base. This can corrupt
172  * the calculations done by the macro mid-stream.
173  */
174 #define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
175  lduh [THR + TI_CPU], REG1; \
176  sethi %hi(trap_block), REG2; \
177  sllx REG1, TRAP_BLOCK_SZ_SHIFT, REG1; \
178  or REG2, %lo(trap_block), REG2; \
179  add REG2, REG1, REG2; \
180  ldx [REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST;
181 
182 #else
183 
184 #define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
185  sethi %hi(trap_block), DEST; \
186  or DEST, %lo(trap_block), DEST; \
187 
188 /* Uniprocessor versions, we know the cpuid is zero. */
189 #define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
190  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
191  ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
192 
193 /* Clobbers TMP, loads local processor's IRQ work area into DEST. */
194 #define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
195  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
196  add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
197 
198 #define TRAP_LOAD_THREAD_REG(DEST, TMP) \
199  TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
200  ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
201 
202 /* No per-cpu areas on uniprocessor, so no need to load DEST. */
203 #define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
204 
205 #endif /* !(CONFIG_SMP) */
206 
207 #endif /* _SPARC_TRAP_BLOCK_H */