diff options
author | Jack Steiner <steiner@sgi.com> | 2008-07-30 01:33:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 12:41:47 -0400 |
commit | 4c921d4d8aa74140597fd8736261837f73ca6e7a (patch) | |
tree | 54a0d98c8257f633af599177bd66f33d58c19ca7 /drivers/misc/sgi-gru | |
parent | 34d8a380d784d1fbea941a68beebdd7f9a3bebdf (diff) |
GRU Driver: GRU instructions & macros
This patchs contains macros & inline functions used to issue instructions
to the GRU.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-gru')
-rw-r--r-- | drivers/misc/sgi-gru/gru_instructions.h | 679 |
1 files changed, 679 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h new file mode 100644 index 000000000000..3159b261c5a7 --- /dev/null +++ b/drivers/misc/sgi-gru/gru_instructions.h | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Lesser General Public License as published by | ||
6 | * the Free Software Foundation; either version 2.1 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Lesser General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Lesser General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #ifndef __GRU_INSTRUCTIONS_H__ | ||
20 | #define __GRU_INSTRUCTIONS_H__ | ||
21 | |||
22 | #define gru_flush_cache_hook(p) | ||
23 | #define gru_emulator_wait_hook(p, w) | ||
24 | |||
25 | /* | ||
26 | * Architecture dependent functions | ||
27 | */ | ||
28 | |||
29 | #if defined CONFIG_IA64 | ||
30 | #include <linux/compiler.h> | ||
31 | #include <asm/intrinsics.h> | ||
32 | #define __flush_cache(p) ia64_fc(p) | ||
33 | /* Use volatile on IA64 to ensure ordering via st4.rel */ | ||
34 | #define gru_ordered_store_int(p,v) \ | ||
35 | do { \ | ||
36 | barrier(); \ | ||
37 | *((volatile int *)(p)) = v; /* force st.rel */ \ | ||
38 | } while (0) | ||
39 | #elif defined CONFIG_X86_64 | ||
40 | #define __flush_cache(p) clflush(p) | ||
41 | #define gru_ordered_store_int(p,v) \ | ||
42 | do { \ | ||
43 | barrier(); \ | ||
44 | *(int *)p = v; \ | ||
45 | } while (0) | ||
46 | #else | ||
47 | #error "Unsupported architecture" | ||
48 | #endif | ||
49 | |||
50 | /* | ||
51 | * Control block status and exception codes | ||
52 | */ | ||
53 | #define CBS_IDLE 0 | ||
54 | #define CBS_EXCEPTION 1 | ||
55 | #define CBS_ACTIVE 2 | ||
56 | #define CBS_CALL_OS 3 | ||
57 | |||
58 | /* CB substatus bitmasks */ | ||
59 | #define CBSS_MSG_QUEUE_MASK 7 | ||
60 | #define CBSS_IMPLICIT_ABORT_ACTIVE_MASK 8 | ||
61 | |||
62 | /* CB substatus message queue values (low 3 bits of substatus) */ | ||
63 | #define CBSS_NO_ERROR 0 | ||
64 | #define CBSS_LB_OVERFLOWED 1 | ||
65 | #define CBSS_QLIMIT_REACHED 2 | ||
66 | #define CBSS_PAGE_OVERFLOW 3 | ||
67 | #define CBSS_AMO_NACKED 4 | ||
68 | #define CBSS_PUT_NACKED 5 | ||
69 | |||
70 | /* | ||
71 | * Structure used to fetch exception detail for CBs that terminate with | ||
72 | * CBS_EXCEPTION | ||
73 | */ | ||
74 | struct control_block_extended_exc_detail { | ||
75 | unsigned long cb; | ||
76 | int opc; | ||
77 | int ecause; | ||
78 | int exopc; | ||
79 | long exceptdet0; | ||
80 | int exceptdet1; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * Instruction formats | ||
85 | */ | ||
86 | |||
87 | /* | ||
88 | * Generic instruction format. | ||
89 | * This definition has precise bit field definitions. | ||
90 | */ | ||
91 | struct gru_instruction_bits { | ||
92 | /* DW 0 - low */ | ||
93 | unsigned int icmd: 1; | ||
94 | unsigned char ima: 3; /* CB_DelRep, unmapped mode */ | ||
95 | unsigned char reserved0: 4; | ||
96 | unsigned int xtype: 3; | ||
97 | unsigned int iaa0: 2; | ||
98 | unsigned int iaa1: 2; | ||
99 | unsigned char reserved1: 1; | ||
100 | unsigned char opc: 8; /* opcode */ | ||
101 | unsigned char exopc: 8; /* extended opcode */ | ||
102 | /* DW 0 - high */ | ||
103 | unsigned int idef2: 22; /* TRi0 */ | ||
104 | unsigned char reserved2: 2; | ||
105 | unsigned char istatus: 2; | ||
106 | unsigned char isubstatus:4; | ||
107 | unsigned char reserved3: 2; | ||
108 | /* DW 1 */ | ||
109 | unsigned long idef4; /* 42 bits: TRi1, BufSize */ | ||
110 | /* DW 2-6 */ | ||
111 | unsigned long idef1; /* BAddr0 */ | ||
112 | unsigned long idef5; /* Nelem */ | ||
113 | unsigned long idef6; /* Stride, Operand1 */ | ||
114 | unsigned long idef3; /* BAddr1, Value, Operand2 */ | ||
115 | unsigned long reserved4; | ||
116 | /* DW 7 */ | ||
117 | unsigned long avalue; /* AValue */ | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * Generic instruction with friendlier names. This format is used | ||
122 | * for inline instructions. | ||
123 | */ | ||
124 | struct gru_instruction { | ||
125 | /* DW 0 */ | ||
126 | unsigned int op32; /* icmd,xtype,iaa0,ima,opc */ | ||
127 | unsigned int tri0; | ||
128 | unsigned long tri1_bufsize; /* DW 1 */ | ||
129 | unsigned long baddr0; /* DW 2 */ | ||
130 | unsigned long nelem; /* DW 3 */ | ||
131 | unsigned long op1_stride; /* DW 4 */ | ||
132 | unsigned long op2_value_baddr1; /* DW 5 */ | ||
133 | unsigned long reserved0; /* DW 6 */ | ||
134 | unsigned long avalue; /* DW 7 */ | ||
135 | }; | ||
136 | |||
137 | /* Some shifts and masks for the low 32 bits of a GRU command */ | ||
138 | #define GRU_CB_ICMD_SHFT 0 | ||
139 | #define GRU_CB_ICMD_MASK 0x1 | ||
140 | #define GRU_CB_XTYPE_SHFT 8 | ||
141 | #define GRU_CB_XTYPE_MASK 0x7 | ||
142 | #define GRU_CB_IAA0_SHFT 11 | ||
143 | #define GRU_CB_IAA0_MASK 0x3 | ||
144 | #define GRU_CB_IAA1_SHFT 13 | ||
145 | #define GRU_CB_IAA1_MASK 0x3 | ||
146 | #define GRU_CB_IMA_SHFT 1 | ||
147 | #define GRU_CB_IMA_MASK 0x3 | ||
148 | #define GRU_CB_OPC_SHFT 16 | ||
149 | #define GRU_CB_OPC_MASK 0xff | ||
150 | #define GRU_CB_EXOPC_SHFT 24 | ||
151 | #define GRU_CB_EXOPC_MASK 0xff | ||
152 | |||
153 | /* GRU instruction opcodes (opc field) */ | ||
154 | #define OP_NOP 0x00 | ||
155 | #define OP_BCOPY 0x01 | ||
156 | #define OP_VLOAD 0x02 | ||
157 | #define OP_IVLOAD 0x03 | ||
158 | #define OP_VSTORE 0x04 | ||
159 | #define OP_IVSTORE 0x05 | ||
160 | #define OP_VSET 0x06 | ||
161 | #define OP_IVSET 0x07 | ||
162 | #define OP_MESQ 0x08 | ||
163 | #define OP_GAMXR 0x09 | ||
164 | #define OP_GAMIR 0x0a | ||
165 | #define OP_GAMIRR 0x0b | ||
166 | #define OP_GAMER 0x0c | ||
167 | #define OP_GAMERR 0x0d | ||
168 | #define OP_BSTORE 0x0e | ||
169 | #define OP_VFLUSH 0x0f | ||
170 | |||
171 | |||
172 | /* Extended opcodes values (exopc field) */ | ||
173 | |||
174 | /* GAMIR - AMOs with implicit operands */ | ||
175 | #define EOP_IR_FETCH 0x01 /* Plain fetch of memory */ | ||
176 | #define EOP_IR_CLR 0x02 /* Fetch and clear */ | ||
177 | #define EOP_IR_INC 0x05 /* Fetch and increment */ | ||
178 | #define EOP_IR_DEC 0x07 /* Fetch and decrement */ | ||
179 | #define EOP_IR_QCHK1 0x0d /* Queue check, 64 byte msg */ | ||
180 | #define EOP_IR_QCHK2 0x0e /* Queue check, 128 byte msg */ | ||
181 | |||
182 | /* GAMIRR - Registered AMOs with implicit operands */ | ||
183 | #define EOP_IRR_FETCH 0x01 /* Registered fetch of memory */ | ||
184 | #define EOP_IRR_CLR 0x02 /* Registered fetch and clear */ | ||
185 | #define EOP_IRR_INC 0x05 /* Registered fetch and increment */ | ||
186 | #define EOP_IRR_DEC 0x07 /* Registered fetch and decrement */ | ||
187 | #define EOP_IRR_DECZ 0x0f /* Registered fetch and decrement, update on zero*/ | ||
188 | |||
189 | /* GAMER - AMOs with explicit operands */ | ||
190 | #define EOP_ER_SWAP 0x00 /* Exchange argument and memory */ | ||
191 | #define EOP_ER_OR 0x01 /* Logical OR with memory */ | ||
192 | #define EOP_ER_AND 0x02 /* Logical AND with memory */ | ||
193 | #define EOP_ER_XOR 0x03 /* Logical XOR with memory */ | ||
194 | #define EOP_ER_ADD 0x04 /* Add value to memory */ | ||
195 | #define EOP_ER_CSWAP 0x08 /* Compare with operand2, write operand1 if match*/ | ||
196 | #define EOP_ER_CADD 0x0c /* Queue check, operand1*64 byte msg */ | ||
197 | |||
198 | /* GAMERR - Registered AMOs with explicit operands */ | ||
199 | #define EOP_ERR_SWAP 0x00 /* Exchange argument and memory */ | ||
200 | #define EOP_ERR_OR 0x01 /* Logical OR with memory */ | ||
201 | #define EOP_ERR_AND 0x02 /* Logical AND with memory */ | ||
202 | #define EOP_ERR_XOR 0x03 /* Logical XOR with memory */ | ||
203 | #define EOP_ERR_ADD 0x04 /* Add value to memory */ | ||
204 | #define EOP_ERR_CSWAP 0x08 /* Compare with operand2, write operand1 if match*/ | ||
205 | #define EOP_ERR_EPOLL 0x09 /* Poll for equality */ | ||
206 | #define EOP_ERR_NPOLL 0x0a /* Poll for inequality */ | ||
207 | |||
208 | /* GAMXR - SGI Arithmetic unit */ | ||
209 | #define EOP_XR_CSWAP 0x0b /* Masked compare exchange */ | ||
210 | |||
211 | |||
212 | /* Transfer types (xtype field) */ | ||
213 | #define XTYPE_B 0x0 /* byte */ | ||
214 | #define XTYPE_S 0x1 /* short (2-byte) */ | ||
215 | #define XTYPE_W 0x2 /* word (4-byte) */ | ||
216 | #define XTYPE_DW 0x3 /* doubleword (8-byte) */ | ||
217 | #define XTYPE_CL 0x6 /* cacheline (64-byte) */ | ||
218 | |||
219 | |||
220 | /* Instruction access attributes (iaa0, iaa1 fields) */ | ||
221 | #define IAA_RAM 0x0 /* normal cached RAM access */ | ||
222 | #define IAA_NCRAM 0x2 /* noncoherent RAM access */ | ||
223 | #define IAA_MMIO 0x1 /* noncoherent memory-mapped I/O space */ | ||
224 | #define IAA_REGISTER 0x3 /* memory-mapped registers, etc. */ | ||
225 | |||
226 | |||
227 | /* Instruction mode attributes (ima field) */ | ||
228 | #define IMA_MAPPED 0x0 /* Virtual mode */ | ||
229 | #define IMA_CB_DELAY 0x1 /* hold read responses until status changes */ | ||
230 | #define IMA_UNMAPPED 0x2 /* bypass the TLBs (OS only) */ | ||
231 | #define IMA_INTERRUPT 0x4 /* Interrupt when instruction completes */ | ||
232 | |||
233 | /* CBE ecause bits */ | ||
234 | #define CBE_CAUSE_RI (1 << 0) | ||
235 | #define CBE_CAUSE_INVALID_INSTRUCTION (1 << 1) | ||
236 | #define CBE_CAUSE_UNMAPPED_MODE_FORBIDDEN (1 << 2) | ||
237 | #define CBE_CAUSE_PE_CHECK_DATA_ERROR (1 << 3) | ||
238 | #define CBE_CAUSE_IAA_GAA_MISMATCH (1 << 4) | ||
239 | #define CBE_CAUSE_DATA_SEGMENT_LIMIT_EXCEPTION (1 << 5) | ||
240 | #define CBE_CAUSE_OS_FATAL_TLB_FAULT (1 << 6) | ||
241 | #define CBE_CAUSE_EXECUTION_HW_ERROR (1 << 7) | ||
242 | #define CBE_CAUSE_TLBHW_ERROR (1 << 8) | ||
243 | #define CBE_CAUSE_RA_REQUEST_TIMEOUT (1 << 9) | ||
244 | #define CBE_CAUSE_HA_REQUEST_TIMEOUT (1 << 10) | ||
245 | #define CBE_CAUSE_RA_RESPONSE_FATAL (1 << 11) | ||
246 | #define CBE_CAUSE_RA_RESPONSE_NON_FATAL (1 << 12) | ||
247 | #define CBE_CAUSE_HA_RESPONSE_FATAL (1 << 13) | ||
248 | #define CBE_CAUSE_HA_RESPONSE_NON_FATAL (1 << 14) | ||
249 | #define CBE_CAUSE_ADDRESS_SPACE_DECODE_ERROR (1 << 15) | ||
250 | #define CBE_CAUSE_RESPONSE_DATA_ERROR (1 << 16) | ||
251 | #define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR (1 << 17) | ||
252 | |||
253 | /* | ||
254 | * Exceptions are retried for the following cases. If any OTHER bits are set | ||
255 | * in ecause, the exception is not retryable. | ||
256 | */ | ||
257 | #define EXCEPTION_RETRY_BITS (CBE_CAUSE_RESPONSE_DATA_ERROR | \ | ||
258 | CBE_CAUSE_RA_REQUEST_TIMEOUT | \ | ||
259 | CBE_CAUSE_TLBHW_ERROR | \ | ||
260 | CBE_CAUSE_HA_REQUEST_TIMEOUT) | ||
261 | |||
262 | /* Message queue head structure */ | ||
263 | union gru_mesqhead { | ||
264 | unsigned long val; | ||
265 | struct { | ||
266 | unsigned int head; | ||
267 | unsigned int limit; | ||
268 | }; | ||
269 | }; | ||
270 | |||
271 | |||
272 | /* Generate the low word of a GRU instruction */ | ||
273 | static inline unsigned int | ||
274 | __opword(unsigned char opcode, unsigned char exopc, unsigned char xtype, | ||
275 | unsigned char iaa0, unsigned char iaa1, | ||
276 | unsigned char ima) | ||
277 | { | ||
278 | return (1 << GRU_CB_ICMD_SHFT) | | ||
279 | (iaa0 << GRU_CB_IAA0_SHFT) | | ||
280 | (iaa1 << GRU_CB_IAA1_SHFT) | | ||
281 | (ima << GRU_CB_IMA_SHFT) | | ||
282 | (xtype << GRU_CB_XTYPE_SHFT) | | ||
283 | (opcode << GRU_CB_OPC_SHFT) | | ||
284 | (exopc << GRU_CB_EXOPC_SHFT); | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * Prefetch a cacheline. Fetch is unconditional. Must page fault if | ||
289 | * no valid TLB entry is found. | ||
290 | * ??? should I use actual "load" or hardware prefetch??? | ||
291 | */ | ||
292 | static inline void gru_prefetch(void *p) | ||
293 | { | ||
294 | *(volatile char *)p; | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Architecture specific intrinsics | ||
299 | */ | ||
300 | static inline void gru_flush_cache(void *p) | ||
301 | { | ||
302 | __flush_cache(p); | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * Store the lower 32 bits of the command including the "start" bit. Then | ||
307 | * start the instruction executing. | ||
308 | */ | ||
309 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) | ||
310 | { | ||
311 | gru_ordered_store_int(ins, op32); | ||
312 | } | ||
313 | |||
314 | |||
315 | /* Convert "hints" to IMA */ | ||
316 | #define CB_IMA(h) ((h) | IMA_UNMAPPED) | ||
317 | |||
318 | /* Convert data segment cache line index into TRI0 / TRI1 value */ | ||
319 | #define GRU_DINDEX(i) ((i) * GRU_CACHE_LINE_BYTES) | ||
320 | |||
321 | /* Inline functions for GRU instructions. | ||
322 | * Note: | ||
323 | * - nelem and stride are in elements | ||
324 | * - tri0/tri1 is in bytes for the beginning of the data segment. | ||
325 | */ | ||
326 | static inline void gru_vload(void *cb, unsigned long mem_addr, | ||
327 | unsigned int tri0, unsigned char xtype, unsigned long nelem, | ||
328 | unsigned long stride, unsigned long hints) | ||
329 | { | ||
330 | struct gru_instruction *ins = (struct gru_instruction *)cb; | ||
331 | |||
332 | ins->baddr0 = (long)mem_addr; | ||
333 | ins->nelem = nelem; | ||
334 | ins->tri0 = tri0; | ||
335 | ins->op1_stride = stride; | ||
336 | gru_start_instruction(ins, __opword(OP_VLOAD, 0, xtype, IAA_RAM, 0, | ||
337 | CB_IMA(hints))); | ||
338 | } | ||
339 | |||
340 | static inline void gru_vstore(void *cb, unsigned long mem_addr, | ||
341 | unsigned int tri0, unsigned char xtype, unsigned long nelem, | ||
342 | unsigned long stride, unsigned long hints) | ||
343 | { | ||
344 | struct gru_instruction *ins = (void *)cb; | ||
345 | |||
346 | ins->baddr0 = (long)mem_addr; | ||
347 | ins->nelem = nelem; | ||
348 | ins->tri0 = tri0; | ||
349 | ins->op1_stride = stride; | ||
350 | gru_start_instruction(ins, __opword(OP_VSTORE, 0, xtype, IAA_RAM, 0, | ||
351 | CB_IMA(hints))); | ||
352 | } | ||
353 | |||
354 | static inline void gru_ivload(void *cb, unsigned long mem_addr, | ||
355 | unsigned int tri0, unsigned int tri1, unsigned char xtype, | ||
356 | unsigned long nelem, unsigned long hints) | ||
357 | { | ||
358 | struct gru_instruction *ins = (void *)cb; | ||
359 | |||
360 | ins->baddr0 = (long)mem_addr; | ||
361 | ins->nelem = nelem; | ||
362 | ins->tri0 = tri0; | ||
363 | ins->tri1_bufsize = tri1; | ||
364 | gru_start_instruction(ins, __opword(OP_IVLOAD, 0, xtype, IAA_RAM, 0, | ||
365 | CB_IMA(hints))); | ||
366 | } | ||
367 | |||
368 | static inline void gru_ivstore(void *cb, unsigned long mem_addr, | ||
369 | unsigned int tri0, unsigned int tri1, | ||
370 | unsigned char xtype, unsigned long nelem, unsigned long hints) | ||
371 | { | ||
372 | struct gru_instruction *ins = (void *)cb; | ||
373 | |||
374 | ins->baddr0 = (long)mem_addr; | ||
375 | ins->nelem = nelem; | ||
376 | ins->tri0 = tri0; | ||
377 | ins->tri1_bufsize = tri1; | ||
378 | gru_start_instruction(ins, __opword(OP_IVSTORE, 0, xtype, IAA_RAM, 0, | ||
379 | CB_IMA(hints))); | ||
380 | } | ||
381 | |||
382 | static inline void gru_vset(void *cb, unsigned long mem_addr, | ||
383 | unsigned long value, unsigned char xtype, unsigned long nelem, | ||
384 | unsigned long stride, unsigned long hints) | ||
385 | { | ||
386 | struct gru_instruction *ins = (void *)cb; | ||
387 | |||
388 | ins->baddr0 = (long)mem_addr; | ||
389 | ins->op2_value_baddr1 = value; | ||
390 | ins->nelem = nelem; | ||
391 | ins->op1_stride = stride; | ||
392 | gru_start_instruction(ins, __opword(OP_VSET, 0, xtype, IAA_RAM, 0, | ||
393 | CB_IMA(hints))); | ||
394 | } | ||
395 | |||
396 | static inline void gru_ivset(void *cb, unsigned long mem_addr, | ||
397 | unsigned int tri1, unsigned long value, unsigned char xtype, | ||
398 | unsigned long nelem, unsigned long hints) | ||
399 | { | ||
400 | struct gru_instruction *ins = (void *)cb; | ||
401 | |||
402 | ins->baddr0 = (long)mem_addr; | ||
403 | ins->op2_value_baddr1 = value; | ||
404 | ins->nelem = nelem; | ||
405 | ins->tri1_bufsize = tri1; | ||
406 | gru_start_instruction(ins, __opword(OP_IVSET, 0, xtype, IAA_RAM, 0, | ||
407 | CB_IMA(hints))); | ||
408 | } | ||
409 | |||
410 | static inline void gru_vflush(void *cb, unsigned long mem_addr, | ||
411 | unsigned long nelem, unsigned char xtype, unsigned long stride, | ||
412 | unsigned long hints) | ||
413 | { | ||
414 | struct gru_instruction *ins = (void *)cb; | ||
415 | |||
416 | ins->baddr0 = (long)mem_addr; | ||
417 | ins->op1_stride = stride; | ||
418 | ins->nelem = nelem; | ||
419 | gru_start_instruction(ins, __opword(OP_VFLUSH, 0, xtype, IAA_RAM, 0, | ||
420 | CB_IMA(hints))); | ||
421 | } | ||
422 | |||
423 | static inline void gru_nop(void *cb, int hints) | ||
424 | { | ||
425 | struct gru_instruction *ins = (void *)cb; | ||
426 | |||
427 | gru_start_instruction(ins, __opword(OP_NOP, 0, 0, 0, 0, CB_IMA(hints))); | ||
428 | } | ||
429 | |||
430 | |||
431 | static inline void gru_bcopy(void *cb, const unsigned long src, | ||
432 | unsigned long dest, | ||
433 | unsigned int tri0, unsigned int xtype, unsigned long nelem, | ||
434 | unsigned int bufsize, unsigned long hints) | ||
435 | { | ||
436 | struct gru_instruction *ins = (void *)cb; | ||
437 | |||
438 | ins->baddr0 = (long)src; | ||
439 | ins->op2_value_baddr1 = (long)dest; | ||
440 | ins->nelem = nelem; | ||
441 | ins->tri0 = tri0; | ||
442 | ins->tri1_bufsize = bufsize; | ||
443 | gru_start_instruction(ins, __opword(OP_BCOPY, 0, xtype, IAA_RAM, | ||
444 | IAA_RAM, CB_IMA(hints))); | ||
445 | } | ||
446 | |||
447 | static inline void gru_bstore(void *cb, const unsigned long src, | ||
448 | unsigned long dest, unsigned int tri0, unsigned int xtype, | ||
449 | unsigned long nelem, unsigned long hints) | ||
450 | { | ||
451 | struct gru_instruction *ins = (void *)cb; | ||
452 | |||
453 | ins->baddr0 = (long)src; | ||
454 | ins->op2_value_baddr1 = (long)dest; | ||
455 | ins->nelem = nelem; | ||
456 | ins->tri0 = tri0; | ||
457 | gru_start_instruction(ins, __opword(OP_BSTORE, 0, xtype, 0, IAA_RAM, | ||
458 | CB_IMA(hints))); | ||
459 | } | ||
460 | |||
461 | static inline void gru_gamir(void *cb, int exopc, unsigned long src, | ||
462 | unsigned int xtype, unsigned long hints) | ||
463 | { | ||
464 | struct gru_instruction *ins = (void *)cb; | ||
465 | |||
466 | ins->baddr0 = (long)src; | ||
467 | gru_start_instruction(ins, __opword(OP_GAMIR, exopc, xtype, IAA_RAM, 0, | ||
468 | CB_IMA(hints))); | ||
469 | } | ||
470 | |||
471 | static inline void gru_gamirr(void *cb, int exopc, unsigned long src, | ||
472 | unsigned int xtype, unsigned long hints) | ||
473 | { | ||
474 | struct gru_instruction *ins = (void *)cb; | ||
475 | |||
476 | ins->baddr0 = (long)src; | ||
477 | gru_start_instruction(ins, __opword(OP_GAMIRR, exopc, xtype, IAA_RAM, 0, | ||
478 | CB_IMA(hints))); | ||
479 | } | ||
480 | |||
481 | static inline void gru_gamer(void *cb, int exopc, unsigned long src, | ||
482 | unsigned int xtype, | ||
483 | unsigned long operand1, unsigned long operand2, | ||
484 | unsigned long hints) | ||
485 | { | ||
486 | struct gru_instruction *ins = (void *)cb; | ||
487 | |||
488 | ins->baddr0 = (long)src; | ||
489 | ins->op1_stride = operand1; | ||
490 | ins->op2_value_baddr1 = operand2; | ||
491 | gru_start_instruction(ins, __opword(OP_GAMER, exopc, xtype, IAA_RAM, 0, | ||
492 | CB_IMA(hints))); | ||
493 | } | ||
494 | |||
495 | static inline void gru_gamerr(void *cb, int exopc, unsigned long src, | ||
496 | unsigned int xtype, unsigned long operand1, | ||
497 | unsigned long operand2, unsigned long hints) | ||
498 | { | ||
499 | struct gru_instruction *ins = (void *)cb; | ||
500 | |||
501 | ins->baddr0 = (long)src; | ||
502 | ins->op1_stride = operand1; | ||
503 | ins->op2_value_baddr1 = operand2; | ||
504 | gru_start_instruction(ins, __opword(OP_GAMERR, exopc, xtype, IAA_RAM, 0, | ||
505 | CB_IMA(hints))); | ||
506 | } | ||
507 | |||
508 | static inline void gru_gamxr(void *cb, unsigned long src, | ||
509 | unsigned int tri0, unsigned long hints) | ||
510 | { | ||
511 | struct gru_instruction *ins = (void *)cb; | ||
512 | |||
513 | ins->baddr0 = (long)src; | ||
514 | ins->nelem = 4; | ||
515 | gru_start_instruction(ins, __opword(OP_GAMXR, EOP_XR_CSWAP, XTYPE_DW, | ||
516 | IAA_RAM, 0, CB_IMA(hints))); | ||
517 | } | ||
518 | |||
519 | static inline void gru_mesq(void *cb, unsigned long queue, | ||
520 | unsigned long tri0, unsigned long nelem, | ||
521 | unsigned long hints) | ||
522 | { | ||
523 | struct gru_instruction *ins = (void *)cb; | ||
524 | |||
525 | ins->baddr0 = (long)queue; | ||
526 | ins->nelem = nelem; | ||
527 | ins->tri0 = tri0; | ||
528 | gru_start_instruction(ins, __opword(OP_MESQ, 0, XTYPE_CL, IAA_RAM, 0, | ||
529 | CB_IMA(hints))); | ||
530 | } | ||
531 | |||
532 | static inline unsigned long gru_get_amo_value(void *cb) | ||
533 | { | ||
534 | struct gru_instruction *ins = (void *)cb; | ||
535 | |||
536 | return ins->avalue; | ||
537 | } | ||
538 | |||
539 | static inline int gru_get_amo_value_head(void *cb) | ||
540 | { | ||
541 | struct gru_instruction *ins = (void *)cb; | ||
542 | |||
543 | return ins->avalue & 0xffffffff; | ||
544 | } | ||
545 | |||
546 | static inline int gru_get_amo_value_limit(void *cb) | ||
547 | { | ||
548 | struct gru_instruction *ins = (void *)cb; | ||
549 | |||
550 | return ins->avalue >> 32; | ||
551 | } | ||
552 | |||
553 | static inline union gru_mesqhead gru_mesq_head(int head, int limit) | ||
554 | { | ||
555 | union gru_mesqhead mqh; | ||
556 | |||
557 | mqh.head = head; | ||
558 | mqh.limit = limit; | ||
559 | return mqh; | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * Get struct control_block_extended_exc_detail for CB. | ||
564 | */ | ||
565 | extern int gru_get_cb_exception_detail(void *cb, | ||
566 | struct control_block_extended_exc_detail *excdet); | ||
567 | |||
568 | #define GRU_EXC_STR_SIZE 256 | ||
569 | |||
570 | extern int gru_check_status_proc(void *cb); | ||
571 | extern int gru_wait_proc(void *cb); | ||
572 | extern void gru_wait_abort_proc(void *cb); | ||
573 | |||
574 | /* | ||
575 | * Control block definition for checking status | ||
576 | */ | ||
577 | struct gru_control_block_status { | ||
578 | unsigned int icmd :1; | ||
579 | unsigned int unused1 :31; | ||
580 | unsigned int unused2 :24; | ||
581 | unsigned int istatus :2; | ||
582 | unsigned int isubstatus :4; | ||
583 | unsigned int inused3 :2; | ||
584 | }; | ||
585 | |||
586 | /* Get CB status */ | ||
587 | static inline int gru_get_cb_status(void *cb) | ||
588 | { | ||
589 | struct gru_control_block_status *cbs = (void *)cb; | ||
590 | |||
591 | return cbs->istatus; | ||
592 | } | ||
593 | |||
594 | /* Get CB message queue substatus */ | ||
595 | static inline int gru_get_cb_message_queue_substatus(void *cb) | ||
596 | { | ||
597 | struct gru_control_block_status *cbs = (void *)cb; | ||
598 | |||
599 | return cbs->isubstatus & CBSS_MSG_QUEUE_MASK; | ||
600 | } | ||
601 | |||
602 | /* Get CB substatus */ | ||
603 | static inline int gru_get_cb_substatus(void *cb) | ||
604 | { | ||
605 | struct gru_control_block_status *cbs = (void *)cb; | ||
606 | |||
607 | return cbs->isubstatus; | ||
608 | } | ||
609 | |||
610 | /* Check the status of a CB. If the CB is in UPM mode, call the | ||
611 | * OS to handle the UPM status. | ||
612 | * Returns the CB status field value (0 for normal completion) | ||
613 | */ | ||
614 | static inline int gru_check_status(void *cb) | ||
615 | { | ||
616 | struct gru_control_block_status *cbs = (void *)cb; | ||
617 | int ret = cbs->istatus; | ||
618 | |||
619 | if (ret == CBS_CALL_OS) | ||
620 | ret = gru_check_status_proc(cb); | ||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | /* Wait for CB to complete. | ||
625 | * Returns the CB status field value (0 for normal completion) | ||
626 | */ | ||
627 | static inline int gru_wait(void *cb) | ||
628 | { | ||
629 | struct gru_control_block_status *cbs = (void *)cb; | ||
630 | int ret = cbs->istatus;; | ||
631 | |||
632 | if (ret != CBS_IDLE) | ||
633 | ret = gru_wait_proc(cb); | ||
634 | return ret; | ||
635 | } | ||
636 | |||
637 | /* Wait for CB to complete. Aborts program if error. (Note: error does NOT | ||
638 | * mean TLB mis - only fatal errors such as memory parity error or user | ||
639 | * bugs will cause termination. | ||
640 | */ | ||
641 | static inline void gru_wait_abort(void *cb) | ||
642 | { | ||
643 | struct gru_control_block_status *cbs = (void *)cb; | ||
644 | |||
645 | if (cbs->istatus != CBS_IDLE) | ||
646 | gru_wait_abort_proc(cb); | ||
647 | } | ||
648 | |||
649 | |||
650 | /* | ||
651 | * Get a pointer to a control block | ||
652 | * gseg - GSeg address returned from gru_get_thread_gru_segment() | ||
653 | * index - index of desired CB | ||
654 | */ | ||
655 | static inline void *gru_get_cb_pointer(void *gseg, | ||
656 | int index) | ||
657 | { | ||
658 | return gseg + GRU_CB_BASE + index * GRU_HANDLE_STRIDE; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Get a pointer to a cacheline in the data segment portion of a GSeg | ||
663 | * gseg - GSeg address returned from gru_get_thread_gru_segment() | ||
664 | * index - index of desired cache line | ||
665 | */ | ||
666 | static inline void *gru_get_data_pointer(void *gseg, int index) | ||
667 | { | ||
668 | return gseg + GRU_DS_BASE + index * GRU_CACHE_LINE_BYTES; | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Convert a vaddr into the tri index within the GSEG | ||
673 | * vaddr - virtual address of within gseg | ||
674 | */ | ||
675 | static inline int gru_get_tri(void *vaddr) | ||
676 | { | ||
677 | return ((unsigned long)vaddr & (GRU_GSEG_PAGESIZE - 1)) - GRU_DS_BASE; | ||
678 | } | ||
679 | #endif /* __GRU_INSTRUCTIONS_H__ */ | ||