18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __MMU_H 38c2ecf20Sopenharmony_ci#define __MMU_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/const.h> 68c2ecf20Sopenharmony_ci#include <asm/page.h> 78c2ecf20Sopenharmony_ci#include <asm/hypervisor.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define CTX_NR_BITS 13 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL)) 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* UltraSPARC-III+ and later have a feature whereby you can 148c2ecf20Sopenharmony_ci * select what page size the various Data-TLB instances in the 158c2ecf20Sopenharmony_ci * chip. In order to gracefully support this, we put the version 168c2ecf20Sopenharmony_ci * field in a spot outside of the areas of the context register 178c2ecf20Sopenharmony_ci * where this parameter is specified. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci#define CTX_VERSION_SHIFT 22 208c2ecf20Sopenharmony_ci#define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define CTX_PGSZ_8KB _AC(0x0,UL) 238c2ecf20Sopenharmony_ci#define CTX_PGSZ_64KB _AC(0x1,UL) 248c2ecf20Sopenharmony_ci#define CTX_PGSZ_512KB _AC(0x2,UL) 258c2ecf20Sopenharmony_ci#define CTX_PGSZ_4MB _AC(0x3,UL) 268c2ecf20Sopenharmony_ci#define CTX_PGSZ_BITS _AC(0x7,UL) 278c2ecf20Sopenharmony_ci#define CTX_PGSZ0_NUC_SHIFT 61 288c2ecf20Sopenharmony_ci#define CTX_PGSZ1_NUC_SHIFT 58 298c2ecf20Sopenharmony_ci#define CTX_PGSZ0_SHIFT 16 308c2ecf20Sopenharmony_ci#define CTX_PGSZ1_SHIFT 19 318c2ecf20Sopenharmony_ci#define CTX_PGSZ_MASK ((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \ 328c2ecf20Sopenharmony_ci (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT)) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define CTX_PGSZ_BASE CTX_PGSZ_8KB 358c2ecf20Sopenharmony_ci#define CTX_PGSZ_HUGE CTX_PGSZ_4MB 368c2ecf20Sopenharmony_ci#define CTX_PGSZ_KERN CTX_PGSZ_4MB 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Thus, when running on UltraSPARC-III+ and later, we use the following 398c2ecf20Sopenharmony_ci * PRIMARY_CONTEXT register values for the kernel context. 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci#define CTX_CHEETAH_PLUS_NUC \ 428c2ecf20Sopenharmony_ci ((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \ 438c2ecf20Sopenharmony_ci (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT)) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define CTX_CHEETAH_PLUS_CTX0 \ 468c2ecf20Sopenharmony_ci ((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \ 478c2ecf20Sopenharmony_ci (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT)) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* If you want "the TLB context number" use CTX_NR_MASK. If you 508c2ecf20Sopenharmony_ci * want "the bits I program into the context registers" use 518c2ecf20Sopenharmony_ci * CTX_HW_MASK. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci#define CTX_NR_MASK TAG_CONTEXT_BITS 548c2ecf20Sopenharmony_ci#define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT) 578c2ecf20Sopenharmony_ci#define CTX_VALID(__ctx) \ 588c2ecf20Sopenharmony_ci (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK)) 598c2ecf20Sopenharmony_ci#define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK) 608c2ecf20Sopenharmony_ci#define CTX_NRBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_NR_MASK) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define TSB_ENTRY_ALIGNMENT 16 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistruct tsb { 678c2ecf20Sopenharmony_ci unsigned long tag; 688c2ecf20Sopenharmony_ci unsigned long pte; 698c2ecf20Sopenharmony_ci} __attribute__((aligned(TSB_ENTRY_ALIGNMENT))); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_civoid __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte); 728c2ecf20Sopenharmony_civoid tsb_flush(unsigned long ent, unsigned long tag); 738c2ecf20Sopenharmony_civoid tsb_init(struct tsb *tsb, unsigned long size); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistruct tsb_config { 768c2ecf20Sopenharmony_ci struct tsb *tsb; 778c2ecf20Sopenharmony_ci unsigned long tsb_rss_limit; 788c2ecf20Sopenharmony_ci unsigned long tsb_nentries; 798c2ecf20Sopenharmony_ci unsigned long tsb_reg_val; 808c2ecf20Sopenharmony_ci unsigned long tsb_map_vaddr; 818c2ecf20Sopenharmony_ci unsigned long tsb_map_pte; 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define MM_TSB_BASE 0 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 878c2ecf20Sopenharmony_ci#define MM_TSB_HUGE 1 888c2ecf20Sopenharmony_ci#define MM_NUM_TSBS 2 898c2ecf20Sopenharmony_ci#else 908c2ecf20Sopenharmony_ci#define MM_NUM_TSBS 1 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* ADI tags are stored when a page is swapped out and the storage for 948c2ecf20Sopenharmony_ci * tags is allocated dynamically. There is a tag storage descriptor 958c2ecf20Sopenharmony_ci * associated with each set of tag storage pages. Tag storage descriptors 968c2ecf20Sopenharmony_ci * are allocated dynamically. Since kernel will allocate a full page for 978c2ecf20Sopenharmony_ci * each tag storage descriptor, we can store up to 988c2ecf20Sopenharmony_ci * PAGE_SIZE/sizeof(tag storage descriptor) descriptors on that page. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_citypedef struct { 1018c2ecf20Sopenharmony_ci unsigned long start; /* Start address for this tag storage */ 1028c2ecf20Sopenharmony_ci unsigned long end; /* Last address for tag storage */ 1038c2ecf20Sopenharmony_ci unsigned char *tags; /* Where the tags are */ 1048c2ecf20Sopenharmony_ci unsigned long tag_users; /* number of references to descriptor */ 1058c2ecf20Sopenharmony_ci} tag_storage_desc_t; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_citypedef struct { 1088c2ecf20Sopenharmony_ci spinlock_t lock; 1098c2ecf20Sopenharmony_ci unsigned long sparc64_ctx_val; 1108c2ecf20Sopenharmony_ci unsigned long hugetlb_pte_count; 1118c2ecf20Sopenharmony_ci unsigned long thp_pte_count; 1128c2ecf20Sopenharmony_ci struct tsb_config tsb_block[MM_NUM_TSBS]; 1138c2ecf20Sopenharmony_ci struct hv_tsb_descr tsb_descr[MM_NUM_TSBS]; 1148c2ecf20Sopenharmony_ci void *vdso; 1158c2ecf20Sopenharmony_ci bool adi; 1168c2ecf20Sopenharmony_ci tag_storage_desc_t *tag_store; 1178c2ecf20Sopenharmony_ci spinlock_t tag_lock; 1188c2ecf20Sopenharmony_ci} mm_context_t; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define TSB_CONFIG_TSB 0x00 1238c2ecf20Sopenharmony_ci#define TSB_CONFIG_RSS_LIMIT 0x08 1248c2ecf20Sopenharmony_ci#define TSB_CONFIG_NENTRIES 0x10 1258c2ecf20Sopenharmony_ci#define TSB_CONFIG_REG_VAL 0x18 1268c2ecf20Sopenharmony_ci#define TSB_CONFIG_MAP_VADDR 0x20 1278c2ecf20Sopenharmony_ci#define TSB_CONFIG_MAP_PTE 0x28 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#endif /* __MMU_H */ 130