1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/asm_linkage.h>
30#include <sys/machasi.h>
31#include <sys/machtrap.h>
32#include <sys/privregs.h>
33#include <sys/mmu.h>
34#include <vm/mach_sfmmu.h>
35
36#if defined(sun4v) && !defined(lint)
37#include <sys/machparam.h>
38#endif
39
40#if defined(sun4v) && defined(KMDB_TRAPCOUNT)
41/*
42 * The sun4v implemenations of the fast miss handlers are larger than those
43 * of their sun4u kin. This is unfortunate because there is not enough space
44 * remaining in the respective trap table entries for this debug feature.
45 */
46#error "KMDB_TRAPCOUNT not supported on sun4v"
47#endif
48
49/*
50 * This file contains the trap handlers that will be copied to kmdb's trap
51 * table.  See kaif_activate.c for the code that does the actual copying.
52 *
53 * The handlers have a debugging feature, enabled when KMDB_TRAPCOUNT is
54 * defined, which allows them to keep a running count of the number of times
55 * a given trap has occurred.  The counter is stored in the padding at the end
56 * of the handler.  Write access is of course required to allow the values to
57 * be updated, so KMDB_TRAPCOUNT also enables the installation of DTLB entries
58 * for each trap table page.  Finally, the code in this file is copied into
59 * the actual location used by the handler, so we can't perform compile-time
60 * counter location calculations.  The calculations are instead performed at
61 * run-time, as A) we generally already derive the table location as part of
62 * the trap processing and B) simplicity is more of a concern than is speed.
63 */
64
65#if defined(lint)
66#include <kmdb/kaif.h>
67
68void
69kaif_hdlr_dmiss(void)
70{
71}
72
73void
74kaif_itlb_handler(void)
75{
76}
77
78#else /* lint */
79
80#ifdef sun4v
81
82#define	GET_MMU_D_ADDR_CTX(daddr, ctx)			\
83	MMU_FAULT_STATUS_AREA(ctx);			\
84	ldx	[ctx + MMFSA_D_ADDR], daddr;		\
85	ldx	[ctx + MMFSA_D_CTX], ctx
86
87#define	GET_MMU_I_ADDR_CTX(iaddr, ctx)			\
88	MMU_FAULT_STATUS_AREA(ctx);			\
89	ldx	[ctx + MMFSA_I_ADDR], iaddr;		\
90	ldx	[ctx + MMFSA_I_CTX], ctx
91
92/*
93 * KAIF_ITLB_STUFF
94 * derived from ITLB_STUFF in uts/sun4v/vm/mach_sfmmu.h
95 *
96 * Load ITLB entry
97 *
98 * In:
99 *   tte = reg containing tte
100 *   ouch = branch target label used if hcall fails (sun4v only)
101 *   scr1, scr2, scr3, scr4 = scratch registers (must not be %o0-%o3)
102 */
103#define	KAIF_ITLB_STUFF(tte, ouch, scr1, scr2, scr3, scr4)	\
104	mov	%o0, scr1;				\
105	mov	%o1, scr2;				\
106	mov	%o2, scr3;				\
107	mov	%o3, scr4;				\
108	MMU_FAULT_STATUS_AREA(%o2);			\
109	ldx	[%o2 + MMFSA_I_ADDR], %o0;		\
110	ldx	[%o2 + MMFSA_I_CTX], %o1;		\
111	srlx	%o0, PAGESHIFT, %o0;			\
112	sllx	%o0, PAGESHIFT, %o0;			\
113	mov	tte, %o2;				\
114	mov	MAP_ITLB, %o3;				\
115	ta	MMU_MAP_ADDR;				\
116	/* BEGIN CSTYLED */				\
117	brnz,a,pn %o0, ouch;				\
118	  nop;						\
119	/* END CSTYLED */				\
120	mov	scr1, %o0;				\
121	mov	scr2, %o1;				\
122	mov	scr3, %o2;				\
123	mov	scr4, %o3
124
125/*
126 * KAIF_DTLB_STUFF
127 * derived from DTLB_STUFF in uts/sun4v/vm/mach_sfmmu.h
128 *
129 * Load DTLB entry
130 *
131 * In:
132 *   tte = reg containing tte
133 *   ouch = branch target label used if hcall fails (sun4v only)
134 *   scr1, scr2, scr3, scr4 = scratch registers (must not be %o0-%o3)
135 */
136#define	KAIF_DTLB_STUFF(tte, ouch, scr1, scr2, scr3, scr4)	\
137	mov	%o0, scr1;				\
138	mov	%o1, scr2;				\
139	mov	%o2, scr3;				\
140	mov	%o3, scr4;				\
141	MMU_FAULT_STATUS_AREA(%o2);			\
142	ldx	[%o2 + MMFSA_D_ADDR], %o0;		\
143	ldx	[%o2 + MMFSA_D_CTX], %o1;		\
144	srlx	%o0, PAGESHIFT, %o0;			\
145	sllx	%o0, PAGESHIFT, %o0;			\
146	mov	tte, %o2;				\
147	mov	MAP_DTLB, %o3;				\
148	ta	MMU_MAP_ADDR;				\
149	/* BEGIN CSTYLED */				\
150	brnz,a,pn %o0, ouch;				\
151	  nop;						\
152	/* END CSTYLED */				\
153	mov	scr1, %o0;				\
154	mov	scr2, %o1;				\
155	mov	scr3, %o2;				\
156	mov	scr4, %o3
157
158#else /* sun4v */
159
160#define	GET_MMU_D_ADDR_CTX(daddr, ctx)			\
161	mov	MMU_TAG_ACCESS, ctx;			\
162	ldxa	[ctx]ASI_DMMU, daddr;			\
163	sllx	daddr, TAGACC_CTX_LSHIFT, ctx;		\
164	srlx	ctx, TAGACC_CTX_LSHIFT, ctx
165
166#define	GET_MMU_I_ADDR_CTX(iaddr, ctx)			\
167	rdpr	%tpc, iaddr;				\
168	ldxa	[%g0]ASI_IMMU, ctx;			\
169	srlx	ctx, TTARGET_CTX_SHIFT, ctx
170
171#define	KAIF_DTLB_STUFF(tte, ouch, scr1, scr2, scr3, scr4)	\
172	DTLB_STUFF(tte, scr1, scr2, scr3, scr4)
173
174#define	KAIF_ITLB_STUFF(tte, ouch, scr1, scr2, scr3, scr4)	\
175	ITLB_STUFF(tte, scr1, scr2, scr3, scr4)
176
177#endif /* sun4v */
178
179/*
180 * KAIF_CALL_KDI_VATOTTE
181 *
182 * Use kdi_vatotte to look up the tte.  We don't bother stripping the
183 * context, as it won't change the tte we get.
184 *
185 * The two instruction at patch_lbl are modified during runtime
186 * by kaif to point to kdi_vatotte
187 *
188 * Clobbers all globals.
189 * Returns tte in %g1 if successful, otherwise 0 in %g1
190 * Leaves address of next instruction following this macro in scr1
191 */
192#define	KAIF_CALL_KDI_VATOTTE(addr, ctx, patch_lbl, scr0, scr1)	\
193	.global	patch_lbl;					\
194patch_lbl:							\
195	sethi	%hi(0), scr0;					\
196	or	scr0, %lo(0), scr0;				\
197	jmpl	scr0, scr1;					\
198	add	scr1, 8, scr1
199
200
201	ENTRY_NP(kaif_hdlr_dmiss)
202	GET_MMU_D_ADDR_CTX(%g1, %g2)
203
204	KAIF_CALL_KDI_VATOTTE(%g1, %g2, kaif_hdlr_dmiss_patch, %g3, %g7)
2050:	brz	%g1, 1f
206	nop
207
208	/*
209	 * kdi_vatotte gave us a TTE to use.  Load it up and head back
210	 * into the world, but first bump a counter.
211	 */
212
213#ifdef	KMDB_TRAPCOUNT			/* Trap counter.  See top comment */
214	ldx	[%g7 + .count-0b], %g2
215	add	%g2, 1, %g2
216	stx	%g2, [%g7 + .count-0b]
217#endif
218
219	KAIF_DTLB_STUFF(%g1, 1f, %g2, %g3, %g4, %g5)
220	retry
221
2221:	/*
223	 * kdi_vatotte didn't give us a tte, which is unfortunate.  We're
224	 * going to need to jump into the debugger so as to allow it to
225	 * handle the trap.  The debugger itself isn't locked into the TLB,
226	 * so we may well incur a TLB miss while trying to get into it.  As
227	 * such, we're going to switch off the MMU globals before setting foot
228	 * into the debugger, thus allowing a TL>1 miss to be handled without
229	 * clobbering our state.  We'll also save off the tag just in case the
230	 * world ends and someone wants to find out what happened.
231	 *
232	 * We will only reach this point at TL=1, as kdi_vatotte will always
233	 * find the TTE for the debugger without missing.
234	 */
235
236#ifdef	KMDB_TRAPCOUNT			/* Trap address "counter". */
237	GET_MMU_D_ADDR(%g2, %g3)
238	stx	%g2, [%g7 + .daddr-0b]
239	stx	%g1, [%g7 + .ecode-0b]
240#endif
241
242	sethi	%hi(kaif_dtrap), %g1
243	jmp	%g1 + %lo(kaif_dtrap)
244	nop
245	/* NOTREACHED */
246
247#ifdef KMDB_TRAPCOUNT
248	.align 8
249.count:	.xword 0			/* counter goes here */
250.daddr:	.xword 0			/* miss address goes here */
251.ecode:	.xword 0			/* sun4v: g1 contains err code */
252#endif
253
254	.align 32*4			/* force length to 32 instr. */
255	SET_SIZE(kaif_hdlr_dmiss)
256
257
258
259	ENTRY_NP(kaif_hdlr_imiss)
260	GET_MMU_I_ADDR_CTX(%g1, %g2)
261
262	KAIF_CALL_KDI_VATOTTE(%g1, %g2, kaif_hdlr_imiss_patch, %g3, %g7)
2630:	brz	%g1, 1f
264	nop
265
266	/*
267	 * kdi_vatotte gave us a TTE to use.  Load it up and head back
268	 * into the world, but first bump a counter.
269	 */
270#ifdef	KMDB_TRAPCOUNT			/* Trap counter.  See top comment */
271	ldx	[%g7 + .count-0b], %g2
272	add	%g2, 1, %g2
273	stx	%g2, [%g7 + .count-0b]
274#endif
275
276	KAIF_ITLB_STUFF(%g1, 1f, %g2, %g3, %g4, %g5)
277	retry
278
2791:	/*
280	 * kdi_vatotte didn't give us a tte, which is unfortunate.  We're
281	 * going to need to jump into the debugger so as to allow it to
282	 * handle the trap.  The debugger itself isn't locked into the TLB,
283	 * so we may well incur a TLB miss while trying to get into it.  As
284	 * such, we're going to switch off the MMU globals before setting foot
285	 * into the debugger, thus allowing a TL>1 miss to be handled without
286	 * clobbering our state.
287	 *
288	 * We will only reach this point at TL=1, as kdi_vatotte will always
289	 * find the TTE for the debugger without missing.
290	 */
291
292	sethi	%hi(kaif_dtrap), %g1
293	jmp	%g1 + %lo(kaif_dtrap)
294	nop
295	/* NOTREACHED */
296
297#ifdef KMDB_TRAPCOUNT
298	.align	8
299.count:	.xword	0
300#endif
301
302	.align	32*4			/* force length to 32 instr. */
303	SET_SIZE(kaif_hdlr_imiss)
304
305
306
307	ENTRY_NP(kaif_hdlr_generic)
308#ifdef	KMDB_TRAPCOUNT			/* Trap counter.  See top comment */
3090:	rd	%pc, %g3
310	ldx	[%g3 + .count-0b], %g4
311	add	%g4, 1, %g4
312	stx	%g4, [%g3 + .count-0b]
313#endif
314
315	sethi	%hi(kaif_dtrap), %g1
316	jmp	%g1 + %lo(kaif_dtrap)
317	nop
318	/* NOTREACHED */
319
320#ifdef	KMDB_TRAPCOUNT
321	.align	8
322.count:	.xword	0			/* counter goes here */
323#endif
324
325	.align	32*4			/* force length to 32 instr. */
326	SET_SIZE(kaif_hdlr_generic)
327
328#endif /* lint */
329