1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * ICSWX api 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2015 IBM Corp. 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * This provides the Initiate Coprocessor Store Word Indexed (ICSWX) 8*4882a593Smuzhiyun * instruction. This instruction is used to communicate with PowerPC 9*4882a593Smuzhiyun * coprocessors. This also provides definitions of the structures used 10*4882a593Smuzhiyun * to communicate with the coprocessor. 11*4882a593Smuzhiyun * 12*4882a593Smuzhiyun * The RFC02130: Coprocessor Architecture document is the reference for 13*4882a593Smuzhiyun * everything in this file unless otherwise noted. 14*4882a593Smuzhiyun */ 15*4882a593Smuzhiyun #ifndef _ARCH_POWERPC_INCLUDE_ASM_ICSWX_H_ 16*4882a593Smuzhiyun #define _ARCH_POWERPC_INCLUDE_ASM_ICSWX_H_ 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun #include <asm/ppc-opcode.h> /* for PPC_ICSWX */ 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun /* Chapter 6.5.8 Coprocessor-Completion Block (CCB) */ 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #define CCB_VALUE (0x3fffffffffffffff) 23*4882a593Smuzhiyun #define CCB_ADDRESS (0xfffffffffffffff8) 24*4882a593Smuzhiyun #define CCB_CM (0x0000000000000007) 25*4882a593Smuzhiyun #define CCB_CM0 (0x0000000000000004) 26*4882a593Smuzhiyun #define CCB_CM12 (0x0000000000000003) 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun #define CCB_CM0_ALL_COMPLETIONS (0x0) 29*4882a593Smuzhiyun #define CCB_CM0_LAST_IN_CHAIN (0x4) 30*4882a593Smuzhiyun #define CCB_CM12_STORE (0x0) 31*4882a593Smuzhiyun #define CCB_CM12_INTERRUPT (0x1) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun #define CCB_SIZE (0x10) 34*4882a593Smuzhiyun #define CCB_ALIGN CCB_SIZE 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun struct coprocessor_completion_block { 37*4882a593Smuzhiyun __be64 value; 38*4882a593Smuzhiyun __be64 address; 39*4882a593Smuzhiyun } __packed __aligned(CCB_ALIGN); 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun /* Chapter 6.5.7 Coprocessor-Status Block (CSB) */ 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun #define CSB_V (0x80) 45*4882a593Smuzhiyun #define CSB_F (0x04) 46*4882a593Smuzhiyun #define CSB_CH (0x03) 47*4882a593Smuzhiyun #define CSB_CE_INCOMPLETE (0x80) 48*4882a593Smuzhiyun #define CSB_CE_TERMINATION (0x40) 49*4882a593Smuzhiyun #define CSB_CE_TPBC (0x20) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun #define CSB_CC_SUCCESS (0) 52*4882a593Smuzhiyun #define CSB_CC_INVALID_ALIGN (1) 53*4882a593Smuzhiyun #define CSB_CC_OPERAND_OVERLAP (2) 54*4882a593Smuzhiyun #define CSB_CC_DATA_LENGTH (3) 55*4882a593Smuzhiyun #define CSB_CC_TRANSLATION (5) 56*4882a593Smuzhiyun #define CSB_CC_PROTECTION (6) 57*4882a593Smuzhiyun #define CSB_CC_RD_EXTERNAL (7) 58*4882a593Smuzhiyun #define CSB_CC_INVALID_OPERAND (8) 59*4882a593Smuzhiyun #define CSB_CC_PRIVILEGE (9) 60*4882a593Smuzhiyun #define CSB_CC_INTERNAL (10) 61*4882a593Smuzhiyun #define CSB_CC_WR_EXTERNAL (12) 62*4882a593Smuzhiyun #define CSB_CC_NOSPC (13) 63*4882a593Smuzhiyun #define CSB_CC_EXCESSIVE_DDE (14) 64*4882a593Smuzhiyun #define CSB_CC_WR_TRANSLATION (15) 65*4882a593Smuzhiyun #define CSB_CC_WR_PROTECTION (16) 66*4882a593Smuzhiyun #define CSB_CC_UNKNOWN_CODE (17) 67*4882a593Smuzhiyun #define CSB_CC_ABORT (18) 68*4882a593Smuzhiyun #define CSB_CC_EXCEED_BYTE_COUNT (19) /* P9 or later */ 69*4882a593Smuzhiyun #define CSB_CC_TRANSPORT (20) 70*4882a593Smuzhiyun #define CSB_CC_INVALID_CRB (21) /* P9 or later */ 71*4882a593Smuzhiyun #define CSB_CC_INVALID_DDE (30) /* P9 or later */ 72*4882a593Smuzhiyun #define CSB_CC_SEGMENTED_DDL (31) 73*4882a593Smuzhiyun #define CSB_CC_PROGRESS_POINT (32) 74*4882a593Smuzhiyun #define CSB_CC_DDE_OVERFLOW (33) 75*4882a593Smuzhiyun #define CSB_CC_SESSION (34) 76*4882a593Smuzhiyun #define CSB_CC_PROVISION (36) 77*4882a593Smuzhiyun #define CSB_CC_CHAIN (37) 78*4882a593Smuzhiyun #define CSB_CC_SEQUENCE (38) 79*4882a593Smuzhiyun #define CSB_CC_HW (39) 80*4882a593Smuzhiyun /* P9 DD2 NX Workbook 3.2 (Table 4-36): Address translation fault */ 81*4882a593Smuzhiyun #define CSB_CC_FAULT_ADDRESS (250) 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #define CSB_SIZE (0x10) 84*4882a593Smuzhiyun #define CSB_ALIGN CSB_SIZE 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun struct coprocessor_status_block { 87*4882a593Smuzhiyun u8 flags; 88*4882a593Smuzhiyun u8 cs; 89*4882a593Smuzhiyun u8 cc; 90*4882a593Smuzhiyun u8 ce; 91*4882a593Smuzhiyun __be32 count; 92*4882a593Smuzhiyun __be64 address; 93*4882a593Smuzhiyun } __packed __aligned(CSB_ALIGN); 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun /* Chapter 6.5.10 Data-Descriptor List (DDL) 97*4882a593Smuzhiyun * each list contains one or more Data-Descriptor Entries (DDE) 98*4882a593Smuzhiyun */ 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun #define DDE_P (0x8000) 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun #define DDE_SIZE (0x10) 103*4882a593Smuzhiyun #define DDE_ALIGN DDE_SIZE 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun struct data_descriptor_entry { 106*4882a593Smuzhiyun __be16 flags; 107*4882a593Smuzhiyun u8 count; 108*4882a593Smuzhiyun u8 index; 109*4882a593Smuzhiyun __be32 length; 110*4882a593Smuzhiyun __be64 address; 111*4882a593Smuzhiyun } __packed __aligned(DDE_ALIGN); 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun /* 4.3.2 NX-stamped Fault CRB */ 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun #define NX_STAMP_ALIGN (0x10) 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun struct nx_fault_stamp { 118*4882a593Smuzhiyun __be64 fault_storage_addr; 119*4882a593Smuzhiyun __be16 reserved; 120*4882a593Smuzhiyun __u8 flags; 121*4882a593Smuzhiyun __u8 fault_status; 122*4882a593Smuzhiyun __be32 pswid; 123*4882a593Smuzhiyun } __packed __aligned(NX_STAMP_ALIGN); 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun /* Chapter 6.5.2 Coprocessor-Request Block (CRB) */ 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun #define CRB_SIZE (0x80) 128*4882a593Smuzhiyun #define CRB_ALIGN (0x100) /* Errata: requires 256 alignment */ 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun /* Coprocessor Status Block field 131*4882a593Smuzhiyun * ADDRESS address of CSB 132*4882a593Smuzhiyun * C CCB is valid 133*4882a593Smuzhiyun * AT 0 = addrs are virtual, 1 = addrs are phys 134*4882a593Smuzhiyun * M enable perf monitor 135*4882a593Smuzhiyun */ 136*4882a593Smuzhiyun #define CRB_CSB_ADDRESS (0xfffffffffffffff0) 137*4882a593Smuzhiyun #define CRB_CSB_C (0x0000000000000008) 138*4882a593Smuzhiyun #define CRB_CSB_AT (0x0000000000000002) 139*4882a593Smuzhiyun #define CRB_CSB_M (0x0000000000000001) 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun struct coprocessor_request_block { 142*4882a593Smuzhiyun __be32 ccw; 143*4882a593Smuzhiyun __be32 flags; 144*4882a593Smuzhiyun __be64 csb_addr; 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun struct data_descriptor_entry source; 147*4882a593Smuzhiyun struct data_descriptor_entry target; 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun struct coprocessor_completion_block ccb; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun union { 152*4882a593Smuzhiyun struct nx_fault_stamp nx; 153*4882a593Smuzhiyun u8 reserved[16]; 154*4882a593Smuzhiyun } stamp; 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun u8 reserved[32]; 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun struct coprocessor_status_block csb; 159*4882a593Smuzhiyun } __aligned(128); 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun /* RFC02167 Initiate Coprocessor Instructions document 162*4882a593Smuzhiyun * Chapter 8.2.1.1.1 RS 163*4882a593Smuzhiyun * Chapter 8.2.3 Coprocessor Directive 164*4882a593Smuzhiyun * Chapter 8.2.4 Execution 165*4882a593Smuzhiyun * 166*4882a593Smuzhiyun * The CCW must be converted to BE before passing to icswx() 167*4882a593Smuzhiyun */ 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun #define CCW_PS (0xff000000) 170*4882a593Smuzhiyun #define CCW_CT (0x00ff0000) 171*4882a593Smuzhiyun #define CCW_CD (0x0000ffff) 172*4882a593Smuzhiyun #define CCW_CL (0x0000c000) 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun /* RFC02167 Initiate Coprocessor Instructions document 176*4882a593Smuzhiyun * Chapter 8.2.1 Initiate Coprocessor Store Word Indexed (ICSWX) 177*4882a593Smuzhiyun * Chapter 8.2.4.1 Condition Register 0 178*4882a593Smuzhiyun */ 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun #define ICSWX_INITIATED (0x8) 181*4882a593Smuzhiyun #define ICSWX_BUSY (0x4) 182*4882a593Smuzhiyun #define ICSWX_REJECTED (0x2) 183*4882a593Smuzhiyun #define ICSWX_XERS0 (0x1) /* undefined or set from XERSO. */ 184*4882a593Smuzhiyun icswx(__be32 ccw,struct coprocessor_request_block * crb)185*4882a593Smuzhiyunstatic inline int icswx(__be32 ccw, struct coprocessor_request_block *crb) 186*4882a593Smuzhiyun { 187*4882a593Smuzhiyun __be64 ccw_reg = ccw; 188*4882a593Smuzhiyun u32 cr; 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun /* NB: the same structures are used by VAS-NX */ 191*4882a593Smuzhiyun BUILD_BUG_ON(sizeof(*crb) != 128); 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun __asm__ __volatile__( 194*4882a593Smuzhiyun PPC_ICSWX(%1,0,%2) "\n" 195*4882a593Smuzhiyun "mfcr %0\n" 196*4882a593Smuzhiyun : "=r" (cr) 197*4882a593Smuzhiyun : "r" (ccw_reg), "r" (crb) 198*4882a593Smuzhiyun : "cr0", "memory"); 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun return (int)((cr >> 28) & 0xf); 201*4882a593Smuzhiyun } 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun #endif /* _ARCH_POWERPC_INCLUDE_ASM_ICSWX_H_ */ 205