source: mainline/kernel/arch/sparc64/include/mm/tlb.h@ 0eb58f1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0eb58f1 was 36f19c0, checked in by Jakub Jermar <jakub@…>, 19 years ago

Fix a nasty bug in the TLB miss handlers on sparc64.
After we no longer lock the kernel stack in the DTLB,
there is a real danger of nested DTLB misses. The nested
miss can very easily clobber the DTLB Tag Access register.
Therefore, the original miss may not read this register, but
it has to receive its value as an argument. The argument
value is saved in the trap table when it is guaranteed that
the nested TLB miss will not occur.

  • Property mode set to 100644
File size: 11.0 KB
Line 
1/*
2 * Copyright (c) 2005 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup sparc64mm
30 * @{
31 */
32/** @file
33 */
34
35#ifndef KERN_sparc64_TLB_H_
36#define KERN_sparc64_TLB_H_
37
38#define ITLB_ENTRY_COUNT 64
39#define DTLB_ENTRY_COUNT 64
40
41#define MEM_CONTEXT_KERNEL 0
42#define MEM_CONTEXT_TEMP 1
43
44/** Page sizes. */
45#define PAGESIZE_8K 0
46#define PAGESIZE_64K 1
47#define PAGESIZE_512K 2
48#define PAGESIZE_4M 3
49
50/** Bit width of the TLB-locked portion of kernel address space. */
51#define KERNEL_PAGE_WIDTH 22 /* 4M */
52
53/* TLB Demap Operation types. */
54#define TLB_DEMAP_PAGE 0
55#define TLB_DEMAP_CONTEXT 1
56
57#define TLB_DEMAP_TYPE_SHIFT 6
58
59/* TLB Demap Operation Context register encodings. */
60#define TLB_DEMAP_PRIMARY 0
61#define TLB_DEMAP_SECONDARY 1
62#define TLB_DEMAP_NUCLEUS 2
63
64#define TLB_DEMAP_CONTEXT_SHIFT 4
65
66/* TLB Tag Access shifts */
67#define TLB_TAG_ACCESS_CONTEXT_SHIFT 0
68#define TLB_TAG_ACCESS_CONTEXT_MASK ((1 << 13) - 1)
69#define TLB_TAG_ACCESS_VPN_SHIFT 13
70
71#ifndef __ASM__
72
73#include <arch/mm/tte.h>
74#include <arch/mm/mmu.h>
75#include <arch/mm/page.h>
76#include <arch/asm.h>
77#include <arch/barrier.h>
78#include <arch/types.h>
79
80union tlb_context_reg {
81 uint64_t v;
82 struct {
83 unsigned long : 51;
84 unsigned context : 13; /**< Context/ASID. */
85 } __attribute__ ((packed));
86};
87typedef union tlb_context_reg tlb_context_reg_t;
88
89/** I-/D-TLB Data In/Access Register type. */
90typedef tte_data_t tlb_data_t;
91
92/** I-/D-TLB Data Access Address in Alternate Space. */
93union tlb_data_access_addr {
94 uint64_t value;
95 struct {
96 uint64_t : 55;
97 unsigned tlb_entry : 6;
98 unsigned : 3;
99 } __attribute__ ((packed));
100};
101typedef union tlb_data_access_addr tlb_data_access_addr_t;
102typedef union tlb_data_access_addr tlb_tag_read_addr_t;
103
104/** I-/D-TLB Tag Read Register. */
105union tlb_tag_read_reg {
106 uint64_t value;
107 struct {
108 uint64_t vpn : 51; /**< Virtual Address bits 63:13. */
109 unsigned context : 13; /**< Context identifier. */
110 } __attribute__ ((packed));
111};
112typedef union tlb_tag_read_reg tlb_tag_read_reg_t;
113typedef union tlb_tag_read_reg tlb_tag_access_reg_t;
114
115
116/** TLB Demap Operation Address. */
117union tlb_demap_addr {
118 uint64_t value;
119 struct {
120 uint64_t vpn: 51; /**< Virtual Address bits 63:13. */
121 unsigned : 6; /**< Ignored. */
122 unsigned type : 1; /**< The type of demap operation. */
123 unsigned context : 2; /**< Context register selection. */
124 unsigned : 4; /**< Zero. */
125 } __attribute__ ((packed));
126};
127typedef union tlb_demap_addr tlb_demap_addr_t;
128
129/** TLB Synchronous Fault Status Register. */
130union tlb_sfsr_reg {
131 uint64_t value;
132 struct {
133 unsigned long : 40; /**< Implementation dependent. */
134 unsigned asi : 8; /**< ASI. */
135 unsigned : 2;
136 unsigned ft : 7; /**< Fault type. */
137 unsigned e : 1; /**< Side-effect bit. */
138 unsigned ct : 2; /**< Context Register selection. */
139 unsigned pr : 1; /**< Privilege bit. */
140 unsigned w : 1; /**< Write bit. */
141 unsigned ow : 1; /**< Overwrite bit. */
142 unsigned fv : 1; /**< Fault Valid bit. */
143 } __attribute__ ((packed));
144};
145typedef union tlb_sfsr_reg tlb_sfsr_reg_t;
146
147/** Read MMU Primary Context Register.
148 *
149 * @return Current value of Primary Context Register.
150 */
151static inline uint64_t mmu_primary_context_read(void)
152{
153 return asi_u64_read(ASI_DMMU, VA_PRIMARY_CONTEXT_REG);
154}
155
156/** Write MMU Primary Context Register.
157 *
158 * @param v New value of Primary Context Register.
159 */
160static inline void mmu_primary_context_write(uint64_t v)
161{
162 asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v);
163 flush();
164}
165
166/** Read MMU Secondary Context Register.
167 *
168 * @return Current value of Secondary Context Register.
169 */
170static inline uint64_t mmu_secondary_context_read(void)
171{
172 return asi_u64_read(ASI_DMMU, VA_SECONDARY_CONTEXT_REG);
173}
174
175/** Write MMU Primary Context Register.
176 *
177 * @param v New value of Primary Context Register.
178 */
179static inline void mmu_secondary_context_write(uint64_t v)
180{
181 asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v);
182 flush();
183}
184
185/** Read IMMU TLB Data Access Register.
186 *
187 * @param entry TLB Entry index.
188 *
189 * @return Current value of specified IMMU TLB Data Access Register.
190 */
191static inline uint64_t itlb_data_access_read(index_t entry)
192{
193 tlb_data_access_addr_t reg;
194
195 reg.value = 0;
196 reg.tlb_entry = entry;
197 return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
198}
199
200/** Write IMMU TLB Data Access Register.
201 *
202 * @param entry TLB Entry index.
203 * @param value Value to be written.
204 */
205static inline void itlb_data_access_write(index_t entry, uint64_t value)
206{
207 tlb_data_access_addr_t reg;
208
209 reg.value = 0;
210 reg.tlb_entry = entry;
211 asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
212 flush();
213}
214
215/** Read DMMU TLB Data Access Register.
216 *
217 * @param entry TLB Entry index.
218 *
219 * @return Current value of specified DMMU TLB Data Access Register.
220 */
221static inline uint64_t dtlb_data_access_read(index_t entry)
222{
223 tlb_data_access_addr_t reg;
224
225 reg.value = 0;
226 reg.tlb_entry = entry;
227 return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
228}
229
230/** Write DMMU TLB Data Access Register.
231 *
232 * @param entry TLB Entry index.
233 * @param value Value to be written.
234 */
235static inline void dtlb_data_access_write(index_t entry, uint64_t value)
236{
237 tlb_data_access_addr_t reg;
238
239 reg.value = 0;
240 reg.tlb_entry = entry;
241 asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
242 membar();
243}
244
245/** Read IMMU TLB Tag Read Register.
246 *
247 * @param entry TLB Entry index.
248 *
249 * @return Current value of specified IMMU TLB Tag Read Register.
250 */
251static inline uint64_t itlb_tag_read_read(index_t entry)
252{
253 tlb_tag_read_addr_t tag;
254
255 tag.value = 0;
256 tag.tlb_entry = entry;
257 return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
258}
259
260/** Read DMMU TLB Tag Read Register.
261 *
262 * @param entry TLB Entry index.
263 *
264 * @return Current value of specified DMMU TLB Tag Read Register.
265 */
266static inline uint64_t dtlb_tag_read_read(index_t entry)
267{
268 tlb_tag_read_addr_t tag;
269
270 tag.value = 0;
271 tag.tlb_entry = entry;
272 return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
273}
274
275/** Write IMMU TLB Tag Access Register.
276 *
277 * @param v Value to be written.
278 */
279static inline void itlb_tag_access_write(uint64_t v)
280{
281 asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v);
282 flush();
283}
284
285/** Read IMMU TLB Tag Access Register.
286 *
287 * @return Current value of IMMU TLB Tag Access Register.
288 */
289static inline uint64_t itlb_tag_access_read(void)
290{
291 return asi_u64_read(ASI_IMMU, VA_IMMU_TAG_ACCESS);
292}
293
294/** Write DMMU TLB Tag Access Register.
295 *
296 * @param v Value to be written.
297 */
298static inline void dtlb_tag_access_write(uint64_t v)
299{
300 asi_u64_write(ASI_DMMU, VA_DMMU_TAG_ACCESS, v);
301 membar();
302}
303
304/** Read DMMU TLB Tag Access Register.
305 *
306 * @return Current value of DMMU TLB Tag Access Register.
307 */
308static inline uint64_t dtlb_tag_access_read(void)
309{
310 return asi_u64_read(ASI_DMMU, VA_DMMU_TAG_ACCESS);
311}
312
313
314/** Write IMMU TLB Data in Register.
315 *
316 * @param v Value to be written.
317 */
318static inline void itlb_data_in_write(uint64_t v)
319{
320 asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v);
321 flush();
322}
323
324/** Write DMMU TLB Data in Register.
325 *
326 * @param v Value to be written.
327 */
328static inline void dtlb_data_in_write(uint64_t v)
329{
330 asi_u64_write(ASI_DTLB_DATA_IN_REG, 0, v);
331 membar();
332}
333
334/** Read ITLB Synchronous Fault Status Register.
335 *
336 * @return Current content of I-SFSR register.
337 */
338static inline uint64_t itlb_sfsr_read(void)
339{
340 return asi_u64_read(ASI_IMMU, VA_IMMU_SFSR);
341}
342
343/** Write ITLB Synchronous Fault Status Register.
344 *
345 * @param v New value of I-SFSR register.
346 */
347static inline void itlb_sfsr_write(uint64_t v)
348{
349 asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v);
350 flush();
351}
352
353/** Read DTLB Synchronous Fault Status Register.
354 *
355 * @return Current content of D-SFSR register.
356 */
357static inline uint64_t dtlb_sfsr_read(void)
358{
359 return asi_u64_read(ASI_DMMU, VA_DMMU_SFSR);
360}
361
362/** Write DTLB Synchronous Fault Status Register.
363 *
364 * @param v New value of D-SFSR register.
365 */
366static inline void dtlb_sfsr_write(uint64_t v)
367{
368 asi_u64_write(ASI_DMMU, VA_DMMU_SFSR, v);
369 membar();
370}
371
372/** Read DTLB Synchronous Fault Address Register.
373 *
374 * @return Current content of D-SFAR register.
375 */
376static inline uint64_t dtlb_sfar_read(void)
377{
378 return asi_u64_read(ASI_DMMU, VA_DMMU_SFAR);
379}
380
381/** Perform IMMU TLB Demap Operation.
382 *
383 * @param type Selects between context and page demap.
384 * @param context_encoding Specifies which Context register has Context ID for
385 * demap.
386 * @param page Address which is on the page to be demapped.
387 */
388static inline void itlb_demap(int type, int context_encoding, uintptr_t page)
389{
390 tlb_demap_addr_t da;
391 page_address_t pg;
392
393 da.value = 0;
394 pg.address = page;
395
396 da.type = type;
397 da.context = context_encoding;
398 da.vpn = pg.vpn;
399
400 asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); /* da.value is the
401 * address within the
402 * ASI */
403 flush();
404}
405
406/** Perform DMMU TLB Demap Operation.
407 *
408 * @param type Selects between context and page demap.
409 * @param context_encoding Specifies which Context register has Context ID for
410 * demap.
411 * @param page Address which is on the page to be demapped.
412 */
413static inline void dtlb_demap(int type, int context_encoding, uintptr_t page)
414{
415 tlb_demap_addr_t da;
416 page_address_t pg;
417
418 da.value = 0;
419 pg.address = page;
420
421 da.type = type;
422 da.context = context_encoding;
423 da.vpn = pg.vpn;
424
425 asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); /* da.value is the
426 * address within the
427 * ASI */
428 membar();
429}
430
431extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate);
432extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate);
433extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate);
434
435extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable);
436
437extern void dump_sfsr_and_sfar(void);
438
439#endif /* !def __ASM__ */
440
441#endif
442
443/** @}
444 */
Note: See TracBrowser for help on using the repository browser.