1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __MMU_H
#define __MMU_H

#include <linux/const.h>
#include <asm/page.h>
#include <asm/hypervisor.h>

#define CTX_NR_BITS		13

#define TAG_CONTEXT_BITS	((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))

/* UltraSPARC-III+ and later have a feature whereby you can
 * select what page size the various Data-TLB instances in the
 * chip.  In order to gracefully support this, we put the version
 * field in a spot outside of the areas of the context register
 * where this parameter is specified.
 */
#define CTX_VERSION_SHIFT	22
#define CTX_VERSION_MASK	((~0UL) << CTX_VERSION_SHIFT)

#define CTX_PGSZ_8KB		_AC(0x0,UL)
#define CTX_PGSZ_64KB		_AC(0x1,UL)
#define CTX_PGSZ_512KB		_AC(0x2,UL)
#define CTX_PGSZ_4MB		_AC(0x3,UL)
#define CTX_PGSZ_BITS		_AC(0x7,UL)
#define CTX_PGSZ0_NUC_SHIFT	61
#define CTX_PGSZ1_NUC_SHIFT	58
#define CTX_PGSZ0_SHIFT		16
#define CTX_PGSZ1_SHIFT		19
#define CTX_PGSZ_MASK		((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \
				 (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT))

#define CTX_PGSZ_BASE	CTX_PGSZ_8KB
#define CTX_PGSZ_HUGE	CTX_PGSZ_4MB
#define CTX_PGSZ_KERN	CTX_PGSZ_4MB

/* Thus, when running on UltraSPARC-III+ and later, we use the following
 * PRIMARY_CONTEXT register values for the kernel context.
 */
#define CTX_CHEETAH_PLUS_NUC \
	((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \
	 (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT))

#define CTX_CHEETAH_PLUS_CTX0 \
	((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \
	 (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT))

/* If you want "the TLB context number" use CTX_NR_MASK.  If you
 * want "the bits I program into the context registers" use
 * CTX_HW_MASK.
 */
#define CTX_NR_MASK		TAG_CONTEXT_BITS
#define CTX_HW_MASK		(CTX_NR_MASK | CTX_PGSZ_MASK)

#define CTX_FIRST_VERSION	BIT(CTX_VERSION_SHIFT)
#define CTX_VALID(__ctx)	\
	 (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
#define CTX_HWBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
#define CTX_NRBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_NR_MASK)

#ifndef __ASSEMBLY__

#define TSB_ENTRY_ALIGNMENT	16

struct tsb {
	unsigned long tag;
	unsigned long pte;
} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));

void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
void tsb_flush(unsigned long ent, unsigned long tag);
void tsb_init(struct tsb *tsb, unsigned long size);

struct tsb_config {
	struct tsb		*tsb;
	unsigned long		tsb_rss_limit;
	unsigned long		tsb_nentries;
	unsigned long		tsb_reg_val;
	unsigned long		tsb_map_vaddr;
	unsigned long		tsb_map_pte;
};

#define MM_TSB_BASE	0

#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
#define MM_TSB_HUGE	1
#define MM_NUM_TSBS	2
#else
#define MM_NUM_TSBS	1
#endif

/* ADI tags are stored when a page is swapped out and the storage for
 * tags is allocated dynamically. There is a tag storage descriptor
 * associated with each set of tag storage pages. Tag storage descriptors
 * are allocated dynamically. Since kernel will allocate a full page for
 * each tag storage descriptor, we can store up to
 * PAGE_SIZE/sizeof(tag storage descriptor) descriptors on that page.
 */
typedef struct {
	unsigned long	start;		/* Start address for this tag storage */
	unsigned long	end;		/* Last address for tag storage */
	unsigned char	*tags;		/* Where the tags are */
	unsigned long	tag_users;	/* number of references to descriptor */
} tag_storage_desc_t;

typedef struct {
	spinlock_t		lock;
	unsigned long		sparc64_ctx_val;
	unsigned long		hugetlb_pte_count;
	unsigned long		thp_pte_count;
	struct tsb_config	tsb_block[MM_NUM_TSBS];
	struct hv_tsb_descr	tsb_descr[MM_NUM_TSBS];
	void			*vdso;
	bool			adi;
	tag_storage_desc_t	*tag_store;
	spinlock_t		tag_lock;
} mm_context_t;

#endif /* !__ASSEMBLY__ */

#define TSB_CONFIG_TSB		0x00
#define TSB_CONFIG_RSS_LIMIT	0x08
#define TSB_CONFIG_NENTRIES	0x10
#define TSB_CONFIG_REG_VAL	0x18
#define TSB_CONFIG_MAP_VADDR	0x20
#define TSB_CONFIG_MAP_PTE	0x28

#endif /* __MMU_H */
掌心的温暖 是你紧握著的光芒 透过了指缝 一星半点投奔向远方