1/* $Id: itlb_base.S,v 1.11 2001/08/17 04:55:09 kanoj Exp $
2 * itlb_base.S:	Front end to ITLB miss replacement strategy.
3 *              This is included directly into the trap table.
4 *
5 * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
6 * Copyright (C) 1997,1998 Jakub Jelinek   (jj@ultra.linux.cz)
7 */
8
9#if PAGE_SHIFT == 13
10/*
11 * To compute vpte offset, we need to do ((addr >> 13) << 3),
12 * which can be optimized to (addr >> 10) if bits 10/11/12 can
13 * be guaranteed to be 0 ... mmu_context.h does guarantee this
14 * by only using 10 bits in the hwcontext value.
15 */
16#define CREATE_VPTE_OFFSET1(r1, r2) \
17				srax	r1, 10, r2
18#define CREATE_VPTE_OFFSET2(r1, r2)
19#define CREATE_VPTE_NOP		nop
20#else /* PAGE_SHIFT */
21#define CREATE_VPTE_OFFSET1(r1, r2) \
22				srax	r1, PAGE_SHIFT, r2
23#define CREATE_VPTE_OFFSET2(r1, r2) \
24				sllx	r2, 3, r2
25#define CREATE_VPTE_NOP
26#endif /* PAGE_SHIFT */
27
28
29/* Ways we can get here:
30 *
31 * 1) Nucleus instruction misses from module code.
32 * 2) All user instruction misses.
33 *
34 * All real page faults merge their code paths to the
35 * sparc64_realfault_common label below.
36 */
37
38/* ITLB ** ICACHE line 1: Quick user TLB misses		*/
39	ldxa		[%g1 + %g1] ASI_IMMU, %g4	! Get TAG_ACCESS
40	CREATE_VPTE_OFFSET1(%g4, %g6)			! Create VPTE offset
41	CREATE_VPTE_OFFSET2(%g4, %g6)			! Create VPTE offset
42	ldxa		[%g3 + %g6] ASI_P, %g5		! Load VPTE
431:	brgez,pn	%g5, 3f				! Not valid, branch out
44	 sethi		%hi(_PAGE_EXEC), %g4		! Delay-slot
45	andcc		%g5, %g4, %g0			! Executable?
46	be,pn		%xcc, 3f			! Nope, branch.
47	 nop						! Delay-slot
482:	stxa		%g5, [%g0] ASI_ITLB_DATA_IN	! Load PTE into TLB
49	retry						! Trap return
503:	rdpr		%pstate, %g4			! Move into alternate globals
51
52/* ITLB ** ICACHE line 2: Real faults			*/
53	wrpr		%g4, PSTATE_AG|PSTATE_MG, %pstate
54	rdpr		%tpc, %g5			! And load faulting VA
55	mov		FAULT_CODE_ITLB, %g4		! It was read from ITLB
56sparc64_realfault_common:				! Called by TL0 dtlb_miss too
57	stb		%g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code]
58	stx		%g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address]
59	ba,pt		%xcc, etrap			! Save state
601:	 rd		%pc, %g7			! ...
61	nop
62
63/* ITLB ** ICACHE line 3: Finish faults + window fixups	*/
64	call		do_sparc64_fault		! Call fault handler
65	 add		%sp, PTREGS_OFF, %o0		! Compute pt_regs arg
66	ba,pt		%xcc, rtrap_clr_l6		! Restore cpu state
67	 nop
68winfix_trampoline:
69	rdpr		%tpc, %g3			! Prepare winfixup TNPC
70	or		%g3, 0x7c, %g3			! Compute offset to branch
71	wrpr		%g3, %tnpc			! Write it into TNPC
72	done						! Do it to it
73
74/* ITLB ** ICACHE line 4: Unused...	*/
75	nop
76	nop
77	nop
78	nop
79	CREATE_VPTE_NOP
80
81#undef CREATE_VPTE_OFFSET1
82#undef CREATE_VPTE_OFFSET2
83#undef CREATE_VPTE_NOP
84