/* * Copyright (C) 2005 Jakub Jermar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __sparc64_TLB_H__ #define __sparc64_TLB_H__ #include #include #include #include #include #include #include #define ITLB_ENTRY_COUNT 64 #define DTLB_ENTRY_COUNT 64 /** Page sizes. */ #define PAGESIZE_8K 0 #define PAGESIZE_64K 1 #define PAGESIZE_512K 2 #define PAGESIZE_4M 3 /** Bit width of the TLB-locked portion of kernel address space. */ #define KERNEL_PAGE_WIDTH 22 /* 4M */ union tlb_context_reg { __u64 v; struct { unsigned long : 51; unsigned context : 13; /**< Context/ASID. */ } __attribute__ ((packed)); }; typedef union tlb_context_reg tlb_context_reg_t; /** I-/D-TLB Data In/Access Register type. */ typedef tte_data_t tlb_data_t; /** I-/D-TLB Data Access Address in Alternate Space. */ union tlb_data_access_addr { __u64 value; struct { __u64 : 55; unsigned tlb_entry : 6; unsigned : 3; } __attribute__ ((packed)); }; typedef union tlb_data_access_addr tlb_data_access_addr_t; typedef union tlb_data_access_addr tlb_tag_read_addr_t; /** I-/D-TLB Tag Read Register. */ union tlb_tag_read_reg { __u64 value; struct { __u64 vpn : 51; /**< Virtual Address bits 63:13. */ unsigned context : 13; /**< Context identifier. */ } __attribute__ ((packed)); }; typedef union tlb_tag_read_reg tlb_tag_read_reg_t; typedef union tlb_tag_read_reg tlb_tag_access_reg_t; /** TLB Demap Operation types. */ #define TLB_DEMAP_PAGE 0 #define TLB_DEMAP_CONTEXT 1 /** TLB Demap Operation Context register encodings. */ #define TLB_DEMAP_PRIMARY 0 #define TLB_DEMAP_SECONDARY 1 #define TLB_DEMAP_NUCLEUS 2 /** TLB Demap Operation Address. */ union tlb_demap_addr { __u64 value; struct { __u64 vpn: 51; /**< Virtual Address bits 63:13. */ unsigned : 6; /**< Ignored. */ unsigned type : 1; /**< The type of demap operation. */ unsigned context : 2; /**< Context register selection. */ unsigned : 4; /**< Zero. */ } __attribute__ ((packed)); }; typedef union tlb_demap_addr tlb_demap_addr_t; /** TLB Synchronous Fault Status Register. */ union tlb_sfsr_reg { __u64 value; struct { unsigned long : 39; /**< Implementation dependent. */ unsigned nf : 1; /**< Nonfaulting load. */ unsigned asi : 8; /**< ASI. */ unsigned tm : 1; /**< TLB miss. */ unsigned : 1; unsigned ft : 7; /**< Fault type. */ unsigned e : 1; /**< Side-effect bit. */ unsigned ct : 2; /**< Context Register selection. */ unsigned pr : 1; /**< Privilege bit. */ unsigned w : 1; /**< Write bit. */ unsigned ow : 1; /**< Overwrite bit. */ unsigned fv : 1; /**< Fault Valid bit. */ } __attribute__ ((packed)); }; typedef union tlb_sfsr_reg tlb_sfsr_reg_t; /** Read MMU Primary Context Register. * * @return Current value of Primary Context Register. */ static inline __u64 mmu_primary_context_read(void) { return asi_u64_read(ASI_DMMU, VA_PRIMARY_CONTEXT_REG); } /** Write MMU Primary Context Register. * * @param v New value of Primary Context Register. */ static inline void mmu_primary_context_write(__u64 v) { asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v); flush(); } /** Read MMU Secondary Context Register. * * @return Current value of Secondary Context Register. */ static inline __u64 mmu_secondary_context_read(void) { return asi_u64_read(ASI_DMMU, VA_SECONDARY_CONTEXT_REG); } /** Write MMU Primary Context Register. * * @param v New value of Primary Context Register. */ static inline void mmu_secondary_context_write(__u64 v) { asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v); flush(); } /** Read IMMU TLB Data Access Register. * * @param entry TLB Entry index. * * @return Current value of specified IMMU TLB Data Access Register. */ static inline __u64 itlb_data_access_read(index_t entry) { tlb_data_access_addr_t reg; reg.value = 0; reg.tlb_entry = entry; return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value); } /** Write IMMU TLB Data Access Register. * * @param entry TLB Entry index. * @param value Value to be written. */ static inline void itlb_data_access_write(index_t entry, __u64 value) { tlb_data_access_addr_t reg; reg.value = 0; reg.tlb_entry = entry; asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value); flush(); } /** Read DMMU TLB Data Access Register. * * @param entry TLB Entry index. * * @return Current value of specified DMMU TLB Data Access Register. */ static inline __u64 dtlb_data_access_read(index_t entry) { tlb_data_access_addr_t reg; reg.value = 0; reg.tlb_entry = entry; return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value); } /** Write DMMU TLB Data Access Register. * * @param entry TLB Entry index. * @param value Value to be written. */ static inline void dtlb_data_access_write(index_t entry, __u64 value) { tlb_data_access_addr_t reg; reg.value = 0; reg.tlb_entry = entry; asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value); flush(); } /** Read IMMU TLB Tag Read Register. * * @param entry TLB Entry index. * * @return Current value of specified IMMU TLB Tag Read Register. */ static inline __u64 itlb_tag_read_read(index_t entry) { tlb_tag_read_addr_t tag; tag.value = 0; tag.tlb_entry = entry; return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value); } /** Read DMMU TLB Tag Read Register. * * @param entry TLB Entry index. * * @return Current value of specified DMMU TLB Tag Read Register. */ static inline __u64 dtlb_tag_read_read(index_t entry) { tlb_tag_read_addr_t tag; tag.value = 0; tag.tlb_entry = entry; return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value); } /** Write IMMU TLB Tag Access Register. * * @param v Value to be written. */ static inline void itlb_tag_access_write(__u64 v) { asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v); flush(); } /** Read IMMU TLB Tag Access Register. * * @return Current value of IMMU TLB Tag Access Register. */ static inline __u64 itlb_tag_access_read(void) { return asi_u64_read(ASI_IMMU, VA_IMMU_TAG_ACCESS); } /** Write DMMU TLB Tag Access Register. * * @param v Value to be written. */ static inline void dtlb_tag_access_write(__u64 v) { asi_u64_write(ASI_DMMU, VA_DMMU_TAG_ACCESS, v); flush(); } /** Read DMMU TLB Tag Access Register. * * @return Current value of DMMU TLB Tag Access Register. */ static inline __u64 dtlb_tag_access_read(void) { return asi_u64_read(ASI_DMMU, VA_DMMU_TAG_ACCESS); } /** Write IMMU TLB Data in Register. * * @param v Value to be written. */ static inline void itlb_data_in_write(__u64 v) { asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v); flush(); } /** Write DMMU TLB Data in Register. * * @param v Value to be written. */ static inline void dtlb_data_in_write(__u64 v) { asi_u64_write(ASI_DTLB_DATA_IN_REG, 0, v); flush(); } /** Read ITLB Synchronous Fault Status Register. * * @return Current content of I-SFSR register. */ static inline __u64 itlb_sfsr_read(void) { return asi_u64_read(ASI_IMMU, VA_IMMU_SFSR); } /** Write ITLB Synchronous Fault Status Register. * * @param v New value of I-SFSR register. */ static inline void itlb_sfsr_write(__u64 v) { asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v); flush(); } /** Read DTLB Synchronous Fault Status Register. * * @return Current content of D-SFSR register. */ static inline __u64 dtlb_sfsr_read(void) { return asi_u64_read(ASI_DMMU, VA_DMMU_SFSR); } /** Write DTLB Synchronous Fault Status Register. * * @param v New value of D-SFSR register. */ static inline void dtlb_sfsr_write(__u64 v) { asi_u64_write(ASI_DMMU, VA_DMMU_SFSR, v); flush(); } /** Read DTLB Synchronous Fault Address Register. * * @return Current content of D-SFAR register. */ static inline __u64 dtlb_sfar_read(void) { return asi_u64_read(ASI_DMMU, VA_DMMU_SFAR); } /** Perform IMMU TLB Demap Operation. * * @param type Selects between context and page demap. * @param context_encoding Specifies which Context register has Context ID for demap. * @param page Address which is on the page to be demapped. */ static inline void itlb_demap(int type, int context_encoding, __address page) { tlb_demap_addr_t da; page_address_t pg; da.value = 0; pg.address = page; da.type = type; da.context = context_encoding; da.vpn = pg.vpn; asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); flush(); } /** Perform DMMU TLB Demap Operation. * * @param type Selects between context and page demap. * @param context_encoding Specifies which Context register has Context ID for demap. * @param page Address which is on the page to be demapped. */ static inline void dtlb_demap(int type, int context_encoding, __address page) { tlb_demap_addr_t da; page_address_t pg; da.value = 0; pg.address = page; da.type = type; da.context = context_encoding; da.vpn = pg.vpn; asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); flush(); } extern void fast_instruction_access_mmu_miss(void); extern void fast_data_access_mmu_miss(void); extern void fast_data_access_protection(void); extern void dtlb_insert_mapping(__address page, __address frame, int pagesize, bool locked, bool cacheable); #endif