diff options
Diffstat (limited to 'drivers/misc/sgi-gru/gru_instructions.h')
-rw-r--r-- | drivers/misc/sgi-gru/gru_instructions.h | 669 |
1 files changed, 669 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..0dc36225c7c6 --- /dev/null +++ b/drivers/misc/sgi-gru/gru_instructions.h | |||
@@ -0,0 +1,669 @@ | |||
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 | * Architecture specific intrinsics | ||
289 | */ | ||
290 | static inline void gru_flush_cache(void *p) | ||
291 | { | ||
292 | __flush_cache(p); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Store the lower 32 bits of the command including the "start" bit. Then | ||
297 | * start the instruction executing. | ||
298 | */ | ||
299 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) | ||
300 | { | ||
301 | gru_ordered_store_int(ins, op32); | ||
302 | } | ||
303 | |||
304 | |||
305 | /* Convert "hints" to IMA */ | ||
306 | #define CB_IMA(h) ((h) | IMA_UNMAPPED) | ||
307 | |||
308 | /* Convert data segment cache line index into TRI0 / TRI1 value */ | ||
309 | #define GRU_DINDEX(i) ((i) * GRU_CACHE_LINE_BYTES) | ||
310 | |||
311 | /* Inline functions for GRU instructions. | ||
312 | * Note: | ||
313 | * - nelem and stride are in elements | ||
314 | * - tri0/tri1 is in bytes for the beginning of the data segment. | ||
315 | */ | ||
316 | static inline void gru_vload(void *cb, unsigned long mem_addr, | ||
317 | unsigned int tri0, unsigned char xtype, unsigned long nelem, | ||
318 | unsigned long stride, unsigned long hints) | ||
319 | { | ||
320 | struct gru_instruction *ins = (struct gru_instruction *)cb; | ||
321 | |||
322 | ins->baddr0 = (long)mem_addr; | ||
323 | ins->nelem = nelem; | ||
324 | ins->tri0 = tri0; | ||
325 | ins->op1_stride = stride; | ||
326 | gru_start_instruction(ins, __opword(OP_VLOAD, 0, xtype, IAA_RAM, 0, | ||
327 | CB_IMA(hints))); | ||
328 | } | ||
329 | |||
330 | static inline void gru_vstore(void *cb, unsigned long mem_addr, | ||
331 | unsigned int tri0, unsigned char xtype, unsigned long nelem, | ||
332 | unsigned long stride, unsigned long hints) | ||
333 | { | ||
334 | struct gru_instruction *ins = (void *)cb; | ||
335 | |||
336 | ins->baddr0 = (long)mem_addr; | ||
337 | ins->nelem = nelem; | ||
338 | ins->tri0 = tri0; | ||
339 | ins->op1_stride = stride; | ||
340 | gru_start_instruction(ins, __opword(OP_VSTORE, 0, xtype, IAA_RAM, 0, | ||
341 | CB_IMA(hints))); | ||
342 | } | ||
343 | |||
344 | static inline void gru_ivload(void *cb, unsigned long mem_addr, | ||
345 | unsigned int tri0, unsigned int tri1, unsigned char xtype, | ||
346 | unsigned long nelem, unsigned long hints) | ||
347 | { | ||
348 | struct gru_instruction *ins = (void *)cb; | ||
349 | |||
350 | ins->baddr0 = (long)mem_addr; | ||
351 | ins->nelem = nelem; | ||
352 | ins->tri0 = tri0; | ||
353 | ins->tri1_bufsize = tri1; | ||
354 | gru_start_instruction(ins, __opword(OP_IVLOAD, 0, xtype, IAA_RAM, 0, | ||
355 | CB_IMA(hints))); | ||
356 | } | ||
357 | |||
358 | static inline void gru_ivstore(void *cb, unsigned long mem_addr, | ||
359 | unsigned int tri0, unsigned int tri1, | ||
360 | unsigned char xtype, unsigned long nelem, unsigned long hints) | ||
361 | { | ||
362 | struct gru_instruction *ins = (void *)cb; | ||
363 | |||
364 | ins->baddr0 = (long)mem_addr; | ||
365 | ins->nelem = nelem; | ||
366 | ins->tri0 = tri0; | ||
367 | ins->tri1_bufsize = tri1; | ||
368 | gru_start_instruction(ins, __opword(OP_IVSTORE, 0, xtype, IAA_RAM, 0, | ||
369 | CB_IMA(hints))); | ||
370 | } | ||
371 | |||
372 | static inline void gru_vset(void *cb, unsigned long mem_addr, | ||
373 | unsigned long value, unsigned char xtype, unsigned long nelem, | ||
374 | unsigned long stride, unsigned long hints) | ||
375 | { | ||
376 | struct gru_instruction *ins = (void *)cb; | ||
377 | |||
378 | ins->baddr0 = (long)mem_addr; | ||
379 | ins->op2_value_baddr1 = value; | ||
380 | ins->nelem = nelem; | ||
381 | ins->op1_stride = stride; | ||
382 | gru_start_instruction(ins, __opword(OP_VSET, 0, xtype, IAA_RAM, 0, | ||
383 | CB_IMA(hints))); | ||
384 | } | ||
385 | |||
386 | static inline void gru_ivset(void *cb, unsigned long mem_addr, | ||
387 | unsigned int tri1, unsigned long value, unsigned char xtype, | ||
388 | unsigned long nelem, unsigned long hints) | ||
389 | { | ||
390 | struct gru_instruction *ins = (void *)cb; | ||
391 | |||
392 | ins->baddr0 = (long)mem_addr; | ||
393 | ins->op2_value_baddr1 = value; | ||
394 | ins->nelem = nelem; | ||
395 | ins->tri1_bufsize = tri1; | ||
396 | gru_start_instruction(ins, __opword(OP_IVSET, 0, xtype, IAA_RAM, 0, | ||
397 | CB_IMA(hints))); | ||
398 | } | ||
399 | |||
400 | static inline void gru_vflush(void *cb, unsigned long mem_addr, | ||
401 | unsigned long nelem, unsigned char xtype, unsigned long stride, | ||
402 | unsigned long hints) | ||
403 | { | ||
404 | struct gru_instruction *ins = (void *)cb; | ||
405 | |||
406 | ins->baddr0 = (long)mem_addr; | ||
407 | ins->op1_stride = stride; | ||
408 | ins->nelem = nelem; | ||
409 | gru_start_instruction(ins, __opword(OP_VFLUSH, 0, xtype, IAA_RAM, 0, | ||
410 | CB_IMA(hints))); | ||
411 | } | ||
412 | |||
413 | static inline void gru_nop(void *cb, int hints) | ||
414 | { | ||
415 | struct gru_instruction *ins = (void *)cb; | ||
416 | |||
417 | gru_start_instruction(ins, __opword(OP_NOP, 0, 0, 0, 0, CB_IMA(hints))); | ||
418 | } | ||
419 | |||
420 | |||
421 | static inline void gru_bcopy(void *cb, const unsigned long src, | ||
422 | unsigned long dest, | ||
423 | unsigned int tri0, unsigned int xtype, unsigned long nelem, | ||
424 | unsigned int bufsize, unsigned long hints) | ||
425 | { | ||
426 | struct gru_instruction *ins = (void *)cb; | ||
427 | |||
428 | ins->baddr0 = (long)src; | ||
429 | ins->op2_value_baddr1 = (long)dest; | ||
430 | ins->nelem = nelem; | ||
431 | ins->tri0 = tri0; | ||
432 | ins->tri1_bufsize = bufsize; | ||
433 | gru_start_instruction(ins, __opword(OP_BCOPY, 0, xtype, IAA_RAM, | ||
434 | IAA_RAM, CB_IMA(hints))); | ||
435 | } | ||
436 | |||
437 | static inline void gru_bstore(void *cb, const unsigned long src, | ||
438 | unsigned long dest, unsigned int tri0, unsigned int xtype, | ||
439 | unsigned long nelem, unsigned long hints) | ||
440 | { | ||
441 | struct gru_instruction *ins = (void *)cb; | ||
442 | |||
443 | ins->baddr0 = (long)src; | ||
444 | ins->op2_value_baddr1 = (long)dest; | ||
445 | ins->nelem = nelem; | ||
446 | ins->tri0 = tri0; | ||
447 | gru_start_instruction(ins, __opword(OP_BSTORE, 0, xtype, 0, IAA_RAM, | ||
448 | CB_IMA(hints))); | ||
449 | } | ||
450 | |||
451 | static inline void gru_gamir(void *cb, int exopc, unsigned long src, | ||
452 | unsigned int xtype, unsigned long hints) | ||
453 | { | ||
454 | struct gru_instruction *ins = (void *)cb; | ||
455 | |||
456 | ins->baddr0 = (long)src; | ||
457 | gru_start_instruction(ins, __opword(OP_GAMIR, exopc, xtype, IAA_RAM, 0, | ||
458 | CB_IMA(hints))); | ||
459 | } | ||
460 | |||
461 | static inline void gru_gamirr(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_GAMIRR, exopc, xtype, IAA_RAM, 0, | ||
468 | CB_IMA(hints))); | ||
469 | } | ||
470 | |||
471 | static inline void gru_gamer(void *cb, int exopc, unsigned long src, | ||
472 | unsigned int xtype, | ||
473 | unsigned long operand1, unsigned long operand2, | ||
474 | unsigned long hints) | ||
475 | { | ||
476 | struct gru_instruction *ins = (void *)cb; | ||
477 | |||
478 | ins->baddr0 = (long)src; | ||
479 | ins->op1_stride = operand1; | ||
480 | ins->op2_value_baddr1 = operand2; | ||
481 | gru_start_instruction(ins, __opword(OP_GAMER, exopc, xtype, IAA_RAM, 0, | ||
482 | CB_IMA(hints))); | ||
483 | } | ||
484 | |||
485 | static inline void gru_gamerr(void *cb, int exopc, unsigned long src, | ||
486 | unsigned int xtype, unsigned long operand1, | ||
487 | unsigned long operand2, unsigned long hints) | ||
488 | { | ||
489 | struct gru_instruction *ins = (void *)cb; | ||
490 | |||
491 | ins->baddr0 = (long)src; | ||
492 | ins->op1_stride = operand1; | ||
493 | ins->op2_value_baddr1 = operand2; | ||
494 | gru_start_instruction(ins, __opword(OP_GAMERR, exopc, xtype, IAA_RAM, 0, | ||
495 | CB_IMA(hints))); | ||
496 | } | ||
497 | |||
498 | static inline void gru_gamxr(void *cb, unsigned long src, | ||
499 | unsigned int tri0, unsigned long hints) | ||
500 | { | ||
501 | struct gru_instruction *ins = (void *)cb; | ||
502 | |||
503 | ins->baddr0 = (long)src; | ||
504 | ins->nelem = 4; | ||
505 | gru_start_instruction(ins, __opword(OP_GAMXR, EOP_XR_CSWAP, XTYPE_DW, | ||
506 | IAA_RAM, 0, CB_IMA(hints))); | ||
507 | } | ||
508 | |||
509 | static inline void gru_mesq(void *cb, unsigned long queue, | ||
510 | unsigned long tri0, unsigned long nelem, | ||
511 | unsigned long hints) | ||
512 | { | ||
513 | struct gru_instruction *ins = (void *)cb; | ||
514 | |||
515 | ins->baddr0 = (long)queue; | ||
516 | ins->nelem = nelem; | ||
517 | ins->tri0 = tri0; | ||
518 | gru_start_instruction(ins, __opword(OP_MESQ, 0, XTYPE_CL, IAA_RAM, 0, | ||
519 | CB_IMA(hints))); | ||
520 | } | ||
521 | |||
522 | static inline unsigned long gru_get_amo_value(void *cb) | ||
523 | { | ||
524 | struct gru_instruction *ins = (void *)cb; | ||
525 | |||
526 | return ins->avalue; | ||
527 | } | ||
528 | |||
529 | static inline int gru_get_amo_value_head(void *cb) | ||
530 | { | ||
531 | struct gru_instruction *ins = (void *)cb; | ||
532 | |||
533 | return ins->avalue & 0xffffffff; | ||
534 | } | ||
535 | |||
536 | static inline int gru_get_amo_value_limit(void *cb) | ||
537 | { | ||
538 | struct gru_instruction *ins = (void *)cb; | ||
539 | |||
540 | return ins->avalue >> 32; | ||
541 | } | ||
542 | |||
543 | static inline union gru_mesqhead gru_mesq_head(int head, int limit) | ||
544 | { | ||
545 | union gru_mesqhead mqh; | ||
546 | |||
547 | mqh.head = head; | ||
548 | mqh.limit = limit; | ||
549 | return mqh; | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Get struct control_block_extended_exc_detail for CB. | ||
554 | */ | ||
555 | extern int gru_get_cb_exception_detail(void *cb, | ||
556 | struct control_block_extended_exc_detail *excdet); | ||
557 | |||
558 | #define GRU_EXC_STR_SIZE 256 | ||
559 | |||
560 | extern int gru_check_status_proc(void *cb); | ||
561 | extern int gru_wait_proc(void *cb); | ||
562 | extern void gru_wait_abort_proc(void *cb); | ||
563 | |||
564 | /* | ||
565 | * Control block definition for checking status | ||
566 | */ | ||
567 | struct gru_control_block_status { | ||
568 | unsigned int icmd :1; | ||
569 | unsigned int unused1 :31; | ||
570 | unsigned int unused2 :24; | ||
571 | unsigned int istatus :2; | ||
572 | unsigned int isubstatus :4; | ||
573 | unsigned int inused3 :2; | ||
574 | }; | ||
575 | |||
576 | /* Get CB status */ | ||
577 | static inline int gru_get_cb_status(void *cb) | ||
578 | { | ||
579 | struct gru_control_block_status *cbs = (void *)cb; | ||
580 | |||
581 | return cbs->istatus; | ||
582 | } | ||
583 | |||
584 | /* Get CB message queue substatus */ | ||
585 | static inline int gru_get_cb_message_queue_substatus(void *cb) | ||
586 | { | ||
587 | struct gru_control_block_status *cbs = (void *)cb; | ||
588 | |||
589 | return cbs->isubstatus & CBSS_MSG_QUEUE_MASK; | ||
590 | } | ||
591 | |||
592 | /* Get CB substatus */ | ||
593 | static inline int gru_get_cb_substatus(void *cb) | ||
594 | { | ||
595 | struct gru_control_block_status *cbs = (void *)cb; | ||
596 | |||
597 | return cbs->isubstatus; | ||
598 | } | ||
599 | |||
600 | /* Check the status of a CB. If the CB is in UPM mode, call the | ||
601 | * OS to handle the UPM status. | ||
602 | * Returns the CB status field value (0 for normal completion) | ||
603 | */ | ||
604 | static inline int gru_check_status(void *cb) | ||
605 | { | ||
606 | struct gru_control_block_status *cbs = (void *)cb; | ||
607 | int ret = cbs->istatus; | ||
608 | |||
609 | if (ret == CBS_CALL_OS) | ||
610 | ret = gru_check_status_proc(cb); | ||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | /* Wait for CB to complete. | ||
615 | * Returns the CB status field value (0 for normal completion) | ||
616 | */ | ||
617 | static inline int gru_wait(void *cb) | ||
618 | { | ||
619 | struct gru_control_block_status *cbs = (void *)cb; | ||
620 | int ret = cbs->istatus;; | ||
621 | |||
622 | if (ret != CBS_IDLE) | ||
623 | ret = gru_wait_proc(cb); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | /* Wait for CB to complete. Aborts program if error. (Note: error does NOT | ||
628 | * mean TLB mis - only fatal errors such as memory parity error or user | ||
629 | * bugs will cause termination. | ||
630 | */ | ||
631 | static inline void gru_wait_abort(void *cb) | ||
632 | { | ||
633 | struct gru_control_block_status *cbs = (void *)cb; | ||
634 | |||
635 | if (cbs->istatus != CBS_IDLE) | ||
636 | gru_wait_abort_proc(cb); | ||
637 | } | ||
638 | |||
639 | |||
640 | /* | ||
641 | * Get a pointer to a control block | ||
642 | * gseg - GSeg address returned from gru_get_thread_gru_segment() | ||
643 | * index - index of desired CB | ||
644 | */ | ||
645 | static inline void *gru_get_cb_pointer(void *gseg, | ||
646 | int index) | ||
647 | { | ||
648 | return gseg + GRU_CB_BASE + index * GRU_HANDLE_STRIDE; | ||
649 | } | ||
650 | |||
651 | /* | ||
652 | * Get a pointer to a cacheline in the data segment portion of a GSeg | ||
653 | * gseg - GSeg address returned from gru_get_thread_gru_segment() | ||
654 | * index - index of desired cache line | ||
655 | */ | ||
656 | static inline void *gru_get_data_pointer(void *gseg, int index) | ||
657 | { | ||
658 | return gseg + GRU_DS_BASE + index * GRU_CACHE_LINE_BYTES; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Convert a vaddr into the tri index within the GSEG | ||
663 | * vaddr - virtual address of within gseg | ||
664 | */ | ||
665 | static inline int gru_get_tri(void *vaddr) | ||
666 | { | ||
667 | return ((unsigned long)vaddr & (GRU_GSEG_PAGESIZE - 1)) - GRU_DS_BASE; | ||
668 | } | ||
669 | #endif /* __GRU_INSTRUCTIONS_H__ */ | ||