1*a24e5e1cSJack Steiner /* 2*a24e5e1cSJack Steiner * GRU KERNEL MCS INSTRUCTIONS 3*a24e5e1cSJack Steiner * 4*a24e5e1cSJack Steiner * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 5*a24e5e1cSJack Steiner * 6*a24e5e1cSJack Steiner * This program is free software; you can redistribute it and/or modify 7*a24e5e1cSJack Steiner * it under the terms of the GNU General Public License as published by 8*a24e5e1cSJack Steiner * the Free Software Foundation; either version 2 of the License, or 9*a24e5e1cSJack Steiner * (at your option) any later version. 10*a24e5e1cSJack Steiner * 11*a24e5e1cSJack Steiner * This program is distributed in the hope that it will be useful, 12*a24e5e1cSJack Steiner * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*a24e5e1cSJack Steiner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*a24e5e1cSJack Steiner * GNU General Public License for more details. 15*a24e5e1cSJack Steiner * 16*a24e5e1cSJack Steiner * You should have received a copy of the GNU General Public License 17*a24e5e1cSJack Steiner * along with this program; if not, write to the Free Software 18*a24e5e1cSJack Steiner * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19*a24e5e1cSJack Steiner */ 20*a24e5e1cSJack Steiner 21*a24e5e1cSJack Steiner #include <linux/kernel.h> 22*a24e5e1cSJack Steiner #include "gru.h" 23*a24e5e1cSJack Steiner #include "grulib.h" 24*a24e5e1cSJack Steiner #include "grutables.h" 25*a24e5e1cSJack Steiner 26*a24e5e1cSJack Steiner /* 10 sec */ 27*a24e5e1cSJack Steiner #ifdef CONFIG_IA64 28*a24e5e1cSJack Steiner #include <asm/processor.h> 29*a24e5e1cSJack Steiner #define GRU_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) 30*a24e5e1cSJack Steiner #else 31*a24e5e1cSJack Steiner #include <asm/tsc.h> 32*a24e5e1cSJack Steiner #define GRU_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) 33*a24e5e1cSJack Steiner #endif 34*a24e5e1cSJack Steiner 35*a24e5e1cSJack Steiner /* Extract the status field from a kernel handle */ 36*a24e5e1cSJack Steiner #define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) 37*a24e5e1cSJack Steiner 38*a24e5e1cSJack Steiner static void start_instruction(void *h) 39*a24e5e1cSJack Steiner { 40*a24e5e1cSJack Steiner unsigned long *w0 = h; 41*a24e5e1cSJack Steiner 42*a24e5e1cSJack Steiner wmb(); /* setting CMD bit must be last */ 43*a24e5e1cSJack Steiner *w0 = *w0 | 1; 44*a24e5e1cSJack Steiner gru_flush_cache(h); 45*a24e5e1cSJack Steiner } 46*a24e5e1cSJack Steiner 47*a24e5e1cSJack Steiner static int wait_instruction_complete(void *h, enum mcs_op opc) 48*a24e5e1cSJack Steiner { 49*a24e5e1cSJack Steiner int status; 50*a24e5e1cSJack Steiner cycles_t start_time = get_cycles(); 51*a24e5e1cSJack Steiner 52*a24e5e1cSJack Steiner while (1) { 53*a24e5e1cSJack Steiner cpu_relax(); 54*a24e5e1cSJack Steiner status = GET_MSEG_HANDLE_STATUS(h); 55*a24e5e1cSJack Steiner if (status != CCHSTATUS_ACTIVE) 56*a24e5e1cSJack Steiner break; 57*a24e5e1cSJack Steiner if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) 58*a24e5e1cSJack Steiner panic("GRU %p is malfunctioning\n", h); 59*a24e5e1cSJack Steiner } 60*a24e5e1cSJack Steiner return status; 61*a24e5e1cSJack Steiner } 62*a24e5e1cSJack Steiner 63*a24e5e1cSJack Steiner #if defined CONFIG_IA64 64*a24e5e1cSJack Steiner static void cch_allocate_set_asids( 65*a24e5e1cSJack Steiner struct gru_context_configuration_handle *cch, int asidval) 66*a24e5e1cSJack Steiner { 67*a24e5e1cSJack Steiner int i; 68*a24e5e1cSJack Steiner 69*a24e5e1cSJack Steiner for (i = 0; i < 8; i++) { 70*a24e5e1cSJack Steiner cch->asid[i] = (asidval++); 71*a24e5e1cSJack Steiner #if 0 72*a24e5e1cSJack Steiner /* ZZZ hugepages not supported yet */ 73*a24e5e1cSJack Steiner if (i == RGN_HPAGE) 74*a24e5e1cSJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift); 75*a24e5e1cSJack Steiner else 76*a24e5e1cSJack Steiner #endif 77*a24e5e1cSJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT); 78*a24e5e1cSJack Steiner } 79*a24e5e1cSJack Steiner } 80*a24e5e1cSJack Steiner #elif defined CONFIG_X86_64 81*a24e5e1cSJack Steiner static void cch_allocate_set_asids( 82*a24e5e1cSJack Steiner struct gru_context_configuration_handle *cch, int asidval) 83*a24e5e1cSJack Steiner { 84*a24e5e1cSJack Steiner int i; 85*a24e5e1cSJack Steiner 86*a24e5e1cSJack Steiner for (i = 0; i < 8; i++) { 87*a24e5e1cSJack Steiner cch->asid[i] = asidval++; 88*a24e5e1cSJack Steiner cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) | 89*a24e5e1cSJack Steiner GRU_SIZEAVAIL(21); 90*a24e5e1cSJack Steiner } 91*a24e5e1cSJack Steiner } 92*a24e5e1cSJack Steiner #endif 93*a24e5e1cSJack Steiner 94*a24e5e1cSJack Steiner int cch_allocate(struct gru_context_configuration_handle *cch, 95*a24e5e1cSJack Steiner int asidval, unsigned long cbrmap, 96*a24e5e1cSJack Steiner unsigned long dsrmap) 97*a24e5e1cSJack Steiner { 98*a24e5e1cSJack Steiner cch_allocate_set_asids(cch, asidval); 99*a24e5e1cSJack Steiner cch->dsr_allocation_map = dsrmap; 100*a24e5e1cSJack Steiner cch->cbr_allocation_map = cbrmap; 101*a24e5e1cSJack Steiner cch->opc = CCHOP_ALLOCATE; 102*a24e5e1cSJack Steiner start_instruction(cch); 103*a24e5e1cSJack Steiner return wait_instruction_complete(cch, cchop_allocate); 104*a24e5e1cSJack Steiner } 105*a24e5e1cSJack Steiner 106*a24e5e1cSJack Steiner int cch_start(struct gru_context_configuration_handle *cch) 107*a24e5e1cSJack Steiner { 108*a24e5e1cSJack Steiner cch->opc = CCHOP_START; 109*a24e5e1cSJack Steiner start_instruction(cch); 110*a24e5e1cSJack Steiner return wait_instruction_complete(cch, cchop_start); 111*a24e5e1cSJack Steiner } 112*a24e5e1cSJack Steiner 113*a24e5e1cSJack Steiner int cch_interrupt(struct gru_context_configuration_handle *cch) 114*a24e5e1cSJack Steiner { 115*a24e5e1cSJack Steiner cch->opc = CCHOP_INTERRUPT; 116*a24e5e1cSJack Steiner start_instruction(cch); 117*a24e5e1cSJack Steiner return wait_instruction_complete(cch, cchop_interrupt); 118*a24e5e1cSJack Steiner } 119*a24e5e1cSJack Steiner 120*a24e5e1cSJack Steiner int cch_deallocate(struct gru_context_configuration_handle *cch) 121*a24e5e1cSJack Steiner { 122*a24e5e1cSJack Steiner cch->opc = CCHOP_DEALLOCATE; 123*a24e5e1cSJack Steiner start_instruction(cch); 124*a24e5e1cSJack Steiner return wait_instruction_complete(cch, cchop_deallocate); 125*a24e5e1cSJack Steiner } 126*a24e5e1cSJack Steiner 127*a24e5e1cSJack Steiner int cch_interrupt_sync(struct gru_context_configuration_handle 128*a24e5e1cSJack Steiner *cch) 129*a24e5e1cSJack Steiner { 130*a24e5e1cSJack Steiner cch->opc = CCHOP_INTERRUPT_SYNC; 131*a24e5e1cSJack Steiner start_instruction(cch); 132*a24e5e1cSJack Steiner return wait_instruction_complete(cch, cchop_interrupt_sync); 133*a24e5e1cSJack Steiner } 134*a24e5e1cSJack Steiner 135*a24e5e1cSJack Steiner int tgh_invalidate(struct gru_tlb_global_handle *tgh, 136*a24e5e1cSJack Steiner unsigned long vaddr, unsigned long vaddrmask, 137*a24e5e1cSJack Steiner int asid, int pagesize, int global, int n, 138*a24e5e1cSJack Steiner unsigned short ctxbitmap) 139*a24e5e1cSJack Steiner { 140*a24e5e1cSJack Steiner tgh->vaddr = vaddr; 141*a24e5e1cSJack Steiner tgh->asid = asid; 142*a24e5e1cSJack Steiner tgh->pagesize = pagesize; 143*a24e5e1cSJack Steiner tgh->n = n; 144*a24e5e1cSJack Steiner tgh->global = global; 145*a24e5e1cSJack Steiner tgh->vaddrmask = vaddrmask; 146*a24e5e1cSJack Steiner tgh->ctxbitmap = ctxbitmap; 147*a24e5e1cSJack Steiner tgh->opc = TGHOP_TLBINV; 148*a24e5e1cSJack Steiner start_instruction(tgh); 149*a24e5e1cSJack Steiner return wait_instruction_complete(tgh, tghop_invalidate); 150*a24e5e1cSJack Steiner } 151*a24e5e1cSJack Steiner 152*a24e5e1cSJack Steiner void tfh_write_only(struct gru_tlb_fault_handle *tfh, 153*a24e5e1cSJack Steiner unsigned long pfn, unsigned long vaddr, 154*a24e5e1cSJack Steiner int asid, int dirty, int pagesize) 155*a24e5e1cSJack Steiner { 156*a24e5e1cSJack Steiner tfh->fillasid = asid; 157*a24e5e1cSJack Steiner tfh->fillvaddr = vaddr; 158*a24e5e1cSJack Steiner tfh->pfn = pfn; 159*a24e5e1cSJack Steiner tfh->dirty = dirty; 160*a24e5e1cSJack Steiner tfh->pagesize = pagesize; 161*a24e5e1cSJack Steiner tfh->opc = TFHOP_WRITE_ONLY; 162*a24e5e1cSJack Steiner start_instruction(tfh); 163*a24e5e1cSJack Steiner } 164*a24e5e1cSJack Steiner 165*a24e5e1cSJack Steiner void tfh_write_restart(struct gru_tlb_fault_handle *tfh, 166*a24e5e1cSJack Steiner unsigned long paddr, int gaa, 167*a24e5e1cSJack Steiner unsigned long vaddr, int asid, int dirty, 168*a24e5e1cSJack Steiner int pagesize) 169*a24e5e1cSJack Steiner { 170*a24e5e1cSJack Steiner tfh->fillasid = asid; 171*a24e5e1cSJack Steiner tfh->fillvaddr = vaddr; 172*a24e5e1cSJack Steiner tfh->pfn = paddr >> GRU_PADDR_SHIFT; 173*a24e5e1cSJack Steiner tfh->gaa = gaa; 174*a24e5e1cSJack Steiner tfh->dirty = dirty; 175*a24e5e1cSJack Steiner tfh->pagesize = pagesize; 176*a24e5e1cSJack Steiner tfh->opc = TFHOP_WRITE_RESTART; 177*a24e5e1cSJack Steiner start_instruction(tfh); 178*a24e5e1cSJack Steiner } 179*a24e5e1cSJack Steiner 180*a24e5e1cSJack Steiner void tfh_restart(struct gru_tlb_fault_handle *tfh) 181*a24e5e1cSJack Steiner { 182*a24e5e1cSJack Steiner tfh->opc = TFHOP_RESTART; 183*a24e5e1cSJack Steiner start_instruction(tfh); 184*a24e5e1cSJack Steiner } 185*a24e5e1cSJack Steiner 186*a24e5e1cSJack Steiner void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh) 187*a24e5e1cSJack Steiner { 188*a24e5e1cSJack Steiner tfh->opc = TFHOP_USER_POLLING_MODE; 189*a24e5e1cSJack Steiner start_instruction(tfh); 190*a24e5e1cSJack Steiner } 191*a24e5e1cSJack Steiner 192*a24e5e1cSJack Steiner void tfh_exception(struct gru_tlb_fault_handle *tfh) 193*a24e5e1cSJack Steiner { 194*a24e5e1cSJack Steiner tfh->opc = TFHOP_EXCEPTION; 195*a24e5e1cSJack Steiner start_instruction(tfh); 196*a24e5e1cSJack Steiner } 197*a24e5e1cSJack Steiner 198