xref: /openbmc/linux/drivers/misc/sgi-gru/gruhandles.c (revision a24e5e1caf4875bbe09f328b5f4daef6d25ebcc4)
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