xref: /illumos-gate/usr/src/uts/i86pc/vm/hat_i86.h (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Copyright (c) 2014 by Delphix. All rights reserved.
27  * Copyright 2018 Joyent, Inc.
28  */
29 
30 #ifndef	_VM_HAT_I86_H
31 #define	_VM_HAT_I86_H
32 
33 
34 #ifdef	__cplusplus
35 extern "C" {
36 #endif
37 
38 /*
39  * VM - Hardware Address Translation management.
40  *
41  * This file describes the contents of the x86_64 HAT data structures.
42  */
43 #include <sys/types.h>
44 #include <sys/t_lock.h>
45 #include <sys/cpuvar.h>
46 #include <sys/x_call.h>
47 #include <vm/seg.h>
48 #include <vm/page.h>
49 #include <sys/vmparam.h>
50 #include <sys/vm_machparam.h>
51 #include <sys/promif.h>
52 #include <vm/hat_pte.h>
53 #include <vm/htable.h>
54 #include <vm/hment.h>
55 
56 /*
57  * The essential data types involved:
58  *
59  * htable_t	- There is one of these for each page table and it is used
60  *		by the HAT to manage the page table.
61  *
62  * hment_t	- Links together multiple PTEs to a single page.
63  */
64 
65 /*
66  * Maximum number of per-CPU pagetable entries that we'll need to cache in the
67  * HAT. See the big theory statement in uts/i86pc/vm/hat_i86.c for more
68  * information.
69  */
70 #if defined(__xpv)
71 /*
72  * The Xen hypervisor does not use per-CPU pagetables (PCP). Define a single
73  * struct member for it at least to make life easier and not make the member
74  * conditional.
75  */
76 #define	MAX_COPIED_PTES	1
77 #else
78 /*
79  * The 64-bit kernel may have up to 512 PTEs present in it for a given process.
80  */
81 #define	MAX_COPIED_PTES	512
82 #endif	/* __xpv */
83 
84 #define	TOP_LEVEL(h)	(((h)->hat_max_level))
85 
86 /*
87  * The hat struct exists for each address space.
88  */
89 struct hat {
90 	kmutex_t	hat_mutex;
91 	struct as	*hat_as;
92 	uint_t		hat_stats;
93 	pgcnt_t		hat_pages_mapped[MAX_PAGE_LEVEL + 1];
94 	pgcnt_t		hat_ism_pgcnt;
95 	cpuset_t	hat_cpus;
96 	uint16_t	hat_flags;
97 	uint8_t		hat_max_level;	/* top level of this HAT */
98 	uint_t		hat_num_copied;	/* Actual num of hat_copied_ptes[] */
99 	htable_t	*hat_htable;	/* top level htable */
100 	struct hat	*hat_next;
101 	struct hat	*hat_prev;
102 	uint_t		hat_num_hash;	/* number of htable hash buckets */
103 	htable_t	**hat_ht_hash;	/* htable hash buckets */
104 	htable_t	*hat_ht_cached;	/* cached free htables */
105 	x86pte_t	hat_copied_ptes[MAX_COPIED_PTES];
106 #if defined(__amd64) && defined(__xpv)
107 	pfn_t		hat_user_ptable; /* alt top ptable for user mode */
108 #endif
109 };
110 typedef struct hat hat_t;
111 
112 #define	PGCNT_INC(hat, level)	\
113 	atomic_inc_ulong(&(hat)->hat_pages_mapped[level]);
114 #define	PGCNT_DEC(hat, level)	\
115 	atomic_dec_ulong(&(hat)->hat_pages_mapped[level]);
116 
117 /*
118  * Flags for the hat_flags field. For more information, please see the big
119  * theory statement on the HAT design in uts/i86pc/vm/hat_i86.c.
120  *
121  * HAT_FREEING - set when HAT is being destroyed - mostly used to detect that
122  *	demap()s can be avoided.
123  *
124  * HAT_COPIED - Indicates this HAT is a source for per-cpu page tables: see the
125  * 	big comment in hat_i86.c for a description.
126  *
127  * HAT_COPIED_32 - HAT_COPIED, but for an ILP32 process.
128  *
129  * HAT_VICTIM - This is set while a hat is being examined for page table
130  *	stealing and prevents it from being freed.
131  *
132  * HAT_SHARED - The hat has exported it's page tables via hat_share()
133  *
134  * HAT_PINNED - On the hypervisor, indicates the top page table has been pinned.
135  *
136  * HAT_PCP - Used for the per-cpu user page table (i.e. associated with a CPU,
137  *	not a process).
138  */
139 #define	HAT_FREEING	(0x0001)
140 #define	HAT_VICTIM	(0x0002)
141 #define	HAT_SHARED	(0x0004)
142 #define	HAT_PINNED	(0x0008)
143 #define	HAT_COPIED	(0x0010)
144 #define	HAT_COPIED_32	(0x0020)
145 #define	HAT_PCP		(0x0040)
146 
147 /*
148  * Additional platform attribute for hat_devload() to force no caching.
149  */
150 #define	HAT_PLAT_NOCACHE	(0x100000)
151 
152 /*
153  * Simple statistics for the HAT. These are just counters that are
154  * atomically incremented. They can be reset directly from the kernel
155  * debugger.
156  */
157 struct hatstats {
158 	ulong_t	hs_reap_attempts;
159 	ulong_t	hs_reaped;
160 	ulong_t	hs_steals;
161 	ulong_t	hs_ptable_allocs;
162 	ulong_t	hs_ptable_frees;
163 	ulong_t	hs_htable_rgets;	/* allocs from reserve */
164 	ulong_t	hs_htable_rputs;	/* putbacks to reserve */
165 	ulong_t	hs_htable_shared;	/* number of htables shared */
166 	ulong_t	hs_htable_unshared;	/* number of htables unshared */
167 	ulong_t	hs_hm_alloc;
168 	ulong_t	hs_hm_free;
169 	ulong_t	hs_hm_put_reserve;
170 	ulong_t	hs_hm_get_reserve;
171 	ulong_t	hs_hm_steals;
172 	ulong_t	hs_hm_steal_exam;
173 	ulong_t hs_tlb_inval_delayed;
174 	ulong_t hs_hat_copied64;
175 	ulong_t hs_hat_copied32;
176 	ulong_t hs_hat_normal64;
177 };
178 extern struct hatstats hatstat;
179 #ifdef DEBUG
180 #define	HATSTAT_INC(x)	(++hatstat.x)
181 #else
182 #define	HATSTAT_INC(x)	(0)
183 #endif
184 
185 #if defined(_KERNEL)
186 
187 /*
188  * Useful macro to align hat_XXX() address arguments to a page boundary
189  */
190 #define	ALIGN2PAGE(a)		((uintptr_t)(a) & MMU_PAGEMASK)
191 #define	IS_PAGEALIGNED(a)	(((uintptr_t)(a) & MMU_PAGEOFFSET) == 0)
192 
193 extern uint_t	khat_running;	/* set at end of hat_kern_setup() */
194 extern cpuset_t khat_cpuset;	/* cpuset for kernal address demap Xcalls */
195 extern kmutex_t hat_list_lock;
196 extern kcondvar_t hat_list_cv;
197 
198 
199 
200 /*
201  * Interfaces to setup a cpu private mapping (ie. preemption disabled).
202  * The attr and flags arguments are the same as for hat_devload().
203  * setup() must be called once, then any number of calls to remap(),
204  * followed by a final call to release()
205  *
206  * Used by ppcopy(), page_zero(), the memscrubber, and the kernel debugger.
207  */
208 typedef paddr_t hat_mempte_t;				/* phys addr of PTE */
209 extern hat_mempte_t hat_mempte_setup(caddr_t addr);
210 extern void hat_mempte_remap(pfn_t, caddr_t, hat_mempte_t,
211 	uint_t attr, uint_t flags);
212 extern void hat_mempte_release(caddr_t addr, hat_mempte_t);
213 
214 /*
215  * Interfaces to manage which thread has access to htable and hment reserves.
216  * The USE_HAT_RESERVES macro should always be recomputed in full. Its value
217  * (due to curthread) can change after any call into kmem/vmem.
218  */
219 extern uint_t can_steal_post_boot;
220 extern uint_t use_boot_reserve;
221 #define	USE_HAT_RESERVES()					\
222 	(use_boot_reserve || curthread->t_hatdepth > 1 ||	\
223 	panicstr != NULL || vmem_is_populator())
224 
225 /*
226  * initialization stuff needed by by startup, mp_startup...
227  */
228 extern void hat_cpu_online(struct cpu *);
229 extern void hat_cpu_offline(struct cpu *);
230 extern void setup_vaddr_for_ppcopy(struct cpu *);
231 extern void teardown_vaddr_for_ppcopy(struct cpu *);
232 extern void clear_boot_mappings(uintptr_t, uintptr_t);
233 
234 /*
235  * magic value to indicate that all TLB entries should be demapped.
236  */
237 #define	DEMAP_ALL_ADDR	(~(uintptr_t)0)
238 
239 /*
240  * not in any include file???
241  */
242 extern void halt(char *fmt);
243 
244 /*
245  * x86 specific routines for use online in setup or i86pc/vm files
246  */
247 extern void hat_kern_alloc(caddr_t segmap_base, size_t segmap_size,
248 	caddr_t ekernelheap);
249 extern void hat_kern_setup(void);
250 extern void hat_pte_unmap(htable_t *ht, uint_t entry, uint_t flags,
251 	x86pte_t old_pte, void *pte_ptr, boolean_t tlb);
252 extern void hat_init_finish(void);
253 extern caddr_t hat_kpm_pfn2va(pfn_t pfn);
254 extern pfn_t hat_kpm_va2pfn(caddr_t);
255 extern page_t *hat_kpm_vaddr2page(caddr_t);
256 extern uintptr_t hat_kernelbase(uintptr_t);
257 extern void hat_kmap_init(uintptr_t base, size_t len);
258 
259 extern hment_t *hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry);
260 
261 extern void mmu_calc_user_slots(void);
262 extern void hat_tlb_inval(struct hat *hat, uintptr_t va);
263 extern void hat_switch(struct hat *hat);
264 
265 #define	TLB_RANGE_LEN(r)	((r)->tr_cnt << LEVEL_SHIFT((r)->tr_level))
266 
267 /*
268  * A range of virtual pages for purposes of demapping.
269  */
270 typedef struct tlb_range {
271 	uintptr_t tr_va; 	/* address of page */
272 	ulong_t	tr_cnt; 	/* number of pages in range */
273 	int8_t	tr_level; 	/* page table level */
274 } tlb_range_t;
275 
276 #if defined(__xpv)
277 
278 #define	XPV_DISALLOW_MIGRATE()	xen_block_migrate()
279 #define	XPV_ALLOW_MIGRATE()	xen_allow_migrate()
280 
281 #define	mmu_flush_tlb_page(va)	mmu_invlpg((caddr_t)va)
282 #define	mmu_flush_tlb_kpage(va)	mmu_invlpg((caddr_t)va)
283 
284 /*
285  * Interfaces to use around code that maps/unmaps grant table references.
286  */
287 extern void hat_prepare_mapping(hat_t *, caddr_t, uint64_t *);
288 extern void hat_release_mapping(hat_t *, caddr_t);
289 
290 #else
291 
292 #define	XPV_DISALLOW_MIGRATE()	/* nothing */
293 #define	XPV_ALLOW_MIGRATE()	/* nothing */
294 
295 #define	pfn_is_foreign(pfn)	__lintzero
296 
297 typedef enum flush_tlb_type {
298 	FLUSH_TLB_ALL = 1,
299 	FLUSH_TLB_NONGLOBAL = 2,
300 	FLUSH_TLB_RANGE = 3,
301 } flush_tlb_type_t;
302 
303 extern void mmu_flush_tlb(flush_tlb_type_t, tlb_range_t *);
304 extern void mmu_flush_tlb_kpage(uintptr_t);
305 extern void mmu_flush_tlb_page(uintptr_t);
306 
307 extern void hati_cpu_punchin(cpu_t *cpu, uintptr_t va, uint_t attrs);
308 
309 /*
310  * routines to deal with delayed TLB invalidations for idle CPUs
311  */
312 extern void tlb_going_idle(void);
313 extern void tlb_service(void);
314 
315 #endif /* !__xpv */
316 
317 #endif	/* _KERNEL */
318 
319 #ifdef	__cplusplus
320 }
321 #endif
322 
323 #endif	/* _VM_HAT_I86_H */
324