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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * SFMMU primitives. These primitives should only be used by sfmmu
33 #include <sys/asm_linkage.h>
34 #include <sys/machtrap.h>
35 #include <sys/machasi.h>
36 #include <sys/sun4asi.h>
39 #include <vm/hat_sfmmu.h>
40 #include <vm/seg_spt.h>
41 #include <sys/machparam.h>
42 #include <sys/privregs.h>
44 #include <sys/intreg.h>
45 #include <sys/machthread.h>
46 #include <sys/clock.h>
47 #include <sys/trapstat.h>
50 * sfmmu related subroutines
55 * Invalidate either the context of a specific victim or any process
56 * currently running on this CPU.
58 * %g1 = sfmmup whose ctx is being stolen (victim)
59 * when called from sfmmu_wrap_around, %g1 == INVALID_CONTEXT.
60 * Note %g1 is the only input argument used by this xcall handler.
63 ENTRY
(sfmmu_raise_tsb_exception
)
65 ! if
(victim
== INVALID_CONTEXT
) {
66 ! if
(sec-ctx
> INVALID_CONTEXT
)
67 ! write INVALID_CONTEXT to sec-ctx
68 ! if
(pri-ctx
> INVALID_CONTEXT
)
69 ! write INVALID_CONTEXT to pri-ctx
71 ! } else if
(current CPU tsbmiss-
>usfmmup
!= victim sfmmup
) {
74 ! if
(sec-ctx
> INVALID_CONTEXT
)
75 ! write INVALID_CONTEXT to sec-ctx
77 ! if
(pri-ctx
> INVALID_CONTEXT
)
78 ! write INVALID_CONTEXT to pri-ctx
82 sethi
%hi
(ksfmmup
), %g3
83 ldx [%g3
+ %lo
(ksfmmup
)], %g3
85 be,a,pn
%xcc
, ptl1_panic
/* can't invalidate kernel ctx */
86 mov PTL1_BAD_RAISE_TSBEXCP
, %g1
88 set INVALID_CONTEXT
, %g2
90 cmp %g1
, INVALID_CONTEXT
91 bne,pt
%xcc
, 1f
/* called from wrap_around? */
94 ldxa
[%g3
]ASI_MMU_CTX
, %g5
/* %g5 = sec-ctx */
95 cmp %g5
, INVALID_CONTEXT
/* kernel or invalid ctx ? */
96 ble,pn
%xcc
, 0f
/* yes, no need to change */
99 stxa
%g2
, [%g3
]ASI_MMU_CTX
/* set invalid ctx */
103 ldxa
[%g7
]ASI_MMU_CTX
, %g5
/* %g5 = pri-ctx */
104 cmp %g5
, INVALID_CONTEXT
/* kernel or invalid ctx? */
105 ble,pn
%xcc
, 6f
/* yes, no need to change */
108 stxa
%g2
, [%g7
]ASI_MMU_CTX
/* set pri-ctx to invalid */
111 6: /* flushall tlb */
117 mov
%g0
, %o0
! XXX no cpu list yet
118 mov
%g0
, %o1
! XXX no cpu list yet
119 mov MAP_ITLB | MAP_DTLB
, %o2
120 mov MMU_DEMAP_ALL
, %o5
124 ba ptl1_panic
/* bad HV call */
125 mov PTL1_BAD_RAISE_TSBEXCP
, %g1
137 * %g2 = INVALID_CONTEXT
140 CPU_TSBMISS_AREA
(%g5
, %g6
) /* load cpu tsbmiss area */
141 ldx [%g5
+ TSBMISS_UHATID
], %g5
/* load usfmmup */
143 cmp %g5
, %g1
/* is it the victim? */
144 bne,pt
%xcc
, 2f
/* is our sec-ctx a victim? */
147 ldxa
[%g3
]ASI_MMU_CTX
, %g5
/* %g5 = sec-ctx */
148 cmp %g5
, INVALID_CONTEXT
/* kernel or invalid ctx ? */
149 ble,pn
%xcc
, 0f
/* yes, no need to change */
150 mov MMU_PCONTEXT
, %g7
152 stxa
%g2
, [%g3
]ASI_MMU_CTX
/* set sec-ctx to invalid */
156 ldxa
[%g7
]ASI_MMU_CTX
, %g4
/* %g4 = pri-ctx */
157 cmp %g4
, INVALID_CONTEXT
/* is pri-ctx the victim? */
158 ble %icc
, 3f
/* no need to change pri-ctx */
160 stxa
%g2
, [%g7
]ASI_MMU_CTX
/* set pri-ctx to invalid */
164 /* TSB program must be cleared - walkers do not check a context. */
170 mov MMU_TSB_CTXNON0
, %o5
172 brnz
,a,pn
%o0
, ptl1_panic
173 mov PTL1_BAD_HCALL
, %g1
179 SET_SIZE
(sfmmu_raise_tsb_exception
)
181 ENTRY_NP
(sfmmu_getctx_pri
)
182 set MMU_PCONTEXT
, %o0
184 ldxa
[%o0
]ASI_MMU_CTX
, %o0
185 SET_SIZE
(sfmmu_getctx_pri
)
187 ENTRY_NP
(sfmmu_getctx_sec
)
188 set MMU_SCONTEXT
, %o0
190 ldxa
[%o0
]ASI_MMU_CTX
, %o0
191 SET_SIZE
(sfmmu_getctx_sec
)
194 * Set the secondary context register for this process.
195 * %o0 = context number
197 ENTRY_NP
(sfmmu_setctx_sec
)
199 * From resume we call sfmmu_setctx_sec with interrupts disabled.
200 * But we can also get called from C with interrupts enabled. So,
201 * we need to check first.
204 /* If interrupts are not disabled, then disable them */
208 wrpr
%g1
, PSTATE_IE
, %pstate
/* disable interrupts */
210 mov MMU_SCONTEXT
, %o1
211 stxa
%o0
, [%o1
]ASI_MMU_CTX
/* set 2nd context reg. */
214 * if the routine is entered with intr enabled, then enable intr now.
215 * otherwise, keep intr disabled, return without enabing intr.
216 * %g1 - old intr state
220 wrpr
%g0
, %g1
, %pstate
/* enable interrupts */
223 SET_SIZE
(sfmmu_setctx_sec
)
226 * set ktsb_phys to 1 if the processor supports ASI_QUAD_LDD_PHYS.
227 * returns the detection value in %o0.
229 ENTRY_NP
(sfmmu_setup_4lp
)
235 SET_SIZE
(sfmmu_setup_4lp
)
238 * Called to load MMU registers and tsbmiss area
239 * for the active process. This function should
240 * only be called from TL=0.
244 ENTRY_NP
(sfmmu_load_mmustate
)
247 PANIC_IF_INTR_ENABLED_PSTR
(msfmmu_ei_l1
, %g1
)
250 sethi
%hi
(ksfmmup
), %o3
251 ldx [%o3
+ %lo
(ksfmmup
)], %o3
253 be,pn
%xcc
, 7f
! if kernel as
, do nothing
256 set MMU_SCONTEXT
, %o3
257 ldxa
[%o3
]ASI_MMU_CTX
, %o5
259 cmp %o5
, INVALID_CONTEXT
! ctx is invalid?
263 CPU_TSBMISS_AREA
(%o2
, %o3
) ! %o2
= tsbmiss area
264 stx %o0
, [%o2
+ TSBMISS_UHATID
]
265 stx %g0
, [%o2
+ TSBMISS_SHARED_UHATID
]
267 /* check if hypervisor/hardware should handle user TSB */
268 sethi
%hi
(hv_use_non0_tsb
), %o2
269 ld [%o2
+ %lo
(hv_use_non0_tsb
)], %o2
273 clr
%o0
! ntsb
= 0 for invalid ctx
274 clr
%o1
! HV_TSB_INFO_PA
= 0 if inv ctx
275 mov MMU_TSB_CTXNON0
, %o5
276 ta FAST_TRAP
! set TSB info for user process
277 brnz
,a,pn
%o0
, panic_bad_hcall
278 mov MMU_TSB_CTXNON0
, %o1
284 * We need to set up the TSB base register, tsbmiss
285 * area, and pass the TSB information into the hypervisor
287 ldx [%o0
+ SFMMU_TSB
], %o1
! %o1
= first tsbinfo
288 ldx [%o1
+ TSBINFO_NEXTPTR
], %g2
! %g2
= second tsbinfo
290 /* create/set first UTSBREG */
291 MAKE_UTSBREG
(%o1
, %o2
, %o3
) ! %o2
= user tsbreg
292 SET_UTSBREG
(SCRATCHPAD_UTSBREG1
, %o2
, %o3
)
295 mov
-1, %o2
! use
-1 if no second TSB
297 /* make 2nd UTSBREG */
298 MAKE_UTSBREG
(%g2
, %o2
, %o3
) ! %o2
= user tsbreg
300 SET_UTSBREG
(SCRATCHPAD_UTSBREG2
, %o2
, %o3
)
302 /* make 3rd and 4th TSB */
303 CPU_TSBMISS_AREA
(%o4
, %o3
) ! %o4
= tsbmiss area
305 ldx [%o0
+ SFMMU_SCDP
], %g2
! %g2
= sfmmu_scd
307 mov
-1, %o2
! use
-1 if no third TSB
309 ldx [%g2
+ SCD_SFMMUP
], %g3
! %g3
= scdp-
>scd_sfmmup
310 ldx [%g3
+ SFMMU_TSB
], %o1
! %o1
= first scd tsbinfo
312 nop ! panic if no third TSB
314 /* make 3rd UTSBREG */
315 MAKE_UTSBREG
(%o1
, %o2
, %o3
) ! %o2
= user tsbreg
317 SET_UTSBREG_SHCTX
(%o4
, TSBMISS_TSBSCDPTR
, %o2
)
320 mov
-1, %o2
! use
-1 if no
3rd
or 4th TSB
323 mov
-1, %o2
! use
-1 if no
3rd
or 4th TSB
324 ldx [%o1
+ TSBINFO_NEXTPTR
], %g2
! %g2
= second scd tsbinfo
326 mov
-1, %o2
! use
-1 if no
4th TSB
328 /* make 4th UTSBREG */
329 MAKE_UTSBREG
(%g2
, %o2
, %o3
) ! %o2
= user tsbreg
331 SET_UTSBREG_SHCTX
(%o4
, TSBMISS_TSBSCDPTR4M
, %o2
)
334 /* check if hypervisor/hardware should handle user TSB */
335 sethi
%hi
(hv_use_non0_tsb
), %o2
336 ld [%o2
+ %lo
(hv_use_non0_tsb
)], %o2
340 CPU_ADDR
(%o2
, %o4
) ! load CPU struct addr to
%o2 using
%o4
341 ldub
[%o2
+ CPU_TSTAT_FLAGS
], %o1
! load cpu_tstat_flag to
%o1
343 mov
%o0
, %o3
! preserve
%o0
344 btst TSTAT_TLB_STATS
, %o1
345 bnz
,a,pn
%icc
, 5f
! ntsb
= 0 if TLB stats enabled
348 ldx [%o3
+ SFMMU_HVBLOCK
+ HV_TSB_INFO_CNT
], %o0
350 ldx [%o3
+ SFMMU_HVBLOCK
+ HV_TSB_INFO_PA
], %o1
351 mov MMU_TSB_CTXNON0
, %o5
352 ta FAST_TRAP
! set TSB info for user process
353 brnz
,a,pn
%o0
, panic_bad_hcall
354 mov MMU_TSB_CTXNON0
, %o1
355 mov
%o3
, %o0
! restore
%o0
357 ldx [%o0
+ SFMMU_ISMBLKPA
], %o1
! copy members of sfmmu
358 CPU_TSBMISS_AREA
(%o2
, %o3
) ! %o2
= tsbmiss area
359 stx %o1
, [%o2
+ TSBMISS_ISMBLKPA
] ! sfmmu_tsb_miss into the
360 ldub
[%o0
+ SFMMU_TTEFLAGS
], %o3
! per-CPU tsbmiss area.
361 ldub
[%o0
+ SFMMU_RTTEFLAGS
], %o4
362 ldx [%o0
+ SFMMU_SRDP
], %o1
363 stx %o0
, [%o2
+ TSBMISS_UHATID
]
364 stub
%o3
, [%o2
+ TSBMISS_UTTEFLAGS
]
365 stub
%o4
, [%o2
+ TSBMISS_URTTEFLAGS
]
366 stx %o1
, [%o2
+ TSBMISS_SHARED_UHATID
]
367 brz
,pn
%o1
, 7f
! check for sfmmu_srdp
368 add %o0
, SFMMU_HMERMAP
, %o1
369 add %o2
, TSBMISS_SHMERMAP
, %o2
370 mov SFMMU_HMERGNMAP_WORDS
, %o3
371 ! set tsbmiss shmermap
372 SET_REGION_MAP
(%o1
, %o2
, %o3
, %o4
, load_shme_mmustate
)
374 ldx [%o0
+ SFMMU_SCDP
], %o4
! %o4
= sfmmu_scd
375 CPU_TSBMISS_AREA
(%o2
, %o3
) ! %o2
= tsbmiss area
376 mov SFMMU_HMERGNMAP_WORDS
, %o3
377 brnz
,pt
%o4
, 8f
! check for sfmmu_scdp else
378 add %o2
, TSBMISS_SCDSHMERMAP
, %o2
! zero tsbmiss scd_shmermap
379 ZERO_REGION_MAP
(%o2
, %o3
, zero_scd_mmustate
)
383 8: ! set tsbmiss scd_shmermap
384 add %o4
, SCD_HMERMAP
, %o1
385 SET_REGION_MAP
(%o1
, %o2
, %o3
, %o4
, load_scd_mmustate
)
389 sethi
%hi
(panicstr
), %g1
! panic if no
3rd TSB
390 ldx [%g1
+ %lo
(panicstr
)], %g1
396 sethi
%hi
(sfmmu_panic10
), %o0
398 or %o0
, %lo
(sfmmu_panic10
), %o0
400 SET_SIZE
(sfmmu_load_mmustate
)
404 ENTRY
(prefetch_tsbe_read
)
407 SET_SIZE
(prefetch_tsbe_read
)
409 ENTRY
(prefetch_tsbe_write
)
412 SET_SIZE
(prefetch_tsbe_write
)