134d8a380SJack Steiner /* 234d8a380SJack Steiner * SN Platform GRU Driver 334d8a380SJack Steiner * 434d8a380SJack Steiner * GRU HANDLE DEFINITION 534d8a380SJack Steiner * 634d8a380SJack Steiner * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 734d8a380SJack Steiner * 834d8a380SJack Steiner * This program is free software; you can redistribute it and/or modify 934d8a380SJack Steiner * it under the terms of the GNU General Public License as published by 1034d8a380SJack Steiner * the Free Software Foundation; either version 2 of the License, or 1134d8a380SJack Steiner * (at your option) any later version. 1234d8a380SJack Steiner * 1334d8a380SJack Steiner * This program is distributed in the hope that it will be useful, 1434d8a380SJack Steiner * but WITHOUT ANY WARRANTY; without even the implied warranty of 1534d8a380SJack Steiner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1634d8a380SJack Steiner * GNU General Public License for more details. 1734d8a380SJack Steiner * 1834d8a380SJack Steiner * You should have received a copy of the GNU General Public License 1934d8a380SJack Steiner * along with this program; if not, write to the Free Software 2034d8a380SJack Steiner * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2134d8a380SJack Steiner */ 2234d8a380SJack Steiner 2334d8a380SJack Steiner #ifndef __GRUHANDLES_H__ 2434d8a380SJack Steiner #define __GRUHANDLES_H__ 2534d8a380SJack Steiner #include "gru_instructions.h" 2634d8a380SJack Steiner 2734d8a380SJack Steiner /* 2834d8a380SJack Steiner * Manifest constants for GRU Memory Map 2934d8a380SJack Steiner */ 3034d8a380SJack Steiner #define GRU_GSEG0_BASE 0 3134d8a380SJack Steiner #define GRU_MCS_BASE (64 * 1024 * 1024) 3234d8a380SJack Steiner #define GRU_SIZE (128UL * 1024 * 1024) 3334d8a380SJack Steiner 3434d8a380SJack Steiner /* Handle & resource counts */ 3534d8a380SJack Steiner #define GRU_NUM_CB 128 3634d8a380SJack Steiner #define GRU_NUM_DSR_BYTES (32 * 1024) 3734d8a380SJack Steiner #define GRU_NUM_TFM 16 3834d8a380SJack Steiner #define GRU_NUM_TGH 24 3934d8a380SJack Steiner #define GRU_NUM_CBE 128 4034d8a380SJack Steiner #define GRU_NUM_TFH 128 4134d8a380SJack Steiner #define GRU_NUM_CCH 16 4234d8a380SJack Steiner #define GRU_NUM_GSH 1 4334d8a380SJack Steiner 4434d8a380SJack Steiner /* Maximum resource counts that can be reserved by user programs */ 4534d8a380SJack Steiner #define GRU_NUM_USER_CBR GRU_NUM_CBE 4634d8a380SJack Steiner #define GRU_NUM_USER_DSR_BYTES GRU_NUM_DSR_BYTES 4734d8a380SJack Steiner 4834d8a380SJack Steiner /* Bytes per handle & handle stride. Code assumes all cb, tfh, cbe handles 4934d8a380SJack Steiner * are the same */ 5034d8a380SJack Steiner #define GRU_HANDLE_BYTES 64 5134d8a380SJack Steiner #define GRU_HANDLE_STRIDE 256 5234d8a380SJack Steiner 5334d8a380SJack Steiner /* Base addresses of handles */ 5434d8a380SJack Steiner #define GRU_TFM_BASE (GRU_MCS_BASE + 0x00000) 5534d8a380SJack Steiner #define GRU_TGH_BASE (GRU_MCS_BASE + 0x08000) 5634d8a380SJack Steiner #define GRU_CBE_BASE (GRU_MCS_BASE + 0x10000) 5734d8a380SJack Steiner #define GRU_TFH_BASE (GRU_MCS_BASE + 0x18000) 5834d8a380SJack Steiner #define GRU_CCH_BASE (GRU_MCS_BASE + 0x20000) 5934d8a380SJack Steiner #define GRU_GSH_BASE (GRU_MCS_BASE + 0x30000) 6034d8a380SJack Steiner 6134d8a380SJack Steiner /* User gseg constants */ 6234d8a380SJack Steiner #define GRU_GSEG_STRIDE (4 * 1024 * 1024) 6334d8a380SJack Steiner #define GSEG_BASE(a) ((a) & ~(GRU_GSEG_PAGESIZE - 1)) 6434d8a380SJack Steiner 6534d8a380SJack Steiner /* Data segment constants */ 6634d8a380SJack Steiner #define GRU_DSR_AU_BYTES 1024 6734d8a380SJack Steiner #define GRU_DSR_CL (GRU_NUM_DSR_BYTES / GRU_CACHE_LINE_BYTES) 6834d8a380SJack Steiner #define GRU_DSR_AU_CL (GRU_DSR_AU_BYTES / GRU_CACHE_LINE_BYTES) 6934d8a380SJack Steiner #define GRU_DSR_AU (GRU_NUM_DSR_BYTES / GRU_DSR_AU_BYTES) 7034d8a380SJack Steiner 7134d8a380SJack Steiner /* Control block constants */ 7234d8a380SJack Steiner #define GRU_CBR_AU_SIZE 2 7334d8a380SJack Steiner #define GRU_CBR_AU (GRU_NUM_CBE / GRU_CBR_AU_SIZE) 7434d8a380SJack Steiner 7534d8a380SJack Steiner /* Convert resource counts to the number of AU */ 7634d8a380SJack Steiner #define GRU_DS_BYTES_TO_AU(n) DIV_ROUND_UP(n, GRU_DSR_AU_BYTES) 7734d8a380SJack Steiner #define GRU_CB_COUNT_TO_AU(n) DIV_ROUND_UP(n, GRU_CBR_AU_SIZE) 7834d8a380SJack Steiner 7934d8a380SJack Steiner /* UV limits */ 8034d8a380SJack Steiner #define GRU_CHIPLETS_PER_HUB 2 8134d8a380SJack Steiner #define GRU_HUBS_PER_BLADE 1 8234d8a380SJack Steiner #define GRU_CHIPLETS_PER_BLADE (GRU_HUBS_PER_BLADE * GRU_CHIPLETS_PER_HUB) 8334d8a380SJack Steiner 8434d8a380SJack Steiner /* User GRU Gseg offsets */ 8534d8a380SJack Steiner #define GRU_CB_BASE 0 8634d8a380SJack Steiner #define GRU_CB_LIMIT (GRU_CB_BASE + GRU_HANDLE_STRIDE * GRU_NUM_CBE) 8734d8a380SJack Steiner #define GRU_DS_BASE 0x20000 8834d8a380SJack Steiner #define GRU_DS_LIMIT (GRU_DS_BASE + GRU_NUM_DSR_BYTES) 8934d8a380SJack Steiner 9034d8a380SJack Steiner /* Convert a GRU physical address to the chiplet offset */ 9134d8a380SJack Steiner #define GSEGPOFF(h) ((h) & (GRU_SIZE - 1)) 9234d8a380SJack Steiner 9334d8a380SJack Steiner /* Convert an arbitrary handle address to the beginning of the GRU segment */ 9434d8a380SJack Steiner #ifndef __PLUGIN__ 9534d8a380SJack Steiner #define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1))) 9634d8a380SJack Steiner #else 9734d8a380SJack Steiner extern void *gmu_grubase(void *h); 9834d8a380SJack Steiner #define GRUBASE(h) gmu_grubase(h) 9934d8a380SJack Steiner #endif 10034d8a380SJack Steiner 10134d8a380SJack Steiner /* General addressing macros. */ 10234d8a380SJack Steiner static inline void *get_gseg_base_address(void *base, int ctxnum) 10334d8a380SJack Steiner { 10434d8a380SJack Steiner return (void *)(base + GRU_GSEG0_BASE + GRU_GSEG_STRIDE * ctxnum); 10534d8a380SJack Steiner } 10634d8a380SJack Steiner 10734d8a380SJack Steiner static inline void *get_gseg_base_address_cb(void *base, int ctxnum, int line) 10834d8a380SJack Steiner { 10934d8a380SJack Steiner return (void *)(get_gseg_base_address(base, ctxnum) + 11034d8a380SJack Steiner GRU_CB_BASE + GRU_HANDLE_STRIDE * line); 11134d8a380SJack Steiner } 11234d8a380SJack Steiner 11334d8a380SJack Steiner static inline void *get_gseg_base_address_ds(void *base, int ctxnum, int line) 11434d8a380SJack Steiner { 11534d8a380SJack Steiner return (void *)(get_gseg_base_address(base, ctxnum) + GRU_DS_BASE + 11634d8a380SJack Steiner GRU_CACHE_LINE_BYTES * line); 11734d8a380SJack Steiner } 11834d8a380SJack Steiner 11934d8a380SJack Steiner static inline struct gru_tlb_fault_map *get_tfm(void *base, int ctxnum) 12034d8a380SJack Steiner { 12134d8a380SJack Steiner return (struct gru_tlb_fault_map *)(base + GRU_TFM_BASE + 12234d8a380SJack Steiner ctxnum * GRU_HANDLE_STRIDE); 12334d8a380SJack Steiner } 12434d8a380SJack Steiner 12534d8a380SJack Steiner static inline struct gru_tlb_global_handle *get_tgh(void *base, int ctxnum) 12634d8a380SJack Steiner { 12734d8a380SJack Steiner return (struct gru_tlb_global_handle *)(base + GRU_TGH_BASE + 12834d8a380SJack Steiner ctxnum * GRU_HANDLE_STRIDE); 12934d8a380SJack Steiner } 13034d8a380SJack Steiner 13134d8a380SJack Steiner static inline struct gru_control_block_extended *get_cbe(void *base, int ctxnum) 13234d8a380SJack Steiner { 13334d8a380SJack Steiner return (struct gru_control_block_extended *)(base + GRU_CBE_BASE + 13434d8a380SJack Steiner ctxnum * GRU_HANDLE_STRIDE); 13534d8a380SJack Steiner } 13634d8a380SJack Steiner 13734d8a380SJack Steiner static inline struct gru_tlb_fault_handle *get_tfh(void *base, int ctxnum) 13834d8a380SJack Steiner { 13934d8a380SJack Steiner return (struct gru_tlb_fault_handle *)(base + GRU_TFH_BASE + 14034d8a380SJack Steiner ctxnum * GRU_HANDLE_STRIDE); 14134d8a380SJack Steiner } 14234d8a380SJack Steiner 14334d8a380SJack Steiner static inline struct gru_context_configuration_handle *get_cch(void *base, 14434d8a380SJack Steiner int ctxnum) 14534d8a380SJack Steiner { 14634d8a380SJack Steiner return (struct gru_context_configuration_handle *)(base + 14734d8a380SJack Steiner GRU_CCH_BASE + ctxnum * GRU_HANDLE_STRIDE); 14834d8a380SJack Steiner } 14934d8a380SJack Steiner 15034d8a380SJack Steiner static inline unsigned long get_cb_number(void *cb) 15134d8a380SJack Steiner { 15234d8a380SJack Steiner return (((unsigned long)cb - GRU_CB_BASE) % GRU_GSEG_PAGESIZE) / 15334d8a380SJack Steiner GRU_HANDLE_STRIDE; 15434d8a380SJack Steiner } 15534d8a380SJack Steiner 15634d8a380SJack Steiner /* byte offset to a specific GRU chiplet. (p=pnode, c=chiplet (0 or 1)*/ 15734d8a380SJack Steiner static inline unsigned long gru_chiplet_paddr(unsigned long paddr, int pnode, 15834d8a380SJack Steiner int chiplet) 15934d8a380SJack Steiner { 16034d8a380SJack Steiner return paddr + GRU_SIZE * (2 * pnode + chiplet); 16134d8a380SJack Steiner } 16234d8a380SJack Steiner 16334d8a380SJack Steiner static inline void *gru_chiplet_vaddr(void *vaddr, int pnode, int chiplet) 16434d8a380SJack Steiner { 16534d8a380SJack Steiner return vaddr + GRU_SIZE * (2 * pnode + chiplet); 16634d8a380SJack Steiner } 16734d8a380SJack Steiner 16834d8a380SJack Steiner 16934d8a380SJack Steiner 17034d8a380SJack Steiner /* 17134d8a380SJack Steiner * Global TLB Fault Map 17234d8a380SJack Steiner * Bitmap of outstanding TLB misses needing interrupt/polling service. 17334d8a380SJack Steiner * 17434d8a380SJack Steiner */ 17534d8a380SJack Steiner struct gru_tlb_fault_map { 17634d8a380SJack Steiner unsigned long fault_bits[BITS_TO_LONGS(GRU_NUM_CBE)]; 17734d8a380SJack Steiner unsigned long fill0[2]; 17834d8a380SJack Steiner unsigned long done_bits[BITS_TO_LONGS(GRU_NUM_CBE)]; 17934d8a380SJack Steiner unsigned long fill1[2]; 18034d8a380SJack Steiner }; 18134d8a380SJack Steiner 18234d8a380SJack Steiner /* 18334d8a380SJack Steiner * TGH - TLB Global Handle 18434d8a380SJack Steiner * Used for TLB flushing. 18534d8a380SJack Steiner * 18634d8a380SJack Steiner */ 18734d8a380SJack Steiner struct gru_tlb_global_handle { 18834d8a380SJack Steiner unsigned int cmd:1; /* DW 0 */ 18934d8a380SJack Steiner unsigned int delresp:1; 19034d8a380SJack Steiner unsigned int opc:1; 19134d8a380SJack Steiner unsigned int fill1:5; 19234d8a380SJack Steiner 19334d8a380SJack Steiner unsigned int fill2:8; 19434d8a380SJack Steiner 19534d8a380SJack Steiner unsigned int status:2; 19634d8a380SJack Steiner unsigned long fill3:2; 19734d8a380SJack Steiner unsigned int state:3; 19834d8a380SJack Steiner unsigned long fill4:1; 19934d8a380SJack Steiner 20034d8a380SJack Steiner unsigned int cause:3; 20134d8a380SJack Steiner unsigned long fill5:37; 20234d8a380SJack Steiner 20334d8a380SJack Steiner unsigned long vaddr:64; /* DW 1 */ 20434d8a380SJack Steiner 20534d8a380SJack Steiner unsigned int asid:24; /* DW 2 */ 20634d8a380SJack Steiner unsigned int fill6:8; 20734d8a380SJack Steiner 20834d8a380SJack Steiner unsigned int pagesize:5; 20934d8a380SJack Steiner unsigned int fill7:11; 21034d8a380SJack Steiner 21134d8a380SJack Steiner unsigned int global:1; 21234d8a380SJack Steiner unsigned int fill8:15; 21334d8a380SJack Steiner 21434d8a380SJack Steiner unsigned long vaddrmask:39; /* DW 3 */ 21534d8a380SJack Steiner unsigned int fill9:9; 21634d8a380SJack Steiner unsigned int n:10; 21734d8a380SJack Steiner unsigned int fill10:6; 21834d8a380SJack Steiner 21934d8a380SJack Steiner unsigned int ctxbitmap:16; /* DW4 */ 22034d8a380SJack Steiner unsigned long fill11[3]; 22134d8a380SJack Steiner }; 22234d8a380SJack Steiner 22334d8a380SJack Steiner enum gru_tgh_cmd { 22434d8a380SJack Steiner TGHCMD_START 22534d8a380SJack Steiner }; 22634d8a380SJack Steiner 22734d8a380SJack Steiner enum gru_tgh_opc { 22834d8a380SJack Steiner TGHOP_TLBNOP, 22934d8a380SJack Steiner TGHOP_TLBINV 23034d8a380SJack Steiner }; 23134d8a380SJack Steiner 23234d8a380SJack Steiner enum gru_tgh_status { 23334d8a380SJack Steiner TGHSTATUS_IDLE, 23434d8a380SJack Steiner TGHSTATUS_EXCEPTION, 23534d8a380SJack Steiner TGHSTATUS_ACTIVE 23634d8a380SJack Steiner }; 23734d8a380SJack Steiner 23834d8a380SJack Steiner enum gru_tgh_state { 23934d8a380SJack Steiner TGHSTATE_IDLE, 24034d8a380SJack Steiner TGHSTATE_PE_INVAL, 24134d8a380SJack Steiner TGHSTATE_INTERRUPT_INVAL, 24234d8a380SJack Steiner TGHSTATE_WAITDONE, 24334d8a380SJack Steiner TGHSTATE_RESTART_CTX, 24434d8a380SJack Steiner }; 24534d8a380SJack Steiner 24634d8a380SJack Steiner /* 24734d8a380SJack Steiner * TFH - TLB Global Handle 24834d8a380SJack Steiner * Used for TLB dropins into the GRU TLB. 24934d8a380SJack Steiner * 25034d8a380SJack Steiner */ 25134d8a380SJack Steiner struct gru_tlb_fault_handle { 25234d8a380SJack Steiner unsigned int cmd:1; /* DW 0 - low 32*/ 25334d8a380SJack Steiner unsigned int delresp:1; 25434d8a380SJack Steiner unsigned int fill0:2; 25534d8a380SJack Steiner unsigned int opc:3; 25634d8a380SJack Steiner unsigned int fill1:9; 25734d8a380SJack Steiner 25834d8a380SJack Steiner unsigned int status:2; 25934d8a380SJack Steiner unsigned int fill2:1; 26034d8a380SJack Steiner unsigned int color:1; 26134d8a380SJack Steiner unsigned int state:3; 26234d8a380SJack Steiner unsigned int fill3:1; 26334d8a380SJack Steiner 26434d8a380SJack Steiner unsigned int cause:7; /* DW 0 - high 32 */ 26534d8a380SJack Steiner unsigned int fill4:1; 26634d8a380SJack Steiner 26734d8a380SJack Steiner unsigned int indexway:12; 26834d8a380SJack Steiner unsigned int fill5:4; 26934d8a380SJack Steiner 27034d8a380SJack Steiner unsigned int ctxnum:4; 27134d8a380SJack Steiner unsigned int fill6:12; 27234d8a380SJack Steiner 27334d8a380SJack Steiner unsigned long missvaddr:64; /* DW 1 */ 27434d8a380SJack Steiner 27534d8a380SJack Steiner unsigned int missasid:24; /* DW 2 */ 27634d8a380SJack Steiner unsigned int fill7:8; 27734d8a380SJack Steiner unsigned int fillasid:24; 27834d8a380SJack Steiner unsigned int dirty:1; 27934d8a380SJack Steiner unsigned int gaa:2; 28034d8a380SJack Steiner unsigned long fill8:5; 28134d8a380SJack Steiner 28234d8a380SJack Steiner unsigned long pfn:41; /* DW 3 */ 28334d8a380SJack Steiner unsigned int fill9:7; 28434d8a380SJack Steiner unsigned int pagesize:5; 28534d8a380SJack Steiner unsigned int fill10:11; 28634d8a380SJack Steiner 28734d8a380SJack Steiner unsigned long fillvaddr:64; /* DW 4 */ 28834d8a380SJack Steiner 28934d8a380SJack Steiner unsigned long fill11[3]; 29034d8a380SJack Steiner }; 29134d8a380SJack Steiner 29234d8a380SJack Steiner enum gru_tfh_opc { 29334d8a380SJack Steiner TFHOP_NOOP, 29434d8a380SJack Steiner TFHOP_RESTART, 29534d8a380SJack Steiner TFHOP_WRITE_ONLY, 29634d8a380SJack Steiner TFHOP_WRITE_RESTART, 29734d8a380SJack Steiner TFHOP_EXCEPTION, 29834d8a380SJack Steiner TFHOP_USER_POLLING_MODE = 7, 29934d8a380SJack Steiner }; 30034d8a380SJack Steiner 30134d8a380SJack Steiner enum tfh_status { 30234d8a380SJack Steiner TFHSTATUS_IDLE, 30334d8a380SJack Steiner TFHSTATUS_EXCEPTION, 30434d8a380SJack Steiner TFHSTATUS_ACTIVE, 30534d8a380SJack Steiner }; 30634d8a380SJack Steiner 30734d8a380SJack Steiner enum tfh_state { 30834d8a380SJack Steiner TFHSTATE_INACTIVE, 30934d8a380SJack Steiner TFHSTATE_IDLE, 31034d8a380SJack Steiner TFHSTATE_MISS_UPM, 31134d8a380SJack Steiner TFHSTATE_MISS_FMM, 31234d8a380SJack Steiner TFHSTATE_HW_ERR, 31334d8a380SJack Steiner TFHSTATE_WRITE_TLB, 31434d8a380SJack Steiner TFHSTATE_RESTART_CBR, 31534d8a380SJack Steiner }; 31634d8a380SJack Steiner 31734d8a380SJack Steiner /* TFH cause bits */ 31834d8a380SJack Steiner enum tfh_cause { 31934d8a380SJack Steiner TFHCAUSE_NONE, 32034d8a380SJack Steiner TFHCAUSE_TLB_MISS, 32134d8a380SJack Steiner TFHCAUSE_TLB_MOD, 32234d8a380SJack Steiner TFHCAUSE_HW_ERROR_RR, 32334d8a380SJack Steiner TFHCAUSE_HW_ERROR_MAIN_ARRAY, 32434d8a380SJack Steiner TFHCAUSE_HW_ERROR_VALID, 32534d8a380SJack Steiner TFHCAUSE_HW_ERROR_PAGESIZE, 32634d8a380SJack Steiner TFHCAUSE_INSTRUCTION_EXCEPTION, 32734d8a380SJack Steiner TFHCAUSE_UNCORRECTIBLE_ERROR, 32834d8a380SJack Steiner }; 32934d8a380SJack Steiner 33034d8a380SJack Steiner /* GAA values */ 33134d8a380SJack Steiner #define GAA_RAM 0x0 33234d8a380SJack Steiner #define GAA_NCRAM 0x2 33334d8a380SJack Steiner #define GAA_MMIO 0x1 33434d8a380SJack Steiner #define GAA_REGISTER 0x3 33534d8a380SJack Steiner 33634d8a380SJack Steiner /* GRU paddr shift for pfn. (NOTE: shift is NOT by actual pagesize) */ 33734d8a380SJack Steiner #define GRU_PADDR_SHIFT 12 33834d8a380SJack Steiner 33934d8a380SJack Steiner /* 34034d8a380SJack Steiner * Context Configuration handle 34134d8a380SJack Steiner * Used to allocate resources to a GSEG context. 34234d8a380SJack Steiner * 34334d8a380SJack Steiner */ 34434d8a380SJack Steiner struct gru_context_configuration_handle { 34534d8a380SJack Steiner unsigned int cmd:1; /* DW0 */ 34634d8a380SJack Steiner unsigned int delresp:1; 34734d8a380SJack Steiner unsigned int opc:3; 34834d8a380SJack Steiner unsigned int unmap_enable:1; 34934d8a380SJack Steiner unsigned int req_slice_set_enable:1; 35034d8a380SJack Steiner unsigned int req_slice:2; 35134d8a380SJack Steiner unsigned int cb_int_enable:1; 35234d8a380SJack Steiner unsigned int tlb_int_enable:1; 35334d8a380SJack Steiner unsigned int tfm_fault_bit_enable:1; 35434d8a380SJack Steiner unsigned int tlb_int_select:4; 35534d8a380SJack Steiner 35634d8a380SJack Steiner unsigned int status:2; 35734d8a380SJack Steiner unsigned int state:2; 35834d8a380SJack Steiner unsigned int reserved2:4; 35934d8a380SJack Steiner 36034d8a380SJack Steiner unsigned int cause:4; 36134d8a380SJack Steiner unsigned int tfm_done_bit_enable:1; 36234d8a380SJack Steiner unsigned int unused:3; 36334d8a380SJack Steiner 36434d8a380SJack Steiner unsigned int dsr_allocation_map; 36534d8a380SJack Steiner 36634d8a380SJack Steiner unsigned long cbr_allocation_map; /* DW1 */ 36734d8a380SJack Steiner 36834d8a380SJack Steiner unsigned int asid[8]; /* DW 2 - 5 */ 36934d8a380SJack Steiner unsigned short sizeavail[8]; /* DW 6 - 7 */ 37034d8a380SJack Steiner } __attribute__ ((packed)); 37134d8a380SJack Steiner 37234d8a380SJack Steiner enum gru_cch_opc { 37334d8a380SJack Steiner CCHOP_START = 1, 37434d8a380SJack Steiner CCHOP_ALLOCATE, 37534d8a380SJack Steiner CCHOP_INTERRUPT, 37634d8a380SJack Steiner CCHOP_DEALLOCATE, 37734d8a380SJack Steiner CCHOP_INTERRUPT_SYNC, 37834d8a380SJack Steiner }; 37934d8a380SJack Steiner 38034d8a380SJack Steiner enum gru_cch_status { 38134d8a380SJack Steiner CCHSTATUS_IDLE, 38234d8a380SJack Steiner CCHSTATUS_EXCEPTION, 38334d8a380SJack Steiner CCHSTATUS_ACTIVE, 38434d8a380SJack Steiner }; 38534d8a380SJack Steiner 38634d8a380SJack Steiner enum gru_cch_state { 38734d8a380SJack Steiner CCHSTATE_INACTIVE, 38834d8a380SJack Steiner CCHSTATE_MAPPED, 38934d8a380SJack Steiner CCHSTATE_ACTIVE, 39034d8a380SJack Steiner CCHSTATE_INTERRUPTED, 39134d8a380SJack Steiner }; 39234d8a380SJack Steiner 39334d8a380SJack Steiner /* CCH Exception cause */ 39434d8a380SJack Steiner enum gru_cch_cause { 39534d8a380SJack Steiner CCHCAUSE_REGION_REGISTER_WRITE_ERROR = 1, 39634d8a380SJack Steiner CCHCAUSE_ILLEGAL_OPCODE = 2, 39734d8a380SJack Steiner CCHCAUSE_INVALID_START_REQUEST = 3, 39834d8a380SJack Steiner CCHCAUSE_INVALID_ALLOCATION_REQUEST = 4, 39934d8a380SJack Steiner CCHCAUSE_INVALID_DEALLOCATION_REQUEST = 5, 40034d8a380SJack Steiner CCHCAUSE_INVALID_INTERRUPT_REQUEST = 6, 40134d8a380SJack Steiner CCHCAUSE_CCH_BUSY = 7, 40234d8a380SJack Steiner CCHCAUSE_NO_CBRS_TO_ALLOCATE = 8, 40334d8a380SJack Steiner CCHCAUSE_BAD_TFM_CONFIG = 9, 40434d8a380SJack Steiner CCHCAUSE_CBR_RESOURCES_OVERSUBSCRIPED = 10, 40534d8a380SJack Steiner CCHCAUSE_DSR_RESOURCES_OVERSUBSCRIPED = 11, 40634d8a380SJack Steiner CCHCAUSE_CBR_DEALLOCATION_ERROR = 12, 40734d8a380SJack Steiner }; 40834d8a380SJack Steiner /* 40934d8a380SJack Steiner * CBE - Control Block Extended 41034d8a380SJack Steiner * Maintains internal GRU state for active CBs. 41134d8a380SJack Steiner * 41234d8a380SJack Steiner */ 41334d8a380SJack Steiner struct gru_control_block_extended { 41434d8a380SJack Steiner unsigned int reserved0:1; /* DW 0 - low */ 41534d8a380SJack Steiner unsigned int imacpy:3; 41634d8a380SJack Steiner unsigned int reserved1:4; 41734d8a380SJack Steiner unsigned int xtypecpy:3; 41834d8a380SJack Steiner unsigned int iaa0cpy:2; 41934d8a380SJack Steiner unsigned int iaa1cpy:2; 42034d8a380SJack Steiner unsigned int reserved2:1; 42134d8a380SJack Steiner unsigned int opccpy:8; 42234d8a380SJack Steiner unsigned int exopccpy:8; 42334d8a380SJack Steiner 42434d8a380SJack Steiner unsigned int idef2cpy:22; /* DW 0 - high */ 42534d8a380SJack Steiner unsigned int reserved3:10; 42634d8a380SJack Steiner 42734d8a380SJack Steiner unsigned int idef4cpy:22; /* DW 1 */ 42834d8a380SJack Steiner unsigned int reserved4:10; 42934d8a380SJack Steiner unsigned int idef4upd:22; 43034d8a380SJack Steiner unsigned int reserved5:10; 43134d8a380SJack Steiner 43234d8a380SJack Steiner unsigned long idef1upd:64; /* DW 2 */ 43334d8a380SJack Steiner 43434d8a380SJack Steiner unsigned long idef5cpy:64; /* DW 3 */ 43534d8a380SJack Steiner 43634d8a380SJack Steiner unsigned long idef6cpy:64; /* DW 4 */ 43734d8a380SJack Steiner 43834d8a380SJack Steiner unsigned long idef3upd:64; /* DW 5 */ 43934d8a380SJack Steiner 44034d8a380SJack Steiner unsigned long idef5upd:64; /* DW 6 */ 44134d8a380SJack Steiner 44234d8a380SJack Steiner unsigned int idef2upd:22; /* DW 7 */ 44334d8a380SJack Steiner unsigned int reserved6:10; 44434d8a380SJack Steiner 44534d8a380SJack Steiner unsigned int ecause:20; 44634d8a380SJack Steiner unsigned int cbrstate:4; 44734d8a380SJack Steiner unsigned int cbrexecstatus:8; 44834d8a380SJack Steiner }; 44934d8a380SJack Steiner 45034d8a380SJack Steiner enum gru_cbr_state { 45134d8a380SJack Steiner CBRSTATE_INACTIVE, 45234d8a380SJack Steiner CBRSTATE_IDLE, 45334d8a380SJack Steiner CBRSTATE_PE_CHECK, 45434d8a380SJack Steiner CBRSTATE_QUEUED, 45534d8a380SJack Steiner CBRSTATE_WAIT_RESPONSE, 45634d8a380SJack Steiner CBRSTATE_INTERRUPTED, 45734d8a380SJack Steiner CBRSTATE_INTERRUPTED_MISS_FMM, 45834d8a380SJack Steiner CBRSTATE_BUSY_INTERRUPT_MISS_FMM, 45934d8a380SJack Steiner CBRSTATE_INTERRUPTED_MISS_UPM, 46034d8a380SJack Steiner CBRSTATE_BUSY_INTERRUPTED_MISS_UPM, 46134d8a380SJack Steiner CBRSTATE_REQUEST_ISSUE, 46234d8a380SJack Steiner CBRSTATE_BUSY_INTERRUPT, 46334d8a380SJack Steiner }; 46434d8a380SJack Steiner 46534d8a380SJack Steiner /* CBE cbrexecstatus bits */ 46634d8a380SJack Steiner #define CBR_EXS_ABORT_OCC_BIT 0 46734d8a380SJack Steiner #define CBR_EXS_INT_OCC_BIT 1 46834d8a380SJack Steiner #define CBR_EXS_PENDING_BIT 2 46934d8a380SJack Steiner #define CBR_EXS_QUEUED_BIT 3 47034d8a380SJack Steiner #define CBR_EXS_TLBHW_BIT 4 47134d8a380SJack Steiner #define CBR_EXS_EXCEPTION_BIT 5 47234d8a380SJack Steiner 47334d8a380SJack Steiner #define CBR_EXS_ABORT_OCC (1 << CBR_EXS_ABORT_OCC_BIT) 47434d8a380SJack Steiner #define CBR_EXS_INT_OCC (1 << CBR_EXS_INT_OCC_BIT) 47534d8a380SJack Steiner #define CBR_EXS_PENDING (1 << CBR_EXS_PENDING_BIT) 47634d8a380SJack Steiner #define CBR_EXS_QUEUED (1 << CBR_EXS_QUEUED_BIT) 47734d8a380SJack Steiner #define CBR_EXS_TLBHW (1 << CBR_EXS_TLBHW_BIT) 47834d8a380SJack Steiner #define CBR_EXS_EXCEPTION (1 << CBR_EXS_EXCEPTION_BIT) 47934d8a380SJack Steiner 48034d8a380SJack Steiner /* CBE ecause bits - defined in gru_instructions.h */ 48134d8a380SJack Steiner 48234d8a380SJack Steiner /* 48334d8a380SJack Steiner * Convert a processor pagesize into the strange encoded pagesize used by the 48434d8a380SJack Steiner * GRU. Processor pagesize is encoded as log of bytes per page. (or PAGE_SHIFT) 48534d8a380SJack Steiner * pagesize log pagesize grupagesize 48634d8a380SJack Steiner * 4k 12 0 48734d8a380SJack Steiner * 16k 14 1 48834d8a380SJack Steiner * 64k 16 2 48934d8a380SJack Steiner * 256k 18 3 49034d8a380SJack Steiner * 1m 20 4 49134d8a380SJack Steiner * 2m 21 5 49234d8a380SJack Steiner * 4m 22 6 49334d8a380SJack Steiner * 16m 24 7 49434d8a380SJack Steiner * 64m 26 8 49534d8a380SJack Steiner * ... 49634d8a380SJack Steiner */ 49734d8a380SJack Steiner #define GRU_PAGESIZE(sh) ((((sh) > 20 ? (sh) + 2: (sh)) >> 1) - 6) 49834d8a380SJack Steiner #define GRU_SIZEAVAIL(sh) (1UL << GRU_PAGESIZE(sh)) 49934d8a380SJack Steiner 50034d8a380SJack Steiner /* minimum TLB purge count to ensure a full purge */ 50134d8a380SJack Steiner #define GRUMAXINVAL 1024UL 50234d8a380SJack Steiner 50334d8a380SJack Steiner 50434d8a380SJack Steiner /* Extract the status field from a kernel handle */ 50534d8a380SJack Steiner #define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) 50634d8a380SJack Steiner 50734d8a380SJack Steiner static inline void start_instruction(void *h) 50834d8a380SJack Steiner { 50934d8a380SJack Steiner unsigned long *w0 = h; 51034d8a380SJack Steiner 51134d8a380SJack Steiner wmb(); /* setting CMD bit must be last */ 51234d8a380SJack Steiner *w0 = *w0 | 1; 51334d8a380SJack Steiner gru_flush_cache(h); 51434d8a380SJack Steiner } 51534d8a380SJack Steiner 51634d8a380SJack Steiner static inline int wait_instruction_complete(void *h) 51734d8a380SJack Steiner { 51834d8a380SJack Steiner int status; 51934d8a380SJack Steiner 52034d8a380SJack Steiner do { 52134d8a380SJack Steiner cpu_relax(); 52234d8a380SJack Steiner barrier(); 52334d8a380SJack Steiner status = GET_MSEG_HANDLE_STATUS(h); 52434d8a380SJack Steiner } while (status == CCHSTATUS_ACTIVE); 52534d8a380SJack Steiner return status; 52634d8a380SJack Steiner } 52734d8a380SJack Steiner 52834d8a380SJack Steiner #if defined CONFIG_IA64 52934d8a380SJack Steiner static inline void cch_allocate_set_asids( 53034d8a380SJack Steiner struct gru_context_configuration_handle *cch, int asidval) 53134d8a380SJack Steiner { 53234d8a380SJack Steiner int i; 53334d8a380SJack Steiner 53434d8a380SJack Steiner for (i = 0; i <= RGN_HPAGE; i++) { /* assume HPAGE is last region */ 53534d8a380SJack Steiner cch->asid[i] = (asidval++); 53634d8a380SJack Steiner #if 0 53734d8a380SJack Steiner /* ZZZ hugepages not supported yet */ 53834d8a380SJack Steiner if (i == RGN_HPAGE) 53934d8a380SJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift); 54034d8a380SJack Steiner else 54134d8a380SJack Steiner #endif 54234d8a380SJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT); 54334d8a380SJack Steiner } 54434d8a380SJack Steiner } 54534d8a380SJack Steiner #elif defined CONFIG_X86_64 54634d8a380SJack Steiner static inline void cch_allocate_set_asids( 54734d8a380SJack Steiner struct gru_context_configuration_handle *cch, int asidval) 54834d8a380SJack Steiner { 54934d8a380SJack Steiner int i; 55034d8a380SJack Steiner 55134d8a380SJack Steiner for (i = 0; i < 8; i++) { 55234d8a380SJack Steiner cch->asid[i] = asidval++; 55334d8a380SJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) | 55434d8a380SJack Steiner GRU_SIZEAVAIL(21); 55534d8a380SJack Steiner } 55634d8a380SJack Steiner } 55734d8a380SJack Steiner #endif 55834d8a380SJack Steiner 55934d8a380SJack Steiner static inline int cch_allocate(struct gru_context_configuration_handle *cch, 56034d8a380SJack Steiner int asidval, unsigned long cbrmap, 56134d8a380SJack Steiner unsigned long dsrmap) 56234d8a380SJack Steiner { 56334d8a380SJack Steiner cch_allocate_set_asids(cch, asidval); 56434d8a380SJack Steiner cch->dsr_allocation_map = dsrmap; 56534d8a380SJack Steiner cch->cbr_allocation_map = cbrmap; 56634d8a380SJack Steiner cch->opc = CCHOP_ALLOCATE; 56734d8a380SJack Steiner start_instruction(cch); 56834d8a380SJack Steiner return wait_instruction_complete(cch); 56934d8a380SJack Steiner } 57034d8a380SJack Steiner 57134d8a380SJack Steiner static inline int cch_start(struct gru_context_configuration_handle *cch) 57234d8a380SJack Steiner { 57334d8a380SJack Steiner cch->opc = CCHOP_START; 57434d8a380SJack Steiner start_instruction(cch); 57534d8a380SJack Steiner return wait_instruction_complete(cch); 57634d8a380SJack Steiner } 57734d8a380SJack Steiner 57834d8a380SJack Steiner static inline int cch_interrupt(struct gru_context_configuration_handle *cch) 57934d8a380SJack Steiner { 58034d8a380SJack Steiner cch->opc = CCHOP_INTERRUPT; 58134d8a380SJack Steiner start_instruction(cch); 58234d8a380SJack Steiner return wait_instruction_complete(cch); 58334d8a380SJack Steiner } 58434d8a380SJack Steiner 58534d8a380SJack Steiner static inline int cch_deallocate(struct gru_context_configuration_handle *cch) 58634d8a380SJack Steiner { 58734d8a380SJack Steiner cch->opc = CCHOP_DEALLOCATE; 58834d8a380SJack Steiner start_instruction(cch); 58934d8a380SJack Steiner return wait_instruction_complete(cch); 59034d8a380SJack Steiner } 59134d8a380SJack Steiner 59234d8a380SJack Steiner static inline int cch_interrupt_sync(struct gru_context_configuration_handle 59334d8a380SJack Steiner *cch) 59434d8a380SJack Steiner { 59534d8a380SJack Steiner cch->opc = CCHOP_INTERRUPT_SYNC; 59634d8a380SJack Steiner start_instruction(cch); 59734d8a380SJack Steiner return wait_instruction_complete(cch); 59834d8a380SJack Steiner } 59934d8a380SJack Steiner 60034d8a380SJack Steiner static inline int tgh_invalidate(struct gru_tlb_global_handle *tgh, 60134d8a380SJack Steiner unsigned long vaddr, unsigned long vaddrmask, 60234d8a380SJack Steiner int asid, int pagesize, int global, int n, 60334d8a380SJack Steiner unsigned short ctxbitmap) 60434d8a380SJack Steiner { 60534d8a380SJack Steiner tgh->vaddr = vaddr; 60634d8a380SJack Steiner tgh->asid = asid; 60734d8a380SJack Steiner tgh->pagesize = pagesize; 60834d8a380SJack Steiner tgh->n = n; 60934d8a380SJack Steiner tgh->global = global; 61034d8a380SJack Steiner tgh->vaddrmask = vaddrmask; 61134d8a380SJack Steiner tgh->ctxbitmap = ctxbitmap; 61234d8a380SJack Steiner tgh->opc = TGHOP_TLBINV; 61334d8a380SJack Steiner start_instruction(tgh); 61434d8a380SJack Steiner return wait_instruction_complete(tgh); 61534d8a380SJack Steiner } 61634d8a380SJack Steiner 61734d8a380SJack Steiner static inline void tfh_write_only(struct gru_tlb_fault_handle *tfh, 61834d8a380SJack Steiner unsigned long pfn, unsigned long vaddr, 61934d8a380SJack Steiner int asid, int dirty, int pagesize) 62034d8a380SJack Steiner { 62134d8a380SJack Steiner tfh->fillasid = asid; 62234d8a380SJack Steiner tfh->fillvaddr = vaddr; 62334d8a380SJack Steiner tfh->pfn = pfn; 62434d8a380SJack Steiner tfh->dirty = dirty; 62534d8a380SJack Steiner tfh->pagesize = pagesize; 62634d8a380SJack Steiner tfh->opc = TFHOP_WRITE_ONLY; 62734d8a380SJack Steiner start_instruction(tfh); 62834d8a380SJack Steiner } 62934d8a380SJack Steiner 63034d8a380SJack Steiner static inline void tfh_write_restart(struct gru_tlb_fault_handle *tfh, 63134d8a380SJack Steiner unsigned long paddr, int gaa, 63234d8a380SJack Steiner unsigned long vaddr, int asid, int dirty, 63334d8a380SJack Steiner int pagesize) 63434d8a380SJack Steiner { 63534d8a380SJack Steiner tfh->fillasid = asid; 63634d8a380SJack Steiner tfh->fillvaddr = vaddr; 63734d8a380SJack Steiner tfh->pfn = paddr >> GRU_PADDR_SHIFT; 63834d8a380SJack Steiner tfh->gaa = gaa; 63934d8a380SJack Steiner tfh->dirty = dirty; 64034d8a380SJack Steiner tfh->pagesize = pagesize; 64134d8a380SJack Steiner tfh->opc = TFHOP_WRITE_RESTART; 64234d8a380SJack Steiner start_instruction(tfh); 64334d8a380SJack Steiner } 64434d8a380SJack Steiner 64534d8a380SJack Steiner static inline void tfh_restart(struct gru_tlb_fault_handle *tfh) 64634d8a380SJack Steiner { 64734d8a380SJack Steiner tfh->opc = TFHOP_RESTART; 64834d8a380SJack Steiner start_instruction(tfh); 64934d8a380SJack Steiner } 65034d8a380SJack Steiner 65134d8a380SJack Steiner static inline void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh) 65234d8a380SJack Steiner { 65334d8a380SJack Steiner tfh->opc = TFHOP_USER_POLLING_MODE; 65434d8a380SJack Steiner start_instruction(tfh); 65534d8a380SJack Steiner } 65634d8a380SJack Steiner 65734d8a380SJack Steiner static inline void tfh_exception(struct gru_tlb_fault_handle *tfh) 65834d8a380SJack Steiner { 65934d8a380SJack Steiner tfh->opc = TFHOP_EXCEPTION; 66034d8a380SJack Steiner start_instruction(tfh); 66134d8a380SJack Steiner } 66234d8a380SJack Steiner 66334d8a380SJack Steiner #endif /* __GRUHANDLES_H__ */ 664