1*11498SJerry.Gilliam@Sun.COM /*
2*11498SJerry.Gilliam@Sun.COM * CDDL HEADER START
3*11498SJerry.Gilliam@Sun.COM *
4*11498SJerry.Gilliam@Sun.COM * The contents of this file are subject to the terms of the
5*11498SJerry.Gilliam@Sun.COM * Common Development and Distribution License (the "License").
6*11498SJerry.Gilliam@Sun.COM * You may not use this file except in compliance with the License.
7*11498SJerry.Gilliam@Sun.COM *
8*11498SJerry.Gilliam@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11498SJerry.Gilliam@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*11498SJerry.Gilliam@Sun.COM * See the License for the specific language governing permissions
11*11498SJerry.Gilliam@Sun.COM * and limitations under the License.
12*11498SJerry.Gilliam@Sun.COM *
13*11498SJerry.Gilliam@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*11498SJerry.Gilliam@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11498SJerry.Gilliam@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*11498SJerry.Gilliam@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*11498SJerry.Gilliam@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*11498SJerry.Gilliam@Sun.COM *
19*11498SJerry.Gilliam@Sun.COM * CDDL HEADER END
20*11498SJerry.Gilliam@Sun.COM */
21*11498SJerry.Gilliam@Sun.COM /*
22*11498SJerry.Gilliam@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23*11498SJerry.Gilliam@Sun.COM * Use is subject to license terms.
24*11498SJerry.Gilliam@Sun.COM */
25*11498SJerry.Gilliam@Sun.COM
26*11498SJerry.Gilliam@Sun.COM /*
27*11498SJerry.Gilliam@Sun.COM * This file contains platform-dependent MMU support routines,
28*11498SJerry.Gilliam@Sun.COM * suitable for mmu methods with 2-cell physical addresses.
29*11498SJerry.Gilliam@Sun.COM * Use of these routines makes the caller platform-dependent,
30*11498SJerry.Gilliam@Sun.COM * since the caller assumes knowledge of the physical layout of
31*11498SJerry.Gilliam@Sun.COM * the machines address space. Generic programs should use the
32*11498SJerry.Gilliam@Sun.COM * standard client interface memory allocators.
33*11498SJerry.Gilliam@Sun.COM */
34*11498SJerry.Gilliam@Sun.COM
35*11498SJerry.Gilliam@Sun.COM #include <sys/promif.h>
36*11498SJerry.Gilliam@Sun.COM #include <sys/promimpl.h>
37*11498SJerry.Gilliam@Sun.COM
38*11498SJerry.Gilliam@Sun.COM ihandle_t
prom_mmu_ihandle(void)39*11498SJerry.Gilliam@Sun.COM prom_mmu_ihandle(void)
40*11498SJerry.Gilliam@Sun.COM {
41*11498SJerry.Gilliam@Sun.COM static ihandle_t immu;
42*11498SJerry.Gilliam@Sun.COM
43*11498SJerry.Gilliam@Sun.COM if (immu != (ihandle_t)0)
44*11498SJerry.Gilliam@Sun.COM return (immu);
45*11498SJerry.Gilliam@Sun.COM
46*11498SJerry.Gilliam@Sun.COM if (prom_getproplen(prom_chosennode(), "mmu") != sizeof (ihandle_t))
47*11498SJerry.Gilliam@Sun.COM return (immu = (ihandle_t)-1);
48*11498SJerry.Gilliam@Sun.COM
49*11498SJerry.Gilliam@Sun.COM (void) prom_getprop(prom_chosennode(), "mmu", (caddr_t)(&immu));
50*11498SJerry.Gilliam@Sun.COM return (immu);
51*11498SJerry.Gilliam@Sun.COM }
52*11498SJerry.Gilliam@Sun.COM
53*11498SJerry.Gilliam@Sun.COM /*
54*11498SJerry.Gilliam@Sun.COM * prom_map_phys:
55*11498SJerry.Gilliam@Sun.COM *
56*11498SJerry.Gilliam@Sun.COM * Create an MMU mapping for a given physical address to a given virtual
57*11498SJerry.Gilliam@Sun.COM * address. The given resources are assumed to be owned by the caller,
58*11498SJerry.Gilliam@Sun.COM * and are *not* removed from any free lists.
59*11498SJerry.Gilliam@Sun.COM *
60*11498SJerry.Gilliam@Sun.COM * This routine is suitable for mapping a 2-cell physical address.
61*11498SJerry.Gilliam@Sun.COM */
62*11498SJerry.Gilliam@Sun.COM
63*11498SJerry.Gilliam@Sun.COM int
prom_map_phys(int mode,size_t size,caddr_t virt,unsigned long long physaddr)64*11498SJerry.Gilliam@Sun.COM prom_map_phys(int mode, size_t size, caddr_t virt, unsigned long long physaddr)
65*11498SJerry.Gilliam@Sun.COM {
66*11498SJerry.Gilliam@Sun.COM cell_t ci[11];
67*11498SJerry.Gilliam@Sun.COM int rv;
68*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
69*11498SJerry.Gilliam@Sun.COM
70*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
71*11498SJerry.Gilliam@Sun.COM return (-1);
72*11498SJerry.Gilliam@Sun.COM
73*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
74*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)7; /* #argument cells */
75*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)1; /* #result cells */
76*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("map"); /* Arg1: method name */
77*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
78*11498SJerry.Gilliam@Sun.COM ci[5] = p1275_int2cell(mode); /* Arg3: SA1: mode */
79*11498SJerry.Gilliam@Sun.COM ci[6] = p1275_size2cell(size); /* Arg4: SA2: size */
80*11498SJerry.Gilliam@Sun.COM ci[7] = p1275_ptr2cell(virt); /* Arg5: SA3: virt */
81*11498SJerry.Gilliam@Sun.COM ci[8] = p1275_ull2cell_high(physaddr); /* Arg6: SA4: phys.hi */
82*11498SJerry.Gilliam@Sun.COM ci[9] = p1275_ull2cell_low(physaddr); /* Arg7: SA5: phys.low */
83*11498SJerry.Gilliam@Sun.COM
84*11498SJerry.Gilliam@Sun.COM promif_preprom();
85*11498SJerry.Gilliam@Sun.COM rv = p1275_cif_handler(&ci);
86*11498SJerry.Gilliam@Sun.COM promif_postprom();
87*11498SJerry.Gilliam@Sun.COM
88*11498SJerry.Gilliam@Sun.COM if (rv != 0)
89*11498SJerry.Gilliam@Sun.COM return (-1);
90*11498SJerry.Gilliam@Sun.COM if (ci[10] != 0) /* Res1: Catch result */
91*11498SJerry.Gilliam@Sun.COM return (-1);
92*11498SJerry.Gilliam@Sun.COM return (0);
93*11498SJerry.Gilliam@Sun.COM }
94*11498SJerry.Gilliam@Sun.COM
95*11498SJerry.Gilliam@Sun.COM void
prom_unmap_phys(size_t size,caddr_t virt)96*11498SJerry.Gilliam@Sun.COM prom_unmap_phys(size_t size, caddr_t virt)
97*11498SJerry.Gilliam@Sun.COM {
98*11498SJerry.Gilliam@Sun.COM (void) prom_unmap_virt(size, virt);
99*11498SJerry.Gilliam@Sun.COM }
100*11498SJerry.Gilliam@Sun.COM
101*11498SJerry.Gilliam@Sun.COM /*
102*11498SJerry.Gilliam@Sun.COM * Allocate aligned or unaligned virtual address space, unmapped.
103*11498SJerry.Gilliam@Sun.COM */
104*11498SJerry.Gilliam@Sun.COM caddr_t
prom_allocate_virt(uint_t align,size_t size)105*11498SJerry.Gilliam@Sun.COM prom_allocate_virt(uint_t align, size_t size)
106*11498SJerry.Gilliam@Sun.COM {
107*11498SJerry.Gilliam@Sun.COM cell_t ci[9];
108*11498SJerry.Gilliam@Sun.COM int rv;
109*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
110*11498SJerry.Gilliam@Sun.COM
111*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
112*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
113*11498SJerry.Gilliam@Sun.COM
114*11498SJerry.Gilliam@Sun.COM if (align == 0)
115*11498SJerry.Gilliam@Sun.COM align = 1;
116*11498SJerry.Gilliam@Sun.COM
117*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
118*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)4; /* #argument cells */
119*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)2; /* #result cells */
120*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */
121*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
122*11498SJerry.Gilliam@Sun.COM ci[5] = p1275_uint2cell(align); /* Arg3: SA1: align */
123*11498SJerry.Gilliam@Sun.COM ci[6] = p1275_size2cell(size); /* Arg4: SA2: size */
124*11498SJerry.Gilliam@Sun.COM
125*11498SJerry.Gilliam@Sun.COM promif_preprom();
126*11498SJerry.Gilliam@Sun.COM rv = p1275_cif_handler(&ci);
127*11498SJerry.Gilliam@Sun.COM promif_postprom();
128*11498SJerry.Gilliam@Sun.COM
129*11498SJerry.Gilliam@Sun.COM if (rv != 0)
130*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
131*11498SJerry.Gilliam@Sun.COM if (ci[7] != 0) /* Res1: Catch result */
132*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
133*11498SJerry.Gilliam@Sun.COM return (p1275_cell2ptr(ci[8])); /* Res2: SR1: base */
134*11498SJerry.Gilliam@Sun.COM }
135*11498SJerry.Gilliam@Sun.COM
136*11498SJerry.Gilliam@Sun.COM /*
137*11498SJerry.Gilliam@Sun.COM * Claim a region of virtual address space, unmapped.
138*11498SJerry.Gilliam@Sun.COM */
139*11498SJerry.Gilliam@Sun.COM caddr_t
prom_claim_virt(size_t size,caddr_t virt)140*11498SJerry.Gilliam@Sun.COM prom_claim_virt(size_t size, caddr_t virt)
141*11498SJerry.Gilliam@Sun.COM {
142*11498SJerry.Gilliam@Sun.COM cell_t ci[10];
143*11498SJerry.Gilliam@Sun.COM int rv;
144*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
145*11498SJerry.Gilliam@Sun.COM
146*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
147*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
148*11498SJerry.Gilliam@Sun.COM
149*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
150*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)5; /* #argument cells */
151*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)2; /* #result cells */
152*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */
153*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
154*11498SJerry.Gilliam@Sun.COM ci[5] = (cell_t)0; /* Arg3: align */
155*11498SJerry.Gilliam@Sun.COM ci[6] = p1275_size2cell(size); /* Arg4: length */
156*11498SJerry.Gilliam@Sun.COM ci[7] = p1275_ptr2cell(virt); /* Arg5: virt */
157*11498SJerry.Gilliam@Sun.COM
158*11498SJerry.Gilliam@Sun.COM promif_preprom();
159*11498SJerry.Gilliam@Sun.COM rv = p1275_cif_handler(&ci);
160*11498SJerry.Gilliam@Sun.COM promif_postprom();
161*11498SJerry.Gilliam@Sun.COM
162*11498SJerry.Gilliam@Sun.COM if (rv != 0)
163*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
164*11498SJerry.Gilliam@Sun.COM if (ci[8] != 0) /* Res1: Catch result */
165*11498SJerry.Gilliam@Sun.COM return ((caddr_t)-1);
166*11498SJerry.Gilliam@Sun.COM return (p1275_cell2ptr(ci[9])); /* Res2: base */
167*11498SJerry.Gilliam@Sun.COM }
168*11498SJerry.Gilliam@Sun.COM
169*11498SJerry.Gilliam@Sun.COM /*
170*11498SJerry.Gilliam@Sun.COM * Free virtual address resource (no unmapping is done).
171*11498SJerry.Gilliam@Sun.COM */
172*11498SJerry.Gilliam@Sun.COM void
prom_free_virt(size_t size,caddr_t virt)173*11498SJerry.Gilliam@Sun.COM prom_free_virt(size_t size, caddr_t virt)
174*11498SJerry.Gilliam@Sun.COM {
175*11498SJerry.Gilliam@Sun.COM cell_t ci[7];
176*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
177*11498SJerry.Gilliam@Sun.COM
178*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
179*11498SJerry.Gilliam@Sun.COM return;
180*11498SJerry.Gilliam@Sun.COM
181*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
182*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)4; /* #argument cells */
183*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)0; /* #return cells */
184*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("release"); /* Arg1: Method name */
185*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
186*11498SJerry.Gilliam@Sun.COM ci[5] = p1275_size2cell(size); /* Arg3: length */
187*11498SJerry.Gilliam@Sun.COM ci[6] = p1275_ptr2cell(virt); /* Arg4: virt */
188*11498SJerry.Gilliam@Sun.COM
189*11498SJerry.Gilliam@Sun.COM promif_preprom();
190*11498SJerry.Gilliam@Sun.COM (void) p1275_cif_handler(&ci);
191*11498SJerry.Gilliam@Sun.COM promif_postprom();
192*11498SJerry.Gilliam@Sun.COM }
193*11498SJerry.Gilliam@Sun.COM
194*11498SJerry.Gilliam@Sun.COM /*
195*11498SJerry.Gilliam@Sun.COM * Un-map virtual address. Does not free underlying resources.
196*11498SJerry.Gilliam@Sun.COM */
197*11498SJerry.Gilliam@Sun.COM void
prom_unmap_virt(size_t size,caddr_t virt)198*11498SJerry.Gilliam@Sun.COM prom_unmap_virt(size_t size, caddr_t virt)
199*11498SJerry.Gilliam@Sun.COM {
200*11498SJerry.Gilliam@Sun.COM cell_t ci[7];
201*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
202*11498SJerry.Gilliam@Sun.COM
203*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
204*11498SJerry.Gilliam@Sun.COM return;
205*11498SJerry.Gilliam@Sun.COM
206*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
207*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)4; /* #argument cells */
208*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)0; /* #result cells */
209*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("unmap"); /* Arg1: Method name */
210*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
211*11498SJerry.Gilliam@Sun.COM ci[5] = p1275_size2cell(size); /* Arg3: SA1: size */
212*11498SJerry.Gilliam@Sun.COM ci[6] = p1275_ptr2cell(virt); /* Arg4: SA2: virt */
213*11498SJerry.Gilliam@Sun.COM
214*11498SJerry.Gilliam@Sun.COM promif_preprom();
215*11498SJerry.Gilliam@Sun.COM (void) p1275_cif_handler(&ci);
216*11498SJerry.Gilliam@Sun.COM promif_postprom();
217*11498SJerry.Gilliam@Sun.COM }
218*11498SJerry.Gilliam@Sun.COM
219*11498SJerry.Gilliam@Sun.COM static pnode_t
prom_mmu_phandle(void)220*11498SJerry.Gilliam@Sun.COM prom_mmu_phandle(void)
221*11498SJerry.Gilliam@Sun.COM {
222*11498SJerry.Gilliam@Sun.COM static pnode_t pmmu = 0;
223*11498SJerry.Gilliam@Sun.COM
224*11498SJerry.Gilliam@Sun.COM if (pmmu == (pnode_t)0) {
225*11498SJerry.Gilliam@Sun.COM ihandle_t ih;
226*11498SJerry.Gilliam@Sun.COM
227*11498SJerry.Gilliam@Sun.COM if ((ih = prom_mmu_ihandle()) == (ihandle_t)-1)
228*11498SJerry.Gilliam@Sun.COM prom_panic("Can't get mmu ihandle");
229*11498SJerry.Gilliam@Sun.COM pmmu = prom_getphandle(ih);
230*11498SJerry.Gilliam@Sun.COM }
231*11498SJerry.Gilliam@Sun.COM return (pmmu);
232*11498SJerry.Gilliam@Sun.COM }
233*11498SJerry.Gilliam@Sun.COM
234*11498SJerry.Gilliam@Sun.COM
235*11498SJerry.Gilliam@Sun.COM int
prom_virt_avail_len(void)236*11498SJerry.Gilliam@Sun.COM prom_virt_avail_len(void)
237*11498SJerry.Gilliam@Sun.COM {
238*11498SJerry.Gilliam@Sun.COM return (prom_getproplen(prom_mmu_phandle(), "available"));
239*11498SJerry.Gilliam@Sun.COM }
240*11498SJerry.Gilliam@Sun.COM
241*11498SJerry.Gilliam@Sun.COM int
prom_virt_avail(caddr_t prop)242*11498SJerry.Gilliam@Sun.COM prom_virt_avail(caddr_t prop)
243*11498SJerry.Gilliam@Sun.COM {
244*11498SJerry.Gilliam@Sun.COM return (prom_getprop(prom_mmu_phandle(), "available", prop));
245*11498SJerry.Gilliam@Sun.COM }
246*11498SJerry.Gilliam@Sun.COM
247*11498SJerry.Gilliam@Sun.COM /*
248*11498SJerry.Gilliam@Sun.COM * Translate virtual address to physical address.
249*11498SJerry.Gilliam@Sun.COM * Returns 0: Success; Non-zero: failure.
250*11498SJerry.Gilliam@Sun.COM * Returns *phys_hi, *phys_lo and *mode only if successful.
251*11498SJerry.Gilliam@Sun.COM */
252*11498SJerry.Gilliam@Sun.COM int
prom_translate_virt(caddr_t virt,int * valid,unsigned long long * physaddr,int * mode)253*11498SJerry.Gilliam@Sun.COM prom_translate_virt(caddr_t virt, int *valid,
254*11498SJerry.Gilliam@Sun.COM unsigned long long *physaddr, int *mode)
255*11498SJerry.Gilliam@Sun.COM {
256*11498SJerry.Gilliam@Sun.COM cell_t ci[11];
257*11498SJerry.Gilliam@Sun.COM int rv;
258*11498SJerry.Gilliam@Sun.COM ihandle_t immu = prom_mmu_ihandle();
259*11498SJerry.Gilliam@Sun.COM
260*11498SJerry.Gilliam@Sun.COM *valid = 0;
261*11498SJerry.Gilliam@Sun.COM
262*11498SJerry.Gilliam@Sun.COM if ((immu == (ihandle_t)-1))
263*11498SJerry.Gilliam@Sun.COM return (-1);
264*11498SJerry.Gilliam@Sun.COM
265*11498SJerry.Gilliam@Sun.COM ci[0] = p1275_ptr2cell("call-method"); /* Service name */
266*11498SJerry.Gilliam@Sun.COM ci[1] = (cell_t)3; /* #argument cells */
267*11498SJerry.Gilliam@Sun.COM ci[2] = (cell_t)5; /* #result cells */
268*11498SJerry.Gilliam@Sun.COM ci[3] = p1275_ptr2cell("translate"); /* Arg1: Method name */
269*11498SJerry.Gilliam@Sun.COM ci[4] = p1275_ihandle2cell(immu); /* Arg2: mmu ihandle */
270*11498SJerry.Gilliam@Sun.COM ci[5] = p1275_ptr2cell(virt); /* Arg3: virt */
271*11498SJerry.Gilliam@Sun.COM ci[6] = 0; /* Res1: catch-resule */
272*11498SJerry.Gilliam@Sun.COM ci[7] = 0; /* Res2: sr1: valid */
273*11498SJerry.Gilliam@Sun.COM
274*11498SJerry.Gilliam@Sun.COM promif_preprom();
275*11498SJerry.Gilliam@Sun.COM rv = p1275_cif_handler(&ci);
276*11498SJerry.Gilliam@Sun.COM promif_postprom();
277*11498SJerry.Gilliam@Sun.COM
278*11498SJerry.Gilliam@Sun.COM if (rv == -1) /* Did the call fail ? */
279*11498SJerry.Gilliam@Sun.COM return (-1);
280*11498SJerry.Gilliam@Sun.COM if (ci[6] != 0) /* Catch result */
281*11498SJerry.Gilliam@Sun.COM return (-1);
282*11498SJerry.Gilliam@Sun.COM
283*11498SJerry.Gilliam@Sun.COM if (p1275_cell2int(ci[7]) != -1) /* Valid results ? */
284*11498SJerry.Gilliam@Sun.COM return (0);
285*11498SJerry.Gilliam@Sun.COM
286*11498SJerry.Gilliam@Sun.COM *mode = p1275_cell2int(ci[8]); /* Res3: sr2: mode, if valid */
287*11498SJerry.Gilliam@Sun.COM *physaddr = p1275_cells2ull(ci[9], ci[10]);
288*11498SJerry.Gilliam@Sun.COM /* Res4: sr3: phys-hi ... Res5: sr4: phys-lo */
289*11498SJerry.Gilliam@Sun.COM *valid = -1; /* Indicate valid result */
290*11498SJerry.Gilliam@Sun.COM return (0);
291*11498SJerry.Gilliam@Sun.COM }
292