1 |
1275 |
phoenix |
/* $Id: dtlb_base.S,v 1.1.1.1 2004-04-15 01:34:37 phoenix Exp $
|
2 |
|
|
* dtlb_base.S: Front end to DTLB 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 |
|
|
/* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS)
|
10 |
|
|
* %g2 (KERN_HIGHBITS | KERN_LOWBITS)
|
11 |
|
|
* %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space)
|
12 |
|
|
* (0xffe0000000000000) Cheetah (64-bit VA space)
|
13 |
|
|
* %g7 __pa(current->mm->pgd)
|
14 |
|
|
*
|
15 |
|
|
* The VPTE base value is completely magic, but note that
|
16 |
|
|
* few places in the kernel other than these TLB miss
|
17 |
|
|
* handlers know anything about the VPTE mechanism or
|
18 |
|
|
* how it works (see VPTE_SIZE, TASK_SIZE and PTRS_PER_PGD).
|
19 |
|
|
* Consider the 44-bit VADDR Ultra-I/II case as an example:
|
20 |
|
|
*
|
21 |
|
|
* VA[0 : (1<<43)] produce VPTE index [%g3 : 0]
|
22 |
|
|
* VA[0 : -(1<<43)] produce VPTE index [%g3-(1<<(43-PAGE_SHIFT+3)) : %g3]
|
23 |
|
|
*
|
24 |
|
|
* For Cheetah's 64-bit VADDR space this is:
|
25 |
|
|
*
|
26 |
|
|
* VA[0 : (1<<63)] produce VPTE index [%g3 : 0]
|
27 |
|
|
* VA[0 : -(1<<63)] produce VPTE index [%g3-(1<<(63-PAGE_SHIFT+3)) : %g3]
|
28 |
|
|
*
|
29 |
|
|
* If you're paying attention you'll notice that this means half of
|
30 |
|
|
* the VPTE table is above %g3 and half is below, low VA addresses
|
31 |
|
|
* map progressively upwards from %g3, and high VA addresses map
|
32 |
|
|
* progressively upwards towards %g3. This trick was needed to make
|
33 |
|
|
* the same 8 instruction handler work both for Spitfire/Blackbird's
|
34 |
|
|
* peculiar VA space hole configuration and the full 64-bit VA space
|
35 |
|
|
* one of Cheetah at the same time.
|
36 |
|
|
*/
|
37 |
|
|
|
38 |
|
|
/* Ways we can get here:
|
39 |
|
|
*
|
40 |
|
|
* 1) Nucleus loads and stores to/from PA-->VA direct mappings.
|
41 |
|
|
* 2) Nucleus loads and stores to/from vmalloc() areas.
|
42 |
|
|
* 3) User loads and stores.
|
43 |
|
|
* 4) User space accesses by nucleus at tl0
|
44 |
|
|
*/
|
45 |
|
|
|
46 |
|
|
#if PAGE_SHIFT == 13
|
47 |
|
|
/*
|
48 |
|
|
* To compute vpte offset, we need to do ((addr >> 13) << 3),
|
49 |
|
|
* which can be optimized to (addr >> 10) if bits 10/11/12 can
|
50 |
|
|
* be guaranteed to be 0 ... mmu_context.h does guarantee this
|
51 |
|
|
* by only using 10 bits in the hwcontext value.
|
52 |
|
|
*/
|
53 |
|
|
#define CREATE_VPTE_OFFSET1(r1, r2)
|
54 |
|
|
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
55 |
|
|
srax r1, 10, r2
|
56 |
|
|
#define CREATE_VPTE_NOP nop
|
57 |
|
|
#else
|
58 |
|
|
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
59 |
|
|
srax r1, PAGE_SHIFT, r2
|
60 |
|
|
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
61 |
|
|
sllx r2, 3, r2
|
62 |
|
|
#define CREATE_VPTE_NOP
|
63 |
|
|
#endif
|
64 |
|
|
|
65 |
|
|
/* DTLB ** ICACHE line 1: Quick user TLB misses */
|
66 |
|
|
ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
|
67 |
|
|
andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus?
|
68 |
|
|
mov 1, %g5 ! For TL==3 test
|
69 |
|
|
from_tl1_trap:
|
70 |
|
|
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
|
71 |
|
|
be,pn %xcc, 3f ! Yep, special processing
|
72 |
|
|
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
73 |
|
|
cmp %g5, 4 ! Last trap level?
|
74 |
|
|
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
|
75 |
|
|
nop ! delay slot
|
76 |
|
|
|
77 |
|
|
/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
|
78 |
|
|
ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
|
79 |
|
|
1: brgez,pn %g5, longpath ! Invalid, branch out
|
80 |
|
|
nop ! Delay-slot
|
81 |
|
|
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
82 |
|
|
retry ! Trap return
|
83 |
|
|
3: brlz,pt %g4, 9b ! Kernel virtual map?
|
84 |
|
|
xor %g2, %g4, %g5 ! Finish bit twiddles
|
85 |
|
|
ba,a,pt %xcc, kvmap ! Yep, go check for obp/vmalloc
|
86 |
|
|
|
87 |
|
|
/* DTLB ** ICACHE line 3: winfixups+real_faults */
|
88 |
|
|
longpath:
|
89 |
|
|
rdpr %pstate, %g5 ! Move into alternate globals
|
90 |
|
|
wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate
|
91 |
|
|
rdpr %tl, %g4 ! See where we came from.
|
92 |
|
|
cmp %g4, 1 ! Is etrap/rtrap window fault?
|
93 |
|
|
mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing
|
94 |
|
|
ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page
|
95 |
|
|
be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling
|
96 |
|
|
mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB
|
97 |
|
|
|
98 |
|
|
/* DTLB ** ICACHE line 4: Unused... */
|
99 |
|
|
ba,a,pt %xcc, winfix_trampoline ! Call window fixup code
|
100 |
|
|
nop
|
101 |
|
|
nop
|
102 |
|
|
nop
|
103 |
|
|
nop
|
104 |
|
|
nop
|
105 |
|
|
nop
|
106 |
|
|
CREATE_VPTE_NOP
|
107 |
|
|
|
108 |
|
|
#undef CREATE_VPTE_OFFSET1
|
109 |
|
|
#undef CREATE_VPTE_OFFSET2
|
110 |
|
|
#undef CREATE_VPTE_NOP
|