162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __MMU_H 362306a36Sopenharmony_ci#define __MMU_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/const.h> 662306a36Sopenharmony_ci#include <asm/page.h> 762306a36Sopenharmony_ci#include <asm/hypervisor.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define CTX_NR_BITS 13 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL)) 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* UltraSPARC-III+ and later have a feature whereby you can 1462306a36Sopenharmony_ci * select what page size the various Data-TLB instances in the 1562306a36Sopenharmony_ci * chip. In order to gracefully support this, we put the version 1662306a36Sopenharmony_ci * field in a spot outside of the areas of the context register 1762306a36Sopenharmony_ci * where this parameter is specified. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci#define CTX_VERSION_SHIFT 22 2062306a36Sopenharmony_ci#define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define CTX_PGSZ_8KB _AC(0x0,UL) 2362306a36Sopenharmony_ci#define CTX_PGSZ_64KB _AC(0x1,UL) 2462306a36Sopenharmony_ci#define CTX_PGSZ_512KB _AC(0x2,UL) 2562306a36Sopenharmony_ci#define CTX_PGSZ_4MB _AC(0x3,UL) 2662306a36Sopenharmony_ci#define CTX_PGSZ_BITS _AC(0x7,UL) 2762306a36Sopenharmony_ci#define CTX_PGSZ0_NUC_SHIFT 61 2862306a36Sopenharmony_ci#define CTX_PGSZ1_NUC_SHIFT 58 2962306a36Sopenharmony_ci#define CTX_PGSZ0_SHIFT 16 3062306a36Sopenharmony_ci#define CTX_PGSZ1_SHIFT 19 3162306a36Sopenharmony_ci#define CTX_PGSZ_MASK ((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \ 3262306a36Sopenharmony_ci (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT)) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define CTX_PGSZ_BASE CTX_PGSZ_8KB 3562306a36Sopenharmony_ci#define CTX_PGSZ_HUGE CTX_PGSZ_4MB 3662306a36Sopenharmony_ci#define CTX_PGSZ_KERN CTX_PGSZ_4MB 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Thus, when running on UltraSPARC-III+ and later, we use the following 3962306a36Sopenharmony_ci * PRIMARY_CONTEXT register values for the kernel context. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci#define CTX_CHEETAH_PLUS_NUC \ 4262306a36Sopenharmony_ci ((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \ 4362306a36Sopenharmony_ci (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT)) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define CTX_CHEETAH_PLUS_CTX0 \ 4662306a36Sopenharmony_ci ((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \ 4762306a36Sopenharmony_ci (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT)) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* If you want "the TLB context number" use CTX_NR_MASK. If you 5062306a36Sopenharmony_ci * want "the bits I program into the context registers" use 5162306a36Sopenharmony_ci * CTX_HW_MASK. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci#define CTX_NR_MASK TAG_CONTEXT_BITS 5462306a36Sopenharmony_ci#define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT) 5762306a36Sopenharmony_ci#define CTX_VALID(__ctx) \ 5862306a36Sopenharmony_ci (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK)) 5962306a36Sopenharmony_ci#define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK) 6062306a36Sopenharmony_ci#define CTX_NRBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_NR_MASK) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define TSB_ENTRY_ALIGNMENT 16 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistruct tsb { 6762306a36Sopenharmony_ci unsigned long tag; 6862306a36Sopenharmony_ci unsigned long pte; 6962306a36Sopenharmony_ci} __attribute__((aligned(TSB_ENTRY_ALIGNMENT))); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_civoid __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte); 7262306a36Sopenharmony_civoid tsb_flush(unsigned long ent, unsigned long tag); 7362306a36Sopenharmony_civoid tsb_init(struct tsb *tsb, unsigned long size); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct tsb_config { 7662306a36Sopenharmony_ci struct tsb *tsb; 7762306a36Sopenharmony_ci unsigned long tsb_rss_limit; 7862306a36Sopenharmony_ci unsigned long tsb_nentries; 7962306a36Sopenharmony_ci unsigned long tsb_reg_val; 8062306a36Sopenharmony_ci unsigned long tsb_map_vaddr; 8162306a36Sopenharmony_ci unsigned long tsb_map_pte; 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define MM_TSB_BASE 0 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 8762306a36Sopenharmony_ci#define MM_TSB_HUGE 1 8862306a36Sopenharmony_ci#define MM_NUM_TSBS 2 8962306a36Sopenharmony_ci#else 9062306a36Sopenharmony_ci#define MM_NUM_TSBS 1 9162306a36Sopenharmony_ci#endif 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* ADI tags are stored when a page is swapped out and the storage for 9462306a36Sopenharmony_ci * tags is allocated dynamically. There is a tag storage descriptor 9562306a36Sopenharmony_ci * associated with each set of tag storage pages. Tag storage descriptors 9662306a36Sopenharmony_ci * are allocated dynamically. Since kernel will allocate a full page for 9762306a36Sopenharmony_ci * each tag storage descriptor, we can store up to 9862306a36Sopenharmony_ci * PAGE_SIZE/sizeof(tag storage descriptor) descriptors on that page. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_citypedef struct { 10162306a36Sopenharmony_ci unsigned long start; /* Start address for this tag storage */ 10262306a36Sopenharmony_ci unsigned long end; /* Last address for tag storage */ 10362306a36Sopenharmony_ci unsigned char *tags; /* Where the tags are */ 10462306a36Sopenharmony_ci unsigned long tag_users; /* number of references to descriptor */ 10562306a36Sopenharmony_ci} tag_storage_desc_t; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_citypedef struct { 10862306a36Sopenharmony_ci spinlock_t lock; 10962306a36Sopenharmony_ci unsigned long sparc64_ctx_val; 11062306a36Sopenharmony_ci unsigned long hugetlb_pte_count; 11162306a36Sopenharmony_ci unsigned long thp_pte_count; 11262306a36Sopenharmony_ci struct tsb_config tsb_block[MM_NUM_TSBS]; 11362306a36Sopenharmony_ci struct hv_tsb_descr tsb_descr[MM_NUM_TSBS]; 11462306a36Sopenharmony_ci void *vdso; 11562306a36Sopenharmony_ci bool adi; 11662306a36Sopenharmony_ci tag_storage_desc_t *tag_store; 11762306a36Sopenharmony_ci spinlock_t tag_lock; 11862306a36Sopenharmony_ci} mm_context_t; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define TSB_CONFIG_TSB 0x00 12362306a36Sopenharmony_ci#define TSB_CONFIG_RSS_LIMIT 0x08 12462306a36Sopenharmony_ci#define TSB_CONFIG_NENTRIES 0x10 12562306a36Sopenharmony_ci#define TSB_CONFIG_REG_VAL 0x18 12662306a36Sopenharmony_ci#define TSB_CONFIG_MAP_VADDR 0x20 12762306a36Sopenharmony_ci#define TSB_CONFIG_MAP_PTE 0x28 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci#endif /* __MMU_H */ 130