[SPARC64]: Kill pgtable quicklists and use SLAB.
[pandora-kernel.git] / arch / sparc64 / kernel / tsb.S
1 /* tsb.S: Sparc64 TSB table handling.
2  *
3  * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
4  */
5
6 #include <asm/tsb.h>
7
8         .text
9         .align  32
10
11         /* Invoked from TLB miss handler, we are in the
12          * MMU global registers and they are setup like
13          * this:
14          *
15          * %g1: TSB entry pointer
16          * %g2: available temporary
17          * %g3: FAULT_CODE_{D,I}TLB
18          * %g4: available temporary
19          * %g5: available temporary
20          * %g6: TAG TARGET
21          * %g7: physical address base of the linux page
22          *      tables for the current address space
23          */
24         .globl          tsb_miss_dtlb
25 tsb_miss_dtlb:
26         mov             TLB_TAG_ACCESS, %g4
27         ldxa            [%g4] ASI_DMMU, %g4
28         ba,pt           %xcc, tsb_miss_page_table_walk
29          nop
30
31         .globl          tsb_miss_itlb
32 tsb_miss_itlb:
33         mov             TLB_TAG_ACCESS, %g4
34         ldxa            [%g4] ASI_IMMU, %g4
35         ba,pt           %xcc, tsb_miss_page_table_walk
36          nop
37
38 tsb_miss_page_table_walk:
39         USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault)
40
41 tsb_reload:
42         TSB_LOCK_TAG(%g1, %g2, %g4)
43
44         /* Load and check PTE.  */
45         ldxa            [%g5] ASI_PHYS_USE_EC, %g5
46         brgez,a,pn      %g5, tsb_do_fault
47          stx            %g0, [%g1]
48
49         TSB_WRITE(%g1, %g5, %g6)
50
51         /* Finally, load TLB and return from trap.  */
52 tsb_tlb_reload:
53         cmp             %g3, FAULT_CODE_DTLB
54         bne,pn          %xcc, tsb_itlb_load
55          nop
56
57 tsb_dtlb_load:
58         stxa            %g5, [%g0] ASI_DTLB_DATA_IN
59         retry
60
61 tsb_itlb_load:
62         stxa            %g5, [%g0] ASI_ITLB_DATA_IN
63         retry
64
65         /* No valid entry in the page tables, do full fault
66          * processing.
67          */
68
69         .globl          tsb_do_fault
70 tsb_do_fault:
71         cmp             %g3, FAULT_CODE_DTLB
72         rdpr            %pstate, %g5
73         bne,pn          %xcc, tsb_do_itlb_fault
74          wrpr           %g5, PSTATE_AG | PSTATE_MG, %pstate
75
76 tsb_do_dtlb_fault:
77         rdpr    %tl, %g4
78         cmp     %g4, 1
79         mov     TLB_TAG_ACCESS, %g4
80         ldxa    [%g4] ASI_DMMU, %g5
81         be,pt   %xcc, sparc64_realfault_common
82          mov    FAULT_CODE_DTLB, %g4
83         ba,pt   %xcc, winfix_trampoline
84          nop
85
86 tsb_do_itlb_fault:
87         rdpr    %tpc, %g5
88         ba,pt   %xcc, sparc64_realfault_common
89          mov    FAULT_CODE_ITLB, %g4
90
91         .globl  sparc64_realfault_common
92 sparc64_realfault_common:
93         stb     %g4, [%g6 + TI_FAULT_CODE]      ! Save fault code
94         stx     %g5, [%g6 + TI_FAULT_ADDR]      ! Save fault address
95         ba,pt   %xcc, etrap                     ! Save trap state
96 1:       rd     %pc, %g7                        ! ...
97         call    do_sparc64_fault                ! Call fault handler
98          add    %sp, PTREGS_OFF, %o0            ! Compute pt_regs arg
99         ba,pt   %xcc, rtrap_clr_l6              ! Restore cpu state
100          nop                                    ! Delay slot (fill me)
101
102         .globl  winfix_trampoline
103 winfix_trampoline:
104         rdpr    %tpc, %g3                       ! Prepare winfixup TNPC
105         or      %g3, 0x7c, %g3                  ! Compute branch offset
106         wrpr    %g3, %tnpc                      ! Write it into TNPC
107         done                                    ! Trap return
108
109         /* Reload MMU related context switch state at
110          * schedule() time.
111          *
112          * %o0: page table physical address
113          * %o1: TSB address
114          */
115         .globl  tsb_context_switch
116 tsb_context_switch:
117         wrpr    %g0, PSTATE_MG | PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV, %pstate
118
119         /* Set page table base alternate global.  */
120         mov     %o0, %g7
121
122         /* XXX can this happen?  */
123         brz,pn  %o1, 9f
124          nop
125
126         /* Lock TSB into D-TLB.  */
127         sethi           %hi(PAGE_SIZE), %o3
128         and             %o3, %o1, %o3
129         sethi           %hi(TSBMAP_BASE), %o2
130         add             %o2, %o3, %o2
131
132         /* XXX handle PAGE_SIZE != 8K correctly...  */
133         mov     TSB_REG, %g1
134         stxa    %o2, [%g1] ASI_DMMU
135         membar  #Sync
136
137         stxa    %o2, [%g1] ASI_IMMU
138         membar  #Sync
139
140 #define KERN_HIGHBITS   ((_PAGE_VALID|_PAGE_SZBITS)^0xfffff80000000000)
141 #define KERN_LOWBITS    (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W | _PAGE_L)
142         sethi           %uhi(KERN_HIGHBITS), %g2
143         or              %g2, %ulo(KERN_HIGHBITS), %g2
144         sllx            %g2, 32, %g2
145         or              %g2, KERN_LOWBITS, %g2
146 #undef KERN_HIGHBITS
147 #undef KERN_LOWBITS
148
149         xor             %o1, %g2, %o1   
150
151         /* We use entry 61 for this locked entry.  This is the spitfire
152          * TLB entry number, and luckily cheetah masks the value with
153          * 15 ending us up with entry 13 which is what we want in that
154          * case too.
155          *
156          * XXX Interactions with prom_world()...
157          */
158         mov             TLB_TAG_ACCESS, %g1
159         stxa            %o2, [%g1] ASI_DMMU
160         membar          #Sync
161         mov             (61 << 3), %g1
162         stxa            %o1, [%g1] ASI_DTLB_DATA_ACCESS
163         membar          #Sync
164
165 9:
166         wrpr    %g0, PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE, %pstate
167
168         retl
169          mov    %o2, %o0