source: mainline/kernel/arch/sparc64/include/mm/sun4u/tlb.h@ 8c2214e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8c2214e was 8c2214e, checked in by Pavel Rimsky <pavel@…>, 15 years ago

Cleanup and merge of the TSB code.

  • Property mode set to 100644
File size: 16.8 KB
RevLine 
[ba50a34]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_sun4u_H_
36#define KERN_sparc64_TLB_sun4u_H_
37
38#if defined (US)
39#define ITLB_ENTRY_COUNT 64
40#define DTLB_ENTRY_COUNT 64
41#define DTLB_MAX_LOCKED_ENTRIES DTLB_ENTRY_COUNT
42#endif
43
44/** TLB_DSMALL is the only of the three DMMUs that can hold locked entries. */
45#if defined (US3)
46#define DTLB_MAX_LOCKED_ENTRIES 16
47#endif
48
49#define MEM_CONTEXT_KERNEL 0
50#define MEM_CONTEXT_TEMP 1
51
52/** Page sizes. */
53#define PAGESIZE_8K 0
54#define PAGESIZE_64K 1
55#define PAGESIZE_512K 2
56#define PAGESIZE_4M 3
57
58/** Bit width of the TLB-locked portion of kernel address space. */
59#define KERNEL_PAGE_WIDTH 22 /* 4M */
60
61/* TLB Demap Operation types. */
62#define TLB_DEMAP_PAGE 0
63#define TLB_DEMAP_CONTEXT 1
64#if defined (US3)
65#define TLB_DEMAP_ALL 2
66#endif
67
68#define TLB_DEMAP_TYPE_SHIFT 6
69
70/* TLB Demap Operation Context register encodings. */
71#define TLB_DEMAP_PRIMARY 0
72#define TLB_DEMAP_SECONDARY 1
73#define TLB_DEMAP_NUCLEUS 2
74
75/* There are more TLBs in one MMU in US3, their codes are defined here. */
76#if defined (US3)
77/* D-MMU: one small (16-entry) TLB and two big (512-entry) TLBs */
78#define TLB_DSMALL 0
79#define TLB_DBIG_0 2
80#define TLB_DBIG_1 3
81
82/* I-MMU: one small (16-entry) TLB and one big TLB */
83#define TLB_ISMALL 0
84#define TLB_IBIG 2
85#endif
86
87#define TLB_DEMAP_CONTEXT_SHIFT 4
88
89/* TLB Tag Access shifts */
90#define TLB_TAG_ACCESS_CONTEXT_SHIFT 0
91#define TLB_TAG_ACCESS_CONTEXT_MASK ((1 << 13) - 1)
92#define TLB_TAG_ACCESS_VPN_SHIFT 13
93
94#ifndef __ASM__
95
96#include <arch/mm/tte.h>
97#include <arch/mm/mmu.h>
98#include <arch/mm/page.h>
99#include <arch/asm.h>
100#include <arch/barrier.h>
101#include <arch/types.h>
102#include <arch/register.h>
103#include <arch/cpu.h>
104
105union tlb_context_reg {
106 uint64_t v;
107 struct {
108 unsigned long : 51;
109 unsigned context : 13; /**< Context/ASID. */
110 } __attribute__ ((packed));
111};
112typedef union tlb_context_reg tlb_context_reg_t;
113
114/** I-/D-TLB Data In/Access Register type. */
115typedef tte_data_t tlb_data_t;
116
117/** I-/D-TLB Data Access Address in Alternate Space. */
118
119#if defined (US)
120
121union tlb_data_access_addr {
122 uint64_t value;
123 struct {
124 uint64_t : 55;
125 unsigned tlb_entry : 6;
126 unsigned : 3;
127 } __attribute__ ((packed));
128};
129typedef union tlb_data_access_addr dtlb_data_access_addr_t;
130typedef union tlb_data_access_addr dtlb_tag_read_addr_t;
131typedef union tlb_data_access_addr itlb_data_access_addr_t;
132typedef union tlb_data_access_addr itlb_tag_read_addr_t;
133
134#elif defined (US3)
135
136/*
137 * In US3, I-MMU and D-MMU have different formats of the data
138 * access register virtual address. In the corresponding
139 * structures the member variable for the entry number is
140 * called "local_tlb_entry" - it contrasts with the "tlb_entry"
141 * for the US data access register VA structure. The rationale
142 * behind this is to prevent careless mistakes in the code
143 * caused by setting only the entry number and not the TLB
144 * number in the US3 code (when taking the code from US).
145 */
146
147union dtlb_data_access_addr {
148 uint64_t value;
149 struct {
150 uint64_t : 45;
151 unsigned : 1;
152 unsigned tlb_number : 2;
153 unsigned : 4;
154 unsigned local_tlb_entry : 9;
155 unsigned : 3;
156 } __attribute__ ((packed));
157};
158typedef union dtlb_data_access_addr dtlb_data_access_addr_t;
159typedef union dtlb_data_access_addr dtlb_tag_read_addr_t;
160
161union itlb_data_access_addr {
162 uint64_t value;
163 struct {
164 uint64_t : 45;
165 unsigned : 1;
166 unsigned tlb_number : 2;
167 unsigned : 6;
168 unsigned local_tlb_entry : 7;
169 unsigned : 3;
170 } __attribute__ ((packed));
171};
172typedef union itlb_data_access_addr itlb_data_access_addr_t;
173typedef union itlb_data_access_addr itlb_tag_read_addr_t;
174
175#endif
176
177/** I-/D-TLB Tag Read Register. */
178union tlb_tag_read_reg {
179 uint64_t value;
180 struct {
181 uint64_t vpn : 51; /**< Virtual Address bits 63:13. */
182 unsigned context : 13; /**< Context identifier. */
183 } __attribute__ ((packed));
184};
185typedef union tlb_tag_read_reg tlb_tag_read_reg_t;
186typedef union tlb_tag_read_reg tlb_tag_access_reg_t;
187
188
189/** TLB Demap Operation Address. */
190union tlb_demap_addr {
191 uint64_t value;
192 struct {
193 uint64_t vpn: 51; /**< Virtual Address bits 63:13. */
194#if defined (US)
195 unsigned : 6; /**< Ignored. */
196 unsigned type : 1; /**< The type of demap operation. */
197#elif defined (US3)
198 unsigned : 5; /**< Ignored. */
199 unsigned type: 2; /**< The type of demap operation. */
200#endif
201 unsigned context : 2; /**< Context register selection. */
202 unsigned : 4; /**< Zero. */
203 } __attribute__ ((packed));
204};
205typedef union tlb_demap_addr tlb_demap_addr_t;
206
207/** TLB Synchronous Fault Status Register. */
208union tlb_sfsr_reg {
209 uint64_t value;
210 struct {
211#if defined (US)
212 unsigned long : 40; /**< Implementation dependent. */
213 unsigned asi : 8; /**< ASI. */
214 unsigned : 2;
215 unsigned ft : 7; /**< Fault type. */
216#elif defined (US3)
217 unsigned long : 39; /**< Implementation dependent. */
218 unsigned nf : 1; /**< Non-faulting load. */
219 unsigned asi : 8; /**< ASI. */
220 unsigned tm : 1; /**< I-TLB miss. */
221 unsigned : 3; /**< Reserved. */
222 unsigned ft : 5; /**< Fault type. */
223#endif
224 unsigned e : 1; /**< Side-effect bit. */
225 unsigned ct : 2; /**< Context Register selection. */
226 unsigned pr : 1; /**< Privilege bit. */
227 unsigned w : 1; /**< Write bit. */
228 unsigned ow : 1; /**< Overwrite bit. */
229 unsigned fv : 1; /**< Fault Valid bit. */
230 } __attribute__ ((packed));
231};
232typedef union tlb_sfsr_reg tlb_sfsr_reg_t;
233
234#if defined (US3)
235
236/*
237 * Functions for determining the number of entries in TLBs. They either return
238 * a constant value or a value based on the CPU autodetection.
239 */
240
241/**
242 * Determine the number of entries in the DMMU's small TLB.
243 */
244static inline uint16_t tlb_dsmall_size(void)
245{
246 return 16;
247}
248
249/**
250 * Determine the number of entries in each DMMU's big TLB.
251 */
252static inline uint16_t tlb_dbig_size(void)
253{
254 return 512;
255}
256
257/**
258 * Determine the number of entries in the IMMU's small TLB.
259 */
260static inline uint16_t tlb_ismall_size(void)
261{
262 return 16;
263}
264
265/**
266 * Determine the number of entries in the IMMU's big TLB.
267 */
268static inline uint16_t tlb_ibig_size(void)
269{
270 if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIV_PLUS)
271 return 512;
272 else
273 return 128;
274}
275
276#endif
277
278/** Read MMU Primary Context Register.
279 *
280 * @return Current value of Primary Context Register.
281 */
282static inline uint64_t mmu_primary_context_read(void)
283{
284 return asi_u64_read(ASI_DMMU, VA_PRIMARY_CONTEXT_REG);
285}
286
287/** Write MMU Primary Context Register.
288 *
289 * @param v New value of Primary Context Register.
290 */
291static inline void mmu_primary_context_write(uint64_t v)
292{
293 asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v);
294 flush_pipeline();
295}
296
297/** Read MMU Secondary Context Register.
298 *
299 * @return Current value of Secondary Context Register.
300 */
301static inline uint64_t mmu_secondary_context_read(void)
302{
303 return asi_u64_read(ASI_DMMU, VA_SECONDARY_CONTEXT_REG);
304}
305
306/** Write MMU Primary Context Register.
307 *
308 * @param v New value of Primary Context Register.
309 */
310static inline void mmu_secondary_context_write(uint64_t v)
311{
312 asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v);
313 flush_pipeline();
314}
315
316#if defined (US)
317
318/** Read IMMU TLB Data Access Register.
319 *
320 * @param entry TLB Entry index.
321 *
322 * @return Current value of specified IMMU TLB Data Access
323 * Register.
324 */
325static inline uint64_t itlb_data_access_read(size_t entry)
326{
327 itlb_data_access_addr_t reg;
328
329 reg.value = 0;
330 reg.tlb_entry = entry;
331 return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
332}
333
334/** Write IMMU TLB Data Access Register.
335 *
336 * @param entry TLB Entry index.
337 * @param value Value to be written.
338 */
339static inline void itlb_data_access_write(size_t entry, uint64_t value)
340{
341 itlb_data_access_addr_t reg;
342
343 reg.value = 0;
344 reg.tlb_entry = entry;
345 asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
346 flush_pipeline();
347}
348
349/** Read DMMU TLB Data Access Register.
350 *
351 * @param entry TLB Entry index.
352 *
353 * @return Current value of specified DMMU TLB Data Access
354 * Register.
355 */
356static inline uint64_t dtlb_data_access_read(size_t entry)
357{
358 dtlb_data_access_addr_t reg;
359
360 reg.value = 0;
361 reg.tlb_entry = entry;
362 return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
363}
364
365/** Write DMMU TLB Data Access Register.
366 *
367 * @param entry TLB Entry index.
368 * @param value Value to be written.
369 */
370static inline void dtlb_data_access_write(size_t entry, uint64_t value)
371{
372 dtlb_data_access_addr_t reg;
373
374 reg.value = 0;
375 reg.tlb_entry = entry;
376 asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
377 membar();
378}
379
380/** Read IMMU TLB Tag Read Register.
381 *
382 * @param entry TLB Entry index.
383 *
384 * @return Current value of specified IMMU TLB Tag Read Register.
385 */
386static inline uint64_t itlb_tag_read_read(size_t entry)
387{
388 itlb_tag_read_addr_t tag;
389
390 tag.value = 0;
391 tag.tlb_entry = entry;
392 return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
393}
394
395/** Read DMMU TLB Tag Read Register.
396 *
397 * @param entry TLB Entry index.
398 *
399 * @return Current value of specified DMMU TLB Tag Read Register.
400 */
401static inline uint64_t dtlb_tag_read_read(size_t entry)
402{
403 dtlb_tag_read_addr_t tag;
404
405 tag.value = 0;
406 tag.tlb_entry = entry;
407 return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
408}
409
410#elif defined (US3)
411
412
413/** Read IMMU TLB Data Access Register.
414 *
415 * @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
416 * @param entry TLB Entry index.
417 *
418 * @return Current value of specified IMMU TLB Data Access
419 * Register.
420 */
421static inline uint64_t itlb_data_access_read(int tlb, size_t entry)
422{
423 itlb_data_access_addr_t reg;
424
425 reg.value = 0;
426 reg.tlb_number = tlb;
427 reg.local_tlb_entry = entry;
428 return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
429}
430
431/** Write IMMU TLB Data Access Register.
432 * @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
433 * @param entry TLB Entry index.
434 * @param value Value to be written.
435 */
436static inline void itlb_data_access_write(int tlb, size_t entry,
437 uint64_t value)
438{
439 itlb_data_access_addr_t reg;
440
441 reg.value = 0;
442 reg.tlb_number = tlb;
443 reg.local_tlb_entry = entry;
444 asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
445 flush_pipeline();
446}
447
448/** Read DMMU TLB Data Access Register.
449 *
450 * @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG, TLB_DBIG)
451 * @param entry TLB Entry index.
452 *
453 * @return Current value of specified DMMU TLB Data Access
454 * Register.
455 */
456static inline uint64_t dtlb_data_access_read(int tlb, size_t entry)
457{
458 dtlb_data_access_addr_t reg;
459
460 reg.value = 0;
461 reg.tlb_number = tlb;
462 reg.local_tlb_entry = entry;
463 return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
464}
465
466/** Write DMMU TLB Data Access Register.
467 *
468 * @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
469 * @param entry TLB Entry index.
470 * @param value Value to be written.
471 */
472static inline void dtlb_data_access_write(int tlb, size_t entry,
473 uint64_t value)
474{
475 dtlb_data_access_addr_t reg;
476
477 reg.value = 0;
478 reg.tlb_number = tlb;
479 reg.local_tlb_entry = entry;
480 asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
481 membar();
482}
483
484/** Read IMMU TLB Tag Read Register.
485 *
486 * @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
487 * @param entry TLB Entry index.
488 *
489 * @return Current value of specified IMMU TLB Tag Read Register.
490 */
491static inline uint64_t itlb_tag_read_read(int tlb, size_t entry)
492{
493 itlb_tag_read_addr_t tag;
494
495 tag.value = 0;
496 tag.tlb_number = tlb;
497 tag.local_tlb_entry = entry;
498 return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
499}
500
501/** Read DMMU TLB Tag Read Register.
502 *
503 * @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
504 * @param entry TLB Entry index.
505 *
506 * @return Current value of specified DMMU TLB Tag Read Register.
507 */
508static inline uint64_t dtlb_tag_read_read(int tlb, size_t entry)
509{
510 dtlb_tag_read_addr_t tag;
511
512 tag.value = 0;
513 tag.tlb_number = tlb;
514 tag.local_tlb_entry = entry;
515 return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
516}
517
518#endif
519
520
521/** Write IMMU TLB Tag Access Register.
522 *
523 * @param v Value to be written.
524 */
525static inline void itlb_tag_access_write(uint64_t v)
526{
527 asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v);
528 flush_pipeline();
529}
530
531/** Read IMMU TLB Tag Access Register.
532 *
533 * @return Current value of IMMU TLB Tag Access Register.
534 */
535static inline uint64_t itlb_tag_access_read(void)
536{
537 return asi_u64_read(ASI_IMMU, VA_IMMU_TAG_ACCESS);
538}
539
540/** Write DMMU TLB Tag Access Register.
541 *
542 * @param v Value to be written.
543 */
544static inline void dtlb_tag_access_write(uint64_t v)
545{
546 asi_u64_write(ASI_DMMU, VA_DMMU_TAG_ACCESS, v);
547 membar();
548}
549
550/** Read DMMU TLB Tag Access Register.
551 *
552 * @return Current value of DMMU TLB Tag Access Register.
553 */
554static inline uint64_t dtlb_tag_access_read(void)
555{
556 return asi_u64_read(ASI_DMMU, VA_DMMU_TAG_ACCESS);
557}
558
559
560/** Write IMMU TLB Data in Register.
561 *
562 * @param v Value to be written.
563 */
564static inline void itlb_data_in_write(uint64_t v)
565{
566 asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v);
567 flush_pipeline();
568}
569
570/** Write DMMU TLB Data in Register.
571 *
572 * @param v Value to be written.
573 */
574static inline void dtlb_data_in_write(uint64_t v)
575{
576 asi_u64_write(ASI_DTLB_DATA_IN_REG, 0, v);
577 membar();
578}
579
580/** Read ITLB Synchronous Fault Status Register.
581 *
582 * @return Current content of I-SFSR register.
583 */
584static inline uint64_t itlb_sfsr_read(void)
585{
586 return asi_u64_read(ASI_IMMU, VA_IMMU_SFSR);
587}
588
589/** Write ITLB Synchronous Fault Status Register.
590 *
591 * @param v New value of I-SFSR register.
592 */
593static inline void itlb_sfsr_write(uint64_t v)
594{
595 asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v);
596 flush_pipeline();
597}
598
599/** Read DTLB Synchronous Fault Status Register.
600 *
601 * @return Current content of D-SFSR register.
602 */
603static inline uint64_t dtlb_sfsr_read(void)
604{
605 return asi_u64_read(ASI_DMMU, VA_DMMU_SFSR);
606}
607
608/** Write DTLB Synchronous Fault Status Register.
609 *
610 * @param v New value of D-SFSR register.
611 */
612static inline void dtlb_sfsr_write(uint64_t v)
613{
614 asi_u64_write(ASI_DMMU, VA_DMMU_SFSR, v);
615 membar();
616}
617
618/** Read DTLB Synchronous Fault Address Register.
619 *
620 * @return Current content of D-SFAR register.
621 */
622static inline uint64_t dtlb_sfar_read(void)
623{
624 return asi_u64_read(ASI_DMMU, VA_DMMU_SFAR);
625}
626
627/** Perform IMMU TLB Demap Operation.
628 *
629 * @param type Selects between context and page demap (and entire MMU
630 * demap on US3).
631 * @param context_encoding Specifies which Context register has Context ID for
632 * demap.
633 * @param page Address which is on the page to be demapped.
634 */
635static inline void itlb_demap(int type, int context_encoding, uintptr_t page)
636{
637 tlb_demap_addr_t da;
638 page_address_t pg;
639
640 da.value = 0;
641 pg.address = page;
642
643 da.type = type;
644 da.context = context_encoding;
645 da.vpn = pg.vpn;
646
647 /* da.value is the address within the ASI */
648 asi_u64_write(ASI_IMMU_DEMAP, da.value, 0);
649
650 flush_pipeline();
651}
652
653/** Perform DMMU TLB Demap Operation.
654 *
655 * @param type Selects between context and page demap (and entire MMU
656 * demap on US3).
657 * @param context_encoding Specifies which Context register has Context ID for
658 * demap.
659 * @param page Address which is on the page to be demapped.
660 */
661static inline void dtlb_demap(int type, int context_encoding, uintptr_t page)
662{
663 tlb_demap_addr_t da;
664 page_address_t pg;
665
666 da.value = 0;
667 pg.address = page;
668
669 da.type = type;
670 da.context = context_encoding;
671 da.vpn = pg.vpn;
672
673 /* da.value is the address within the ASI */
674 asi_u64_write(ASI_DMMU_DEMAP, da.value, 0);
675
676 membar();
677}
678
679extern void fast_instruction_access_mmu_miss(unative_t, istate_t *);
680extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t, istate_t *);
681extern void fast_data_access_protection(tlb_tag_access_reg_t , istate_t *);
682
683extern void dtlb_insert_mapping(uintptr_t, uintptr_t, int, bool, bool);
684
685extern void dump_sfsr_and_sfar(void);
[8c2214e]686extern void describe_dmmu_fault(void);
[ba50a34]687
688#endif /* !def __ASM__ */
689
690#endif
691
692/** @}
693 */
Note: See TracBrowser for help on using the repository browser.