Rev 900 | Rev 902 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 900 | Rev 901 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | /* |
29 | /* |
30 | * TLB management. |
30 | * TLB management. |
31 | */ |
31 | */ |
32 | 32 | ||
33 | #include <mm/tlb.h> |
33 | #include <mm/tlb.h> |
- | 34 | #include <mm/asid.h> |
|
34 | #include <arch/mm/tlb.h> |
35 | #include <arch/mm/tlb.h> |
- | 36 | #include <arch/mm/page.h> |
|
35 | #include <arch/barrier.h> |
37 | #include <arch/barrier.h> |
36 | #include <arch/interrupt.h> |
38 | #include <arch/interrupt.h> |
37 | #include <typedefs.h> |
39 | #include <typedefs.h> |
38 | #include <panic.h> |
40 | #include <panic.h> |
- | 41 | #include <print.h> |
|
39 | 42 | ||
40 | /** Invalidate all TLB entries. */ |
43 | /** Invalidate all TLB entries. */ |
41 | void tlb_invalidate_all(void) |
44 | void tlb_invalidate_all(void) |
42 | { |
45 | { |
43 | /* TODO */ |
46 | /* TODO */ |
Line 82... | Line 85... | ||
82 | void tc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtc) |
85 | void tc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtc) |
83 | { |
86 | { |
84 | region_register rr; |
87 | region_register rr; |
85 | bool restore_rr = false; |
88 | bool restore_rr = false; |
86 | 89 | ||
87 | if (!(entry.not_present.p)) |
90 | if (!(entry.p)) |
88 | return; |
91 | return; |
89 | 92 | ||
90 | rr.word = rr_read(VA_REGION(va)); |
93 | rr.word = rr_read(VA2VRN(va)); |
91 | if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA_REGION(va))))) { |
94 | if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) { |
92 | /* |
95 | /* |
93 | * The selected region register does not contain required RID. |
96 | * The selected region register does not contain required RID. |
94 | * Save the old content of the register and replace the RID. |
97 | * Save the old content of the register and replace the RID. |
95 | */ |
98 | */ |
96 | region_register rr0; |
99 | region_register rr0; |
97 | 100 | ||
98 | rr0 = rr; |
101 | rr0 = rr; |
99 | rr0.map.rid = ASID2RID(asid, VA_REGION(va)); |
102 | rr0.map.rid = ASID2RID(asid, VA2VRN(va)); |
100 | rr_write(VA_REGION(va), rr0.word); |
103 | rr_write(VA2VRN(va), rr0.word); |
101 | srlz_d(); |
104 | srlz_d(); |
102 | srlz_i(); |
105 | srlz_i(); |
103 | } |
106 | } |
104 | 107 | ||
105 | __asm__ volatile ( |
108 | __asm__ volatile ( |
Line 118... | Line 121... | ||
118 | : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc) |
121 | : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc) |
119 | : "p6", "p7", "r8" |
122 | : "p6", "p7", "r8" |
120 | ); |
123 | ); |
121 | 124 | ||
122 | if (restore_rr) { |
125 | if (restore_rr) { |
123 | rr_write(VA_REGION(va),rr.word); |
126 | rr_write(VA2VRN(va), rr.word); |
124 | srlz_d(); |
127 | srlz_d(); |
125 | srlz_i(); |
128 | srlz_i(); |
126 | } |
129 | } |
127 | } |
130 | } |
128 | 131 | ||
Line 161... | Line 164... | ||
161 | void tr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr) |
164 | void tr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr) |
162 | { |
165 | { |
163 | region_register rr; |
166 | region_register rr; |
164 | bool restore_rr = false; |
167 | bool restore_rr = false; |
165 | 168 | ||
166 | if (!(entry.not_present.p)) |
169 | if (!(entry.p)) |
167 | return; |
170 | return; |
168 | 171 | ||
169 | rr.word = rr_read(VA_REGION(va)); |
172 | rr.word = rr_read(VA2VRN(va)); |
170 | if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA_REGION(va))))) { |
173 | if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) { |
171 | /* |
174 | /* |
172 | * The selected region register does not contain required RID. |
175 | * The selected region register does not contain required RID. |
173 | * Save the old content of the register and replace the RID. |
176 | * Save the old content of the register and replace the RID. |
174 | */ |
177 | */ |
175 | region_register rr0; |
178 | region_register rr0; |
176 | 179 | ||
177 | rr0 = rr; |
180 | rr0 = rr; |
178 | rr0.map.rid = ASID2RID(asid, VA_REGION(va)); |
181 | rr0.map.rid = ASID2RID(asid, VA2VRN(va)); |
179 | rr_write(VA_REGION(va), rr0.word); |
182 | rr_write(VA2VRN(va), rr0.word); |
180 | srlz_d(); |
183 | srlz_d(); |
181 | srlz_i(); |
184 | srlz_i(); |
182 | } |
185 | } |
183 | 186 | ||
184 | __asm__ volatile ( |
187 | __asm__ volatile ( |
Line 197... | Line 200... | ||
197 | : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr) |
200 | : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr) |
198 | : "p6", "p7", "r8" |
201 | : "p6", "p7", "r8" |
199 | ); |
202 | ); |
200 | 203 | ||
201 | if (restore_rr) { |
204 | if (restore_rr) { |
202 | rr_write(VA_REGION(va),rr.word); |
205 | rr_write(VA2VRN(va), rr.word); |
203 | srlz_d(); |
206 | srlz_d(); |
204 | srlz_i(); |
207 | srlz_i(); |
205 | } |
208 | } |
206 | } |
209 | } |
207 | 210 | ||
- | 211 | /** Insert data into DTLB. |
|
- | 212 | * |
|
- | 213 | * @param va Virtual page address. |
|
- | 214 | * @param asid Address space identifier. |
|
- | 215 | * @param entry The rest of TLB entry as required by TLB insertion format. |
|
- | 216 | * @param dtr If true, insert into data translation register, use data translation cache otherwise. |
|
- | 217 | * @param tr Translation register if dtr is true, ignored otherwise. |
|
- | 218 | */ |
|
- | 219 | void dtlb_mapping_insert(__address page, __address frame, bool dtr, index_t tr) |
|
- | 220 | { |
|
- | 221 | tlb_entry_t entry; |
|
- | 222 | ||
- | 223 | entry.word[0] = 0; |
|
- | 224 | entry.word[1] = 0; |
|
- | 225 | ||
- | 226 | entry.p = true; /* present */ |
|
- | 227 | entry.ma = MA_WRITEBACK; |
|
- | 228 | entry.a = true; /* already accessed */ |
|
- | 229 | entry.d = true; /* already dirty */ |
|
- | 230 | entry.pl = PL_KERNEL; |
|
- | 231 | entry.ar = AR_READ | AR_WRITE; |
|
- | 232 | entry.ppn = frame >> PPN_SHIFT; |
|
- | 233 | entry.ps = PAGE_WIDTH; |
|
- | 234 | ||
- | 235 | if (dtr) |
|
- | 236 | dtr_mapping_insert(page, ASID_KERNEL, entry, tr); |
|
- | 237 | else |
|
- | 238 | dtc_mapping_insert(page, ASID_KERNEL, entry); |
|
- | 239 | } |
|
- | 240 | ||
208 | void alternate_instruction_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
241 | void alternate_instruction_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
209 | { |
242 | { |
210 | panic("%s\n", __FUNCTION__); |
243 | panic("%s\n", __FUNCTION__); |
211 | } |
244 | } |
212 | 245 | ||
- | 246 | /** Data TLB fault with VHPT turned off. |
|
- | 247 | * |
|
- | 248 | * @param vector Interruption vector. |
|
- | 249 | * @param pstate Structure with saved interruption state. |
|
- | 250 | */ |
|
213 | void alternate_data_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
251 | void alternate_data_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
214 | { |
252 | { |
- | 253 | region_register rr; |
|
- | 254 | rid_t rid; |
|
- | 255 | __address va; |
|
- | 256 | ||
- | 257 | va = pstate->cr_ifa; /* faulting address */ |
|
- | 258 | rr.word = rr_read(VA2VRN(va)); |
|
- | 259 | rid = rr.map.rid; |
|
- | 260 | if (RID2ASID(rid) == ASID_KERNEL) { |
|
- | 261 | if (VA2VRN(va) == VRN_KERNEL) { |
|
- | 262 | /* |
|
- | 263 | * Provide KA2PA(identity) mapping for faulting piece of |
|
- | 264 | * kernel address space. |
|
- | 265 | */ |
|
- | 266 | dtlb_mapping_insert(va, KA2PA(va), false, 0); |
|
- | 267 | return; |
|
- | 268 | } |
|
- | 269 | } |
|
215 | panic("%s: %P\n", __FUNCTION__, pstate->cr_ifa); |
270 | panic("%s: va=%P, rid=%d\n", __FUNCTION__, pstate->cr_ifa, rr.map.rid); |
216 | } |
271 | } |
217 | 272 | ||
218 | void data_nested_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
273 | void data_nested_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
219 | { |
274 | { |
220 | panic("%s\n", __FUNCTION__); |
275 | panic("%s\n", __FUNCTION__); |