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