Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* tlb-flush.S: TLB flushing routines |
2 | * | |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
12 | #include <linux/sys.h> | |
1da177e4 LT |
13 | #include <linux/linkage.h> |
14 | #include <asm/page.h> | |
15 | #include <asm/ptrace.h> | |
16 | #include <asm/spr-regs.h> | |
17 | ||
18 | .macro DEBUG ch | |
19 | # sethi.p %hi(0xfeff9c00),gr4 | |
20 | # setlo %lo(0xfeff9c00),gr4 | |
21 | # setlos #\ch,gr5 | |
22 | # stbi gr5,@(gr4,#0) | |
23 | # membar | |
24 | .endm | |
25 | ||
26 | .section .rodata | |
27 | ||
28 | # sizes corresponding to TPXR.LMAX | |
29 | .balign 1 | |
30 | __tlb_lmax_sizes: | |
31 | .byte 0, 64, 0, 0 | |
32 | .byte 0, 0, 0, 0 | |
33 | .byte 0, 0, 0, 0 | |
34 | .byte 0, 0, 0, 0 | |
35 | ||
36 | .section .text | |
37 | .balign 4 | |
38 | ||
39 | ############################################################################### | |
40 | # | |
41 | # flush everything | |
42 | # - void __flush_tlb_all(void) | |
43 | # | |
44 | ############################################################################### | |
45 | .globl __flush_tlb_all | |
46 | .type __flush_tlb_all,@function | |
47 | __flush_tlb_all: | |
48 | DEBUG 'A' | |
49 | ||
50 | # kill cached PGE value | |
51 | setlos #0xffffffff,gr4 | |
52 | movgs gr4,scr0 | |
53 | movgs gr4,scr1 | |
54 | ||
55 | # kill AMPR-cached TLB values | |
56 | movgs gr0,iamlr1 | |
57 | movgs gr0,iampr1 | |
58 | movgs gr0,damlr1 | |
59 | movgs gr0,dampr1 | |
60 | ||
61 | # find out how many lines there are | |
62 | movsg tpxr,gr5 | |
63 | sethi.p %hi(__tlb_lmax_sizes),gr4 | |
64 | srli gr5,#TPXR_LMAX_SHIFT,gr5 | |
65 | setlo.p %lo(__tlb_lmax_sizes),gr4 | |
66 | andi gr5,#TPXR_LMAX_SMASK,gr5 | |
67 | ldub @(gr4,gr5),gr4 | |
68 | ||
69 | # now, we assume that the TLB line step is page size in size | |
70 | setlos.p #PAGE_SIZE,gr5 | |
71 | setlos #0,gr6 | |
72 | 1: | |
73 | tlbpr gr6,gr0,#6,#0 | |
74 | subicc.p gr4,#1,gr4,icc0 | |
75 | add gr6,gr5,gr6 | |
76 | bne icc0,#2,1b | |
77 | ||
78 | DEBUG 'B' | |
79 | bralr | |
80 | ||
81 | .size __flush_tlb_all, .-__flush_tlb_all | |
82 | ||
83 | ############################################################################### | |
84 | # | |
85 | # flush everything to do with one context | |
86 | # - void __flush_tlb_mm(unsigned long contextid [GR8]) | |
87 | # | |
88 | ############################################################################### | |
89 | .globl __flush_tlb_mm | |
90 | .type __flush_tlb_mm,@function | |
91 | __flush_tlb_mm: | |
92 | DEBUG 'M' | |
93 | ||
94 | # kill cached PGE value | |
95 | setlos #0xffffffff,gr4 | |
96 | movgs gr4,scr0 | |
97 | movgs gr4,scr1 | |
98 | ||
99 | # specify the context we want to flush | |
100 | movgs gr8,tplr | |
101 | ||
102 | # find out how many lines there are | |
103 | movsg tpxr,gr5 | |
104 | sethi.p %hi(__tlb_lmax_sizes),gr4 | |
105 | srli gr5,#TPXR_LMAX_SHIFT,gr5 | |
106 | setlo.p %lo(__tlb_lmax_sizes),gr4 | |
107 | andi gr5,#TPXR_LMAX_SMASK,gr5 | |
108 | ldub @(gr4,gr5),gr4 | |
109 | ||
110 | # now, we assume that the TLB line step is page size in size | |
111 | setlos.p #PAGE_SIZE,gr5 | |
112 | setlos #0,gr6 | |
113 | 0: | |
114 | tlbpr gr6,gr0,#5,#0 | |
115 | subicc.p gr4,#1,gr4,icc0 | |
116 | add gr6,gr5,gr6 | |
117 | bne icc0,#2,0b | |
118 | ||
119 | DEBUG 'N' | |
120 | bralr | |
121 | ||
122 | .size __flush_tlb_mm, .-__flush_tlb_mm | |
123 | ||
124 | ############################################################################### | |
125 | # | |
126 | # flush a range of addresses from the TLB | |
127 | # - void __flush_tlb_page(unsigned long contextid [GR8], | |
128 | # unsigned long start [GR9]) | |
129 | # | |
130 | ############################################################################### | |
131 | .globl __flush_tlb_page | |
132 | .type __flush_tlb_page,@function | |
133 | __flush_tlb_page: | |
134 | # kill cached PGE value | |
135 | setlos #0xffffffff,gr4 | |
136 | movgs gr4,scr0 | |
137 | movgs gr4,scr1 | |
138 | ||
139 | # specify the context we want to flush | |
140 | movgs gr8,tplr | |
141 | ||
142 | # zap the matching TLB line and AMR values | |
143 | setlos #~(PAGE_SIZE-1),gr5 | |
144 | and gr9,gr5,gr9 | |
145 | tlbpr gr9,gr0,#5,#0 | |
146 | ||
147 | bralr | |
148 | ||
149 | .size __flush_tlb_page, .-__flush_tlb_page | |
150 | ||
151 | ############################################################################### | |
152 | # | |
153 | # flush a range of addresses from the TLB | |
154 | # - void __flush_tlb_range(unsigned long contextid [GR8], | |
155 | # unsigned long start [GR9], | |
156 | # unsigned long end [GR10]) | |
157 | # | |
158 | ############################################################################### | |
159 | .globl __flush_tlb_range | |
160 | .type __flush_tlb_range,@function | |
161 | __flush_tlb_range: | |
162 | # kill cached PGE value | |
163 | setlos #0xffffffff,gr4 | |
164 | movgs gr4,scr0 | |
165 | movgs gr4,scr1 | |
166 | ||
167 | # specify the context we want to flush | |
168 | movgs gr8,tplr | |
169 | ||
170 | # round the start down to beginning of TLB line and end up to beginning of next TLB line | |
171 | setlos.p #~(PAGE_SIZE-1),gr5 | |
172 | setlos #PAGE_SIZE,gr6 | |
173 | subi.p gr10,#1,gr10 | |
174 | and gr9,gr5,gr9 | |
175 | and gr10,gr5,gr10 | |
176 | 2: | |
177 | tlbpr gr9,gr0,#5,#0 | |
178 | subcc.p gr9,gr10,gr0,icc0 | |
179 | add gr9,gr6,gr9 | |
180 | bne icc0,#0,2b ; most likely a 1-page flush | |
181 | ||
182 | bralr | |
183 | ||
184 | .size __flush_tlb_range, .-__flush_tlb_range |