xref: /illumos-gate/usr/src/uts/sfmmu/ml/sfmmu_kdi.S (revision 55fea89d)
1*5d9d9091SRichard Lowe/*
2*5d9d9091SRichard Lowe * CDDL HEADER START
3*5d9d9091SRichard Lowe *
4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the
5*5d9d9091SRichard Lowe * Common Development and Distribution License (the "License").
6*5d9d9091SRichard Lowe * You may not use this file except in compliance with the License.
7*5d9d9091SRichard Lowe *
8*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*5d9d9091SRichard Lowe * See the License for the specific language governing permissions
11*5d9d9091SRichard Lowe * and limitations under the License.
12*5d9d9091SRichard Lowe *
13*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*5d9d9091SRichard Lowe *
19*5d9d9091SRichard Lowe * CDDL HEADER END
20*5d9d9091SRichard Lowe */
21*5d9d9091SRichard Lowe
22*5d9d9091SRichard Lowe/*
23*5d9d9091SRichard Lowe * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5d9d9091SRichard Lowe * Use is subject to license terms.
25*5d9d9091SRichard Lowe */
26*5d9d9091SRichard Lowe
27*5d9d9091SRichard Lowe#include <sys/asm_linkage.h>
28*5d9d9091SRichard Lowe#include "assym.h"
29*5d9d9091SRichard Lowe
30*5d9d9091SRichard Lowe#include <sys/sun4asi.h>
31*5d9d9091SRichard Lowe#include <sys/machparam.h>
32*5d9d9091SRichard Lowe#include <vm/hat_sfmmu.h>
33*5d9d9091SRichard Lowe
34*5d9d9091SRichard Lowe/*
35*5d9d9091SRichard Lowe * This file contains a kmdb-support function which retrieves the TTE for a
36*5d9d9091SRichard Lowe * given VA/context pair, and returns it to the caller if the TTE is valid.
37*5d9d9091SRichard Lowe * The code here is essentially an assembly implementation of the unix-tte
38*5d9d9091SRichard Lowe * word used to allow OBP to do the same thing.
39*5d9d9091SRichard Lowe *
40*5d9d9091SRichard Lowe * Depending on the invocation context, the translator may be invoked either
41*5d9d9091SRichard Lowe * as a normal function (kdi_vatotte) or as a trap handler fragment
42*5d9d9091SRichard Lowe * (kdi_trap_vatotte).
43*5d9d9091SRichard Lowe */
44*5d9d9091SRichard Lowe
45*5d9d9091SRichard Lowe/*
46*5d9d9091SRichard Lowe * uint64_t
47*5d9d9091SRichard Lowe * kdi_hme_hash_function(sfmmu_t *sfmmup, uintptr_t va, uint_t hmeshift)
48*5d9d9091SRichard Lowe * {
49*5d9d9091SRichard Lowe *	uintptr_t hash = (uintptr_t)sfmmup ^ (va >> hmeshift);
50*5d9d9091SRichard Lowe *
51*5d9d9091SRichard Lowe *	if (sfmmup == KHATID) {
52*5d9d9091SRichard Lowe *		return (khme_hash_pa + (hash & KHMEHASH_SZ) *
53*5d9d9091SRichard Lowe *		    sizeof (struct hmehash_bucket));
54*5d9d9091SRichard Lowe *	} else {
55*5d9d9091SRichard Lowe *		return (uhme_hash_pa + (hash & UHMEHASH_SZ) *
56*5d9d9091SRichard Lowe *		    sizeof (struct hmehash_bucket));
57*5d9d9091SRichard Lowe *	}
58*5d9d9091SRichard Lowe * }
59*5d9d9091SRichard Lowe */
60*5d9d9091SRichard Lowe
61*5d9d9091SRichard Lowe/*
62*5d9d9091SRichard Lowe * Parameters:	%g1: VA, %g2: sfmmup, %g4: hmeshift
63*5d9d9091SRichard Lowe * Scratch:	%g4, %g5, %g6 available
64*5d9d9091SRichard Lowe * Return:	Hash value in %g4
65*5d9d9091SRichard Lowe */
66*5d9d9091SRichard Lowe
67*5d9d9091SRichard Lowe#define	KDI_HME_HASH_FUNCTION \
68*5d9d9091SRichard Lowe	srlx	%g1, %g4, %g4;		/* va >> hmeshift */		\
69*5d9d9091SRichard Lowe	xor	%g4, %g2, %g4;		/* hash in g4 */		\
70*5d9d9091SRichard Lowe	set	KHATID, %g5;						\
71*5d9d9091SRichard Lowe	ldx	[%g5], %g5;						\
72*5d9d9091SRichard Lowe	cmp	%g2, %g5;						\
73*5d9d9091SRichard Lowe	be	%xcc, is_khat;						\
74*5d9d9091SRichard Lowe	nop;								\
75*5d9d9091SRichard Lowe									\
76*5d9d9091SRichard Lowe	/* sfmmup != KHATID */						\
77*5d9d9091SRichard Lowe	set	UHMEHASH_SZ, %g5;					\
78*5d9d9091SRichard Lowe	ld	[%g5], %g5;						\
79*5d9d9091SRichard Lowe	and	%g4, %g5, %g4;						\
80*5d9d9091SRichard Lowe	mulx	%g4, HMEBUCK_SIZE, %g4; /* g4 = off from hash_pa */	\
81*5d9d9091SRichard Lowe	set	uhme_hash_pa, %g5;					\
82*5d9d9091SRichard Lowe	ldx	[%g5], %g5;						\
83*5d9d9091SRichard Lowe	ba	hash_done;						\
84*5d9d9091SRichard Lowe	add	%g4, %g5, %g4;						\
85*5d9d9091SRichard Lowe									\
86*5d9d9091SRichard Loweis_khat: /* sfmmup == KHATID */						\
87*5d9d9091SRichard Lowe	set	KHMEHASH_SZ, %g5;					\
88*5d9d9091SRichard Lowe	ld	[%g5], %g5;						\
89*5d9d9091SRichard Lowe	and	%g4, %g5, %g4;						\
90*5d9d9091SRichard Lowe	mulx	%g4, HMEBUCK_SIZE, %g4;	/* g4 = off from hash_pa */	\
91*5d9d9091SRichard Lowe	set	khme_hash_pa, %g5;					\
92*5d9d9091SRichard Lowe	ldx	[%g5], %g5;						\
93*5d9d9091SRichard Lowe	add	%g4, %g5, %g4;						\
94*5d9d9091SRichard Lowe									\
95*5d9d9091SRichard Lowehash_done:
96*5d9d9091SRichard Lowe
97*5d9d9091SRichard Lowe/*
98*5d9d9091SRichard Lowe * uint64_t
99*5d9d9091SRichard Lowe * kdi_hme_hash_tag(uint64_t rehash, uintptr_t va)
100*5d9d9091SRichard Lowe * {
101*5d9d9091SRichard Lowe *	uint_t hmeshift = HME_HASH_SHIFT(rehash);
102*5d9d9091SRichard Lowe *	uint64_t bspage = HME_HASH_BSPAGE(va, hmeshift);
103*5d9d9091SRichard Lowe *	return (rehash | (bspage << HTAG_BSPAGE_SHIFT));
104*5d9d9091SRichard Lowe * }
105*5d9d9091SRichard Lowe */
106*5d9d9091SRichard Lowe
107*5d9d9091SRichard Lowe/*
108*5d9d9091SRichard Lowe * Parameters:	%g1: VA, %g3: rehash
109*5d9d9091SRichard Lowe * Scratch:	%g5, %g6 available
110*5d9d9091SRichard Lowe * Return:	hmeblk tag in %g5
111*5d9d9091SRichard Lowe */
112*5d9d9091SRichard Lowe
113*5d9d9091SRichard Lowe#define	KDI_HME_HASH_TAG \
114*5d9d9091SRichard Lowe	cmp	%g3, TTE8K;					\
115*5d9d9091SRichard Lowe	be,a	%xcc, bspage;					\
116*5d9d9091SRichard Lowe	mov	HBLK_RANGE_SHIFT, %g5;				\
117*5d9d9091SRichard Lowe	mulx	%g3, 3, %g5;					\
118*5d9d9091SRichard Lowe	add	%g5, MMU_PAGESHIFT, %g5;			\
119*5d9d9091SRichard Lowe								\
120*5d9d9091SRichard Lowebspage:	/* TTE_PAGE_SHIFT in %g5 */				\
121*5d9d9091SRichard Lowe	srlx	%g1, %g5, %g6;					\
122*5d9d9091SRichard Lowe	sub	%g5, MMU_PAGESHIFT, %g5;			\
123*5d9d9091SRichard Lowe	sllx	%g6, %g5, %g5;					\
124*5d9d9091SRichard Lowe								\
125*5d9d9091SRichard Lowe	/* BSPAGE in %g5 */					\
126*5d9d9091SRichard Lowe	sllx	%g5, HTAG_BSPAGE_SHIFT, %g5;			\
127*5d9d9091SRichard Lowe	sllx	%g3, HTAG_REHASH_SHIFT, %g6;			\
128*5d9d9091SRichard Lowe	or	%g6, SFMMU_INVALID_SHMERID, %g6;		\
129*5d9d9091SRichard Lowe	or	%g5, %g6, %g5
130*5d9d9091SRichard Lowe
131*5d9d9091SRichard Lowe/*
132*5d9d9091SRichard Lowe * uint64_t
133*5d9d9091SRichard Lowe * kdi_hme_hash_table_search(sfmmu_t *sfmmup, uint64_t hmebpa, uint64_t hblktag)
134*5d9d9091SRichard Lowe * {
135*5d9d9091SRichard Lowe *	struct hme_blk *hblkp;
136*5d9d9091SRichard Lowe *	uint64_t blkpap = hmebpa + HMEBP_HBLK;
137*5d9d9091SRichard Lowe *	uint64_t blkpa;
138*5d9d9091SRichard Lowe *
139*5d9d9091SRichard Lowe *	while ((blkpa = lddphys(blkpap)) != HMEBLK_ENDPA) {
140*5d9d9091SRichard Lowe *		if (lddphys(blkpa + HMEBLK_TAG) == hblktag) {
141*5d9d9091SRichard Lowe *			if ((sfmmu_t *)lddphys(blkpa + HMEBLK_TAG + 8) ==
142*5d9d9091SRichard Lowe *			    sfmmup)
143*5d9d9091SRichard Lowe *				return (blkpa);
144*5d9d9091SRichard Lowe *		}
145*5d9d9091SRichard Lowe *
146*5d9d9091SRichard Lowe *		blkpap = blkpa + HMEBLK_NEXTPA;
147*5d9d9091SRichard Lowe *	}
148*5d9d9091SRichard Lowe *
149*5d9d9091SRichard Lowe *	return (NULL);
150*5d9d9091SRichard Lowe * }
151*5d9d9091SRichard Lowe */
152*5d9d9091SRichard Lowe
153*5d9d9091SRichard Lowe/*
154*5d9d9091SRichard Lowe * Parameters:	%g2: sfmmup, %g4: hmebp PA, %g5: hmeblk tag
155*5d9d9091SRichard Lowe * Scratch:	%g4, %g5, %g6 available
156*5d9d9091SRichard Lowe * Return:	hmeblk PA in %g4
157*5d9d9091SRichard Lowe */
158*5d9d9091SRichard Lowe
159*5d9d9091SRichard Lowe#define	KDI_HME_HASH_TABLE_SEARCH \
160*5d9d9091SRichard Lowe	add	%g4, HMEBUCK_NEXTPA, %g4; /* %g4 is hmebucket PA */	\
161*5d9d9091SRichard Lowesearch_loop:								\
162*5d9d9091SRichard Lowe	ldxa	[%g4]ASI_MEM, %g4;					\
163*5d9d9091SRichard Lowe	cmp	%g4, HMEBLK_ENDPA;					\
164*5d9d9091SRichard Lowe	be,a,pn	%xcc, search_done;					\
165*5d9d9091SRichard Lowe	clr 	%g4;							\
166*5d9d9091SRichard Lowe									\
167*5d9d9091SRichard Lowe	add	%g4, HMEBLK_TAG, %g4;	/* %g4 is now hmeblk PA */	\
168*5d9d9091SRichard Lowe	ldxa	[%g4]ASI_MEM, %g6;					\
169*5d9d9091SRichard Lowe	sub	%g4, HMEBLK_TAG, %g4;					\
170*5d9d9091SRichard Lowe	cmp	%g5, %g6;						\
171*5d9d9091SRichard Lowe	bne,a	%xcc, search_loop;					\
172*5d9d9091SRichard Lowe	add	%g4, HMEBLK_NEXTPA, %g4;				\
173*5d9d9091SRichard Lowe									\
174*5d9d9091SRichard Lowe	/* Found a match.  Is it in the right address space? */		\
175*5d9d9091SRichard Lowe	add	%g4, (HMEBLK_TAG + 8), %g4;				\
176*5d9d9091SRichard Lowe	ldxa	[%g4]ASI_MEM, %g6;					\
177*5d9d9091SRichard Lowe	sub	%g4, (HMEBLK_TAG + 8), %g4;				\
178*5d9d9091SRichard Lowe	cmp	%g6, %g2;						\
179*5d9d9091SRichard Lowe	bne,a	%xcc, search_loop;					\
180*5d9d9091SRichard Lowe	add	%g4, HMEBLK_NEXTPA, %g4;				\
181*5d9d9091SRichard Lowe									\
182*5d9d9091SRichard Lowesearch_done:
183*5d9d9091SRichard Lowe
184*5d9d9091SRichard Lowe/*
185*5d9d9091SRichard Lowe * uint64_t
186*5d9d9091SRichard Lowe * kdi_hblk_to_ttep(uint64_t hmeblkpa, uintptr_t va)
187*5d9d9091SRichard Lowe * {
188*5d9d9091SRichard Lowe *	size_t ttesz = ldphys(hmeblkpa + HMEBLK_MISC) & HBLK_SZMASK;
189*5d9d9091SRichard Lowe *	uint_t idx;
190*5d9d9091SRichard Lowe *
191*5d9d9091SRichard Lowe *	if (ttesz == TTE8K)
192*5d9d9091SRichard Lowe *		idx = (va >> MMU_PAGESHIFT) & (NHMENTS - 1);
193*5d9d9091SRichard Lowe *	else
194*5d9d9091SRichard Lowe *		idx = 0;
195*5d9d9091SRichard Lowe *
196*5d9d9091SRichard Lowe *	return (hmeblkpa + (idx * sizeof (struct sf_hment)) +
197*5d9d9091SRichard Lowe *	    HMEBLK_HME + SFHME_TTE);
198*5d9d9091SRichard Lowe * }
199*5d9d9091SRichard Lowe */
200*5d9d9091SRichard Lowe
201*5d9d9091SRichard Lowe/*
202*5d9d9091SRichard Lowe * Parameters:	%g1: VA, %g4: hmeblk PA
203*5d9d9091SRichard Lowe * Scratch:	%g1, %g2, %g3, %g4, %g5, %g6 available
204*5d9d9091SRichard Lowe * Return:	TTE PA in %g2
205*5d9d9091SRichard Lowe */
206*5d9d9091SRichard Lowe
207*5d9d9091SRichard Lowe#define	KDI_HBLK_TO_TTEP \
208*5d9d9091SRichard Lowe	add	%g4, HMEBLK_MISC, %g3;				\
209*5d9d9091SRichard Lowe	lda	[%g3]ASI_MEM, %g3;				\
210*5d9d9091SRichard Lowe	and	%g3, HBLK_SZMASK, %g3;	/* ttesz in %g3 */	\
211*5d9d9091SRichard Lowe								\
212*5d9d9091SRichard Lowe	cmp	%g3, TTE8K;					\
213*5d9d9091SRichard Lowe	bne,a	ttep_calc;					\
214*5d9d9091SRichard Lowe	clr	%g1;						\
215*5d9d9091SRichard Lowe	srlx	%g1, MMU_PAGESHIFT, %g1;			\
216*5d9d9091SRichard Lowe	and	%g1, NHMENTS - 1, %g1;				\
217*5d9d9091SRichard Lowe								\
218*5d9d9091SRichard Lowettep_calc:	/* idx in %g1 */				\
219*5d9d9091SRichard Lowe	mulx	%g1, SFHME_SIZE, %g2;				\
220*5d9d9091SRichard Lowe	add	%g2, %g4, %g2;					\
221*5d9d9091SRichard Lowe	add	%g2, (HMEBLK_HME1 + SFHME_TTE), %g2;
222*5d9d9091SRichard Lowe
223*5d9d9091SRichard Lowe/*
224*5d9d9091SRichard Lowe * uint64_t
225*5d9d9091SRichard Lowe * kdi_vatotte(uintptr_t va, int cnum)
226*5d9d9091SRichard Lowe * {
227*5d9d9091SRichard Lowe *	sfmmu_t *sfmmup = ksfmmup;
228*5d9d9091SRichard Lowe *	uint64_t hmebpa, hmetag, hmeblkpa;
229*5d9d9091SRichard Lowe *	int i;
230*5d9d9091SRichard Lowe *
231*5d9d9091SRichard Lowe *	for (i = 1; i < DEFAULT_MAX_HASHCNT + 1; i++) {
232*5d9d9091SRichard Lowe *		hmebpa = kdi_c_hme_hash_function(sfmmup, va, HME_HASH_SHIFT(i));
233*5d9d9091SRichard Lowe *		hmetag = kdi_c_hme_hash_tag(i, va);
234*5d9d9091SRichard Lowe *		hmeblkpa = kdi_c_hme_hash_table_search(sfmmup, hmebpa, hmetag);
235*5d9d9091SRichard Lowe *
236*5d9d9091SRichard Lowe *		if (hmeblkpa != NULL) {
237*5d9d9091SRichard Lowe *			uint64_t tte = lddphys(kdi_c_hblk_to_ttep(hmeblkpa,
238*5d9d9091SRichard Lowe *			    va));
239*5d9d9091SRichard Lowe *
240*5d9d9091SRichard Lowe *			if ((int64_t)tte < 0)
241*5d9d9091SRichard Lowe *				return (tte);
242*5d9d9091SRichard Lowe *			else
243*5d9d9091SRichard Lowe *				return (0);
244*5d9d9091SRichard Lowe *		}
245*5d9d9091SRichard Lowe *	}
246*5d9d9091SRichard Lowe *
247*5d9d9091SRichard Lowe *	return (0);
248*5d9d9091SRichard Lowe * }
249*5d9d9091SRichard Lowe */
250*5d9d9091SRichard Lowe
251*5d9d9091SRichard Lowe	/*
252*5d9d9091SRichard Lowe	 * Invocation in normal context as a VA-to-TTE translator
253*5d9d9091SRichard Lowe	 * for kernel context only. This routine returns 0 on
254*5d9d9091SRichard Lowe	 * success and -1 on error.
255*5d9d9091SRichard Lowe	 *
256*5d9d9091SRichard Lowe	 * %o0 = VA, input register
257*5d9d9091SRichard Lowe	 * %o1 = KCONTEXT
258*5d9d9091SRichard Lowe	 * %o2 = ttep, output register
259*5d9d9091SRichard Lowe	 */
260*5d9d9091SRichard Lowe	ENTRY_NP(kdi_vatotte)
261*5d9d9091SRichard Lowe	mov	%o0, %g1		/* VA in %g1 */
262*5d9d9091SRichard Lowe	mov	%o1, %g2		/* cnum in %g2 */
263*5d9d9091SRichard Lowe
264*5d9d9091SRichard Lowe	set	kdi_trap_vatotte, %g3
265*5d9d9091SRichard Lowe	jmpl	%g3, %g7		/* => %g1: TTE or 0 */
266*5d9d9091SRichard Lowe	add	%g7, 8, %g7
267*5d9d9091SRichard Lowe
268*5d9d9091SRichard Lowe	brz	%g1, 1f
269*5d9d9091SRichard Lowe	nop
270*5d9d9091SRichard Lowe
271*5d9d9091SRichard Lowe	/* Got a valid TTE */
272*5d9d9091SRichard Lowe	stx	%g1, [%o2]
273*5d9d9091SRichard Lowe	retl
274*5d9d9091SRichard Lowe	clr	%o0
275*5d9d9091SRichard Lowe
276*5d9d9091SRichard Lowe	/* Failed translation */
277*5d9d9091SRichard Lowe1:	retl
278*5d9d9091SRichard Lowe	mov	-1, %o0
279*5d9d9091SRichard Lowe	SET_SIZE(kdi_vatotte)
280*5d9d9091SRichard Lowe
281*5d9d9091SRichard Lowe	/*
282*5d9d9091SRichard Lowe	 * %g1 = vaddr passed in, tte or 0 (error) when return
283*5d9d9091SRichard Lowe	 * %g2 = KCONTEXT
284*5d9d9091SRichard Lowe	 * %g7 = return address
285*5d9d9091SRichard Lowe	 */
286*5d9d9091SRichard Lowe	ENTRY_NP(kdi_trap_vatotte)
287*5d9d9091SRichard Lowe
288*5d9d9091SRichard Lowe	cmp	%g2, KCONTEXT		/* make sure called in kernel ctx */
289*5d9d9091SRichard Lowe	bne,a,pn %icc, 6f
290*5d9d9091SRichard Lowe	  clr	%g1
291*5d9d9091SRichard Lowe
292*5d9d9091SRichard Lowe	sethi   %hi(ksfmmup), %g2
293*5d9d9091SRichard Lowe        ldx     [%g2 + %lo(ksfmmup)], %g2
294*5d9d9091SRichard Lowe
295*5d9d9091SRichard Lowe	mov	1, %g3			/* VA %g1, ksfmmup %g2, idx %g3 */
296*5d9d9091SRichard Lowe	mov	HBLK_RANGE_SHIFT, %g4
297*5d9d9091SRichard Lowe	ba	3f
298*5d9d9091SRichard Lowe	nop
299*5d9d9091SRichard Lowe
300*5d9d9091SRichard Lowe1:	mulx	%g3, 3, %g4		/* 3: see TTE_BSZS_SHIFT */
301*5d9d9091SRichard Lowe	add	%g4, MMU_PAGESHIFT, %g4
302*5d9d9091SRichard Lowe
303*5d9d9091SRichard Lowe3:	KDI_HME_HASH_FUNCTION		/* %g1, %g2, %g4 => hash in %g4 */
304*5d9d9091SRichard Lowe	KDI_HME_HASH_TAG		/* %g1, %g3 => tag in %g5 */
305*5d9d9091SRichard Lowe	KDI_HME_HASH_TABLE_SEARCH	/* %g2, %g4, %g5 => hmeblk PA in %g4 */
306*5d9d9091SRichard Lowe
307*5d9d9091SRichard Lowe	brz	%g4, 5f
308*5d9d9091SRichard Lowe	nop
309*5d9d9091SRichard Lowe
310*5d9d9091SRichard Lowe	KDI_HBLK_TO_TTEP		/* %g1, %g4 => TTE PA in %g2 */
311*5d9d9091SRichard Lowe	ldxa	[%g2]ASI_MEM, %g1
312*5d9d9091SRichard Lowe	brgez,a	%g1, 4f
313*5d9d9091SRichard Lowe	clr	%g1
314*5d9d9091SRichard Lowe4:	ba,a	6f
315*5d9d9091SRichard Lowe
316*5d9d9091SRichard Lowe5:	add	%g3, 1, %g3
317*5d9d9091SRichard Lowe	set	mmu_hashcnt, %g4
318*5d9d9091SRichard Lowe	lduw	[%g4], %g4
319*5d9d9091SRichard Lowe	cmp	%g3, %g4
320*5d9d9091SRichard Lowe	ble	1b
321*5d9d9091SRichard Lowe	nop
322*5d9d9091SRichard Lowe
323*5d9d9091SRichard Lowe	clr	%g1
324*5d9d9091SRichard Lowe
325*5d9d9091SRichard Lowe6:	jmp	%g7
326*5d9d9091SRichard Lowe	nop
327*5d9d9091SRichard Lowe	SET_SIZE(kdi_trap_vatotte)
328*5d9d9091SRichard Lowe
329