Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/include/mm/tlb.h

    rba50a34 r98000fb  
    3636#define KERN_sparc64_TLB_H_
    3737
    38 #if defined (SUN4U)
    39 #include <arch/mm/sun4u/tlb.h>
    40 #elif defined (SUN4V)
    41 #include <arch/mm/sun4v/tlb.h>
    42 #endif
     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);
     686
     687#endif /* !def __ASM__ */
    43688
    44689#endif
Note: See TracChangeset for help on using the changeset viewer.