This chapter describes software functions that can be used on the global reference unit (GRU). For a description of the GRU, see Chapter 1, “Altix UV GRU Direct Access API”. This chapter describes a subset of the /usr/include/uv/gru/gru_instructions.h file.
This section describes software functions used for checking the status of GRU operations, as follows:
extern int gru_check_status_proc(gru_control_block_t *cb); extern int gru_wait_proc(gru_control_block_t *cb); extern void gru_wait_abort_proc(gru_control_block_t *cb); extern void gru_abort(int, gru_control_block_t *cb, char *str); |
The gru_check_status_proc() and gru_wait_proc() functions return one of the following GRU control block status (CBS) values:
CBS_IDLE CBS_EXCEPTION CBS_ACTIVE CBS_CALL_OS |
This section describes software functions used for displaying GRU error information, as follows:
extern char *gru_get_cb_exception_detail_str(int ret, gru_control_block_t *cb, char *buf, int size); |
This section describes some GRU data transfer functions.
GRU data transfer functions have some arguments in common with each other:
xtype - datatype of the transfer. Choose from the following list:
| XTYPE_B | byte | |
| XTYPE_S | short (2-byte) | |
| XTYPE_W | word (4-byte) | |
| XTYPE_DW | doubleword (8-byte) | |
| XTYPE_CL | cacheline (64-byte) |
exopc - extended opcode for atomic memory operations (AMO).
AMOs implicit operand opcodes EOP_IR_FETCH /* Plain fetch of memory */ EOP_IR_CLR /* Fetch and clear */ EOP_IR_INC /* Fetch and increment */ EOP_IR_DEC /* Fetch and decrement */ EOP_IR_QCHK1 /* Queue check, 64 byte msg */ EOP_IR_QCHK2 /* Queue check, 128 byte msg */ Registered AMOs with implicit operand opcodes EOP_IRR_FETCH /* Registered fetch of memory */ EOP_IRR_CLR /* Registered fetch and clear */ EOP_IRR_INC /* Registered fetch and increment */ EOP_IRR_DEC /* Registered fetch and decrement */ EOP_IRR_DECZ /* Registered fetch and decrement, update on zero*/ AMOs with explicit operand opcodes EOP_ER_SWAP /* Exchange argument and memory */ EOP_ER_OR /* Logical OR with memory */ EOP_ER_AND /* Logical AND with memory */ EOP_ER_XOR /* Logical XOR with memory */ EOP_ER_ADD /* Add value to memory */ EOP_ER_CSWAP /* Compare with operand2, write operand1 if match*/ EOP_ER_CADD /* Queue check, operand1*64 byte msg */ Registered AMOs with explicit operand opcodes EOP_ERR_SWAP /* Exchange argument and memory */ EOP_ERR_OR /* Logical OR with memory */ EOP_ERR_AND /* Logical AND with memory */ EOP_ERR_XOR /* Logical XOR with memory */ EOP_ERR_ADD /* Add value to memory */ EOP_ERR_CSWAP /* Compare with operand2, write operand1 if match*/ AMOs with extened opcodes in DSR EOP_XR_CSWAP /* Masked compare exchange */ hints IMA_CB_DELAY /* hold read responses until status changes */ |
This section contains functions for GRU instructions, as follows:
- nelem and stride are in elements
- tri0/tri1 is in bytes for the beginning of the data segment.
static inline void gru_vload(gru_control_block_t *cb, void *mem_addr,
unsigned int tri0, unsigned char xtype, unsigned long nelem,
unsigned long stride, unsigned long hints) {
struct gru_instruction *ins = (struct gru_instruction *)cb;
ins->baddr0 = (long)mem_addr;
ins->nelem = nelem;
ins->op1_stride = stride;
gru_start_instruction(ins, __opdword(OP_VLOAD, 0, xtype, IAA_RAM, 0,
(unsigned long)tri0, hints));
}
static inline void gru_vstore(gru_control_block_t *cb, void *mem_addr,
unsigned int tri0, unsigned char xtype, unsigned long nelem,
unsigned long stride, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->nelem = nelem;
ins->op1_stride = stride;
gru_start_instruction(ins, __opdword(OP_VSTORE, 0, xtype, IAA_RAM, 0,
tri0, hints));
}
static inline void gru_ivload(gru_control_block_t *cb, void *mem_addr,
unsigned int tri0, unsigned int tri1, unsigned char xtype,
unsigned long nelem, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->nelem = nelem;
ins->tri1_bufsize_64 = tri1;
gru_start_instruction(ins, __opdword(OP_IVLOAD, 0, xtype, IAA_RAM, 0,
tri0, hints));
}
static inline void gru_ivstore(gru_control_block_t *cb, void *mem_addr,
unsigned int tri0, unsigned int tri1,
unsigned char xtype, unsigned long nelem, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->nelem = nelem;
ins->tri1_bufsize_64 = tri1;
gru_start_instruction(ins, __opdword(OP_IVSTORE, 0, xtype, IAA_RAM, 0,
tri0, hints));
}
static inline void gru_vset(gru_control_block_t *cb, void *mem_addr,
unsigned long value, unsigned char xtype, unsigned long nelem,
unsigned long stride, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->op2_value_baddr1 = value;
ins->nelem = nelem;
ins->op1_stride = stride;
gru_start_instruction(ins, __opdword(OP_VSET, 0, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_ivset(gru_control_block_t *cb, void *mem_addr,
unsigned int tri1, unsigned long value, unsigned char xtype,
unsigned long nelem, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->op2_value_baddr1 = value;
ins->nelem = nelem;
ins->tri1_bufsize_64 = tri1;
gru_start_instruction(ins, __opdword(OP_IVSET, 0, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_vflush(gru_control_block_t *cb, void *mem_addr,
unsigned long nelem, unsigned char xtype, unsigned long stride,
unsigned long hints)
{
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)mem_addr;
ins->op1_stride = stride;
ins->nelem = nelem;
gru_start_instruction(ins, __opdword(OP_VFLUSH, 0, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_nop(gru_control_block_t *cb, int hints) {
struct gru_instruction *ins = (void *)cb;
gru_start_instruction(ins, __opdword(OP_NOP, 0, 0, 0, 0, 0, hints)); }
static inline void gru_bcopy(gru_control_block_t *cb, const void *src,
void *dest,
unsigned int tri0, unsigned int xtype, unsigned long nelem,
unsigned int bufsize, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
#ifdef UV_REV_1_WARS
if (tri0 + bufsize * 64 >= 8192)
gru_abort_bcopy_war(0);
if (((tri0 + bufsize * 64) & 8191) == 0) // GRU 1.0 WAR
gru_abort_bcopy_war(1);
if (bufsize > 128) // GRU 1.0 WAR
gru_abort_bcopy_war(2);
#endif
ins->baddr0 = (long)src;
ins->op2_value_baddr1 = (long)dest;
ins->nelem = nelem;
ins->tri1_bufsize_64 = bufsize;
gru_start_instruction(ins, __opdword(OP_BCOPY, 0, xtype, IAA_RAM,
IAA_RAM, tri0, hints));
}
static inline void gru_bstore(gru_control_block_t *cb, const void *src,
void *dest, unsigned int tri0, unsigned int xtype,
unsigned long nelem, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
ins->op2_value_baddr1 = (long)dest;
ins->nelem = nelem;
gru_start_instruction(ins, __opdword(OP_BSTORE, 0, xtype, 0, IAA_RAM,
tri0, hints));
}
static inline void gru_gamir(gru_control_block_t *cb, int exopc, void *src,
unsigned int xtype, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
#ifdef UV_REV_1_WARS
ins->nelem = 1; // GRU 1.0 WAR
#endif
gru_start_instruction(ins, __opdword(OP_GAMIR, exopc, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_gamirr(gru_control_block_t *cb, int exopc, void *src,
unsigned int xtype, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
#ifdef UV_REV_1_WARS
ins->nelem = 1; // GRU 1.0 WAR
#endif
gru_start_instruction(ins, __opdword(OP_GAMIRR, exopc, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_gamer(gru_control_block_t *cb, int exopc, void *src,
unsigned int xtype,
unsigned long operand1, unsigned long operand2,
unsigned long hints)
{
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
ins->op1_stride = operand1;
ins->op2_value_baddr1 = operand2;
#ifdef UV_REV_1_WARS
ins->nelem = 1; // GRU 1.0 WAR
#endif
gru_start_instruction(ins, __opdword(OP_GAMER, exopc, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_gamerr(gru_control_block_t *cb, int exopc, void *src,
unsigned int xtype, unsigned long operand1,
unsigned long operand2, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
ins->op1_stride = operand1;
ins->op2_value_baddr1 = operand2;
#ifdef UV_REV_1_WARS
ins->nelem = 1; // GRU 1.0 WAR
#endif
gru_start_instruction(ins, __opdword(OP_GAMERR, exopc, xtype, IAA_RAM, 0,
0, hints));
}
static inline void gru_gamxr(gru_control_block_t *cb, void *src,
unsigned int tri0, unsigned long hints) {
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)src;
ins->nelem = 4;
gru_start_instruction(ins, __opdword(OP_GAMXR, EOP_XR_CSWAP, XTYPE_DW,
IAA_RAM, 0, 0, hints));
}
static inline void __gru_mesq(gru_control_block_t *cb, void *queue,
unsigned long tri0, unsigned long nelem,
unsigned long hints)
{
struct gru_instruction *ins = (void *)cb;
ins->baddr0 = (long)queue;
ins->nelem = nelem;
gru_start_instruction(ins, __opdword(OP_MESQ, 0, XTYPE_CL, IAA_RAM, 0,
tri0, hints));
}
#if !defined(UV_REV_1_WARS)
static inline void gru_mesq(gru_control_block_t *cb, void *queue,
unsigned long tri0, unsigned long nelem,
unsigned long hints)
{
__gru_mesq(cb, queue, tri0, nelem, hints); } #else extern void gru_mesq(gru_control_block_t *cb, void *queue,
unsigned long tri0, unsigned long nelem,
unsigned long hints);
#endif
static inline unsigned long gru_get_amo_value(gru_control_block_t *cb) {
struct gru_instruction *ins = (void *)cb;
return ins->avalue;
}
static inline int gru_get_amo_value_head(gru_control_block_t *cb) {
struct gru_instruction *ins = (void *)cb;
return ins->avalue & 0xffffffff;
}
static inline int gru_get_amo_value_limit(gru_control_block_t *cb) {
struct gru_instruction *ins = (void *)cb;
return ins->avalue >> 32;
}
static inline union gru_mesqhead gru_mesq_head(int head, int limit) {
union gru_mesqhead mqh;
mqh.head = head;
mqh.limit = limit;
return mqh;
}
#define GRU_EXC_STR_SIZE 1024
/*
* Control block definition for checking status */ struct gru_control_block_status {
unsigned int icmd :1;
unsigned int ima :3;
unsigned int reserved0 :4;
unsigned int unused1 :24;
unsigned int unused2 :24;
unsigned int istatus :2;
unsigned int isubstatus :4;
unsigned int unused3 :2;
};
/* Get CB status */
static inline int gru_get_cb_status(gru_control_block_t *cb) {
struct gru_control_block_status *cbs = (void *)cb;
return cbs->istatus;
}
/* Get CB message queue substatus */
static inline int gru_get_cb_message_queue_substatus(gru_control_block_t *cb) {
struct gru_control_block_status *cbs = (void *)cb;
return cbs->isubstatus & CBSS_MSG_QUEUE_MASK; }
/* Get CB substatus */
static inline int gru_get_cb_substatus(gru_control_block_t *cb) {
struct gru_control_block_status *cbs = (void *)cb;
return cbs->isubstatus;
}
/*
* User interface to check an instruction status. UPM and exceptions
* are handled automatically. However, this function does NOT wait
* for an active instruction to complete.
*
*/
static inline int gru_check_status(gru_control_block_t *cb) {
struct gru_control_block_status *cbs = (void *)cb;
int ret;
__barrier();
ret = cbs->istatus;
/* Must call if IDLE to update statistics */
if (ret != CBS_ACTIVE)
ret = gru_check_status_proc(cb);
return ret;
}
/*
* User interface (via inline function) to wait for an instruction
* to complete. Completion status (IDLE or EXCEPTION is returned
* to the user. Exception due to hardware errors are automatically
* retried before returning an exception.
*
*/
static inline int gru_wait(gru_control_block_t *cb) {
return gru_wait_proc(cb);
}
/*
* Wait for CB to complete. Aborts program if error. (Note: error does NOT
* mean TLB mis - only fatal errors such as memory parity error or user
* bugs will cause termination.
*/
static inline void gru_wait_abort(gru_control_block_t *cb) {
gru_wait_abort_proc(cb);
}
/*
* Get a pointer to a control block
* gseg - GSeg address returned from gru_get_thread_gru_segment()
* index - index of desired CB
*/
static inline gru_control_block_t *gru_get_cb_pointer(gru_segment_t *gseg,
int index)
{
return (void *)gseg + GRU_CB_BASE + index * GRU_HANDLE_STRIDE; }
/*
* Get a pointer to a cacheline in the data segment portion of a GSeg
* gseg - GSeg address returned from gru_get_thread_gru_segment()
* index - index of desired cache line
*/
static inline void *gru_get_data_pointer(gru_segment_t *gseg, int index) {
return (void *)gseg + GRU_DS_BASE + index * GRU_CACHE_LINE_BYTES; }
/*
* Convert a vaddr into the tri index within the GSEG
* vaddr - virtual address of within gseg
*/
static inline int gru_get_tri(void *vaddr) {
return ((unsigned long)vaddr & (GRU_MIN_GSEG_PAGESIZE - 1)) - GRU_DS_BASE; }
/*
* Decode and print a GRU instruction.
*/
void gru_print_cb_detail(const char *id, int ret, void *cb);
|