xref: /illumos-gate/usr/src/uts/i86pc/vm/hat_i86.h (revision f48205be61a214698b763ff550ab9e657525104c)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_VM_HAT_I86_H
27 #define	_VM_HAT_I86_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 /*
36  * VM - Hardware Address Translation management.
37  *
38  * This file describes the contents of the x86_64 HAT data structures.
39  */
40 #include <sys/types.h>
41 #include <sys/t_lock.h>
42 #include <sys/cpuvar.h>
43 #include <sys/x_call.h>
44 #include <vm/seg.h>
45 #include <vm/page.h>
46 #include <sys/vmparam.h>
47 #include <sys/vm_machparam.h>
48 #include <sys/promif.h>
49 #include <vm/hat_pte.h>
50 #include <vm/htable.h>
51 #include <vm/hment.h>
52 
53 /*
54  * The essential data types involved:
55  *
56  * htable_t	- There is one of these for each page table and it is used
57  *		by the HAT to manage the page table.
58  *
59  * hment_t	- Links together multiple PTEs to a single page.
60  */
61 
62 /*
63  * VLP processes have a 32 bit address range, so their top level is 2 and
64  * with only 4 PTEs in that table.
65  */
66 #define	VLP_LEVEL	(2)
67 #define	VLP_NUM_PTES	(4)
68 #define	VLP_SIZE	(VLP_NUM_PTES * sizeof (x86pte_t))
69 #define	TOP_LEVEL(h)	(((h)->hat_flags & HAT_VLP) ? VLP_LEVEL : mmu.max_level)
70 #define	VLP_COPY(fromptep, toptep) { \
71 	toptep[0] = fromptep[0]; \
72 	toptep[1] = fromptep[1]; \
73 	toptep[2] = fromptep[2]; \
74 	toptep[3] = fromptep[3]; \
75 }
76 
77 /*
78  * The hat struct exists for each address space.
79  */
80 struct hat {
81 	kmutex_t	hat_mutex;
82 	struct as	*hat_as;
83 	uint_t		hat_stats;
84 	pgcnt_t		hat_pages_mapped[MAX_PAGE_LEVEL + 1];
85 	cpuset_t	hat_cpus;
86 	uint16_t	hat_flags;
87 	htable_t	*hat_htable;	/* top level htable */
88 	struct hat	*hat_next;
89 	struct hat	*hat_prev;
90 	uint_t		hat_num_hash;	/* number of htable hash buckets */
91 	htable_t	**hat_ht_hash;	/* htable hash buckets */
92 	htable_t	*hat_ht_cached;	/* cached free htables */
93 	x86pte_t	hat_vlp_ptes[VLP_NUM_PTES];
94 };
95 typedef struct hat hat_t;
96 
97 #define	PGCNT_INC(hat, level) \
98 	atomic_add_long(&(hat)->hat_pages_mapped[level], 1);
99 #define	PGCNT_DEC(hat, level) \
100 	atomic_add_long(&(hat)->hat_pages_mapped[level], -1);
101 
102 /*
103  * Flags for the hat_flags field
104  *
105  * HAT_FREEING - set when HAT is being destroyed - mostly used to detect that
106  *	demap()s can be avoided.
107  *
108  * HAT_VLP - indicates a 32 bit process has a virtual address range less than
109  *	the hardware's physical address range. (VLP->Virtual Less-than Physical)
110  *
111  * HAT_VICTIM - This is set while a hat is being examined for page table
112  *	stealing and prevents it from being freed.
113  *
114  * HAT_SHARED - The hat has exported it's page tables via hat_share()
115  */
116 #define	HAT_FREEING	(0x0001)
117 #define	HAT_VLP		(0x0002)
118 #define	HAT_VICTIM	(0x0004)
119 #define	HAT_SHARED	(0x0008)
120 
121 /*
122  * Additional platform attribute for hat_devload() to force no caching.
123  */
124 #define	HAT_PLAT_NOCACHE	(0x100000)
125 
126 /*
127  * Simple statistics for the HAT. These are just counters that are
128  * atomically incremented. They can be reset directly from the kernel
129  * debugger.
130  */
131 struct hatstats {
132 	ulong_t	hs_reap_attempts;
133 	ulong_t	hs_reaped;
134 	ulong_t	hs_steals;
135 	ulong_t	hs_ptable_allocs;
136 	ulong_t	hs_ptable_frees;
137 	ulong_t	hs_htable_rgets;	/* allocs from reserve */
138 	ulong_t	hs_htable_rputs;	/* putbacks to reserve */
139 	ulong_t	hs_htable_shared;	/* number of htables shared */
140 	ulong_t	hs_htable_unshared;	/* number of htables unshared */
141 	ulong_t	hs_hm_alloc;
142 	ulong_t	hs_hm_free;
143 	ulong_t	hs_hm_put_reserve;
144 	ulong_t	hs_hm_get_reserve;
145 	ulong_t	hs_hm_steals;
146 	ulong_t	hs_hm_steal_exam;
147 	ulong_t hs_tlb_inval_delayed;
148 };
149 extern struct hatstats hatstat;
150 #ifdef DEBUG
151 #define	HATSTAT_INC(x)	(++hatstat.x)
152 #else
153 #define	HATSTAT_INC(x)	(0)
154 #endif
155 
156 #if defined(_KERNEL)
157 
158 /*
159  * Useful macro to align hat_XXX() address arguments to a page boundary
160  */
161 #define	ALIGN2PAGE(a)		((uintptr_t)(a) & MMU_PAGEMASK)
162 #define	IS_PAGEALIGNED(a)	(((uintptr_t)(a) & MMU_PAGEOFFSET) == 0)
163 
164 extern uint_t	khat_running;	/* set at end of hat_kern_setup() */
165 extern cpuset_t khat_cpuset;	/* cpuset for kernal address demap Xcalls */
166 extern kmutex_t hat_list_lock;
167 extern kcondvar_t hat_list_cv;
168 
169 
170 
171 /*
172  * Interfaces to setup a cpu private mapping (ie. preemption disabled).
173  * The attr and flags arguments are the same as for hat_devload().
174  * setup() must be called once, then any number of calls to remap(),
175  * followed by a final call to release()
176  *
177  * Used by ppcopy(), page_zero(), the memscrubber, and the kernel debugger.
178  */
179 typedef paddr_t hat_mempte_t;				/* phys addr of PTE */
180 extern hat_mempte_t hat_mempte_setup(caddr_t addr);
181 extern void hat_mempte_remap(pfn_t, caddr_t, hat_mempte_t,
182 	uint_t attr, uint_t flags);
183 extern void hat_mempte_release(caddr_t addr, hat_mempte_t);
184 
185 /*
186  * Interfaces to manage which thread has access to htable and hment reserves.
187  * The USE_HAT_RESERVES macro should always be recomputed in full. Its value
188  * (due to curthread) can change after any call into kmem/vmem.
189  */
190 extern uint_t can_steal_post_boot;
191 extern uint_t use_boot_reserve;
192 #define	USE_HAT_RESERVES()					\
193 	(use_boot_reserve || curthread->t_hatdepth > 1 ||	\
194 	panicstr != NULL || vmem_is_populator())
195 
196 /*
197  * initialization stuff needed by by startup, mp_startup...
198  */
199 extern void hat_cpu_online(struct cpu *);
200 extern void hat_cpu_offline(struct cpu *);
201 extern void setup_vaddr_for_ppcopy(struct cpu *);
202 extern void teardown_vaddr_for_ppcopy(struct cpu *);
203 extern void clear_boot_mappings(uintptr_t, uintptr_t);
204 
205 /*
206  * magic value to indicate that all TLB entries should be demapped.
207  */
208 #define	DEMAP_ALL_ADDR	(~(uintptr_t)0)
209 
210 /*
211  * not in any include file???
212  */
213 extern void halt(char *fmt);
214 
215 /*
216  * x86 specific routines for use online in setup or i86pc/vm files
217  */
218 extern void hat_kern_alloc(caddr_t segmap_base, size_t segmap_size,
219 	caddr_t ekernelheap);
220 extern void hat_kern_setup(void);
221 extern void hat_tlb_inval(struct hat *hat, uintptr_t va);
222 extern void hat_pte_unmap(htable_t *ht, uint_t entry, uint_t flags,
223 	x86pte_t old_pte, void *pte_ptr);
224 extern void hat_init_finish(void);
225 extern caddr_t hat_kpm_pfn2va(pfn_t pfn);
226 extern pfn_t hat_kpm_va2pfn(caddr_t);
227 extern page_t *hat_kpm_vaddr2page(caddr_t);
228 extern uintptr_t hat_kernelbase(uintptr_t);
229 extern void hat_kmap_init(uintptr_t base, size_t len);
230 
231 extern hment_t *hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry);
232 
233 /*
234  * routines to deal with delayed TLB invalidations for idle CPUs
235  */
236 extern void tlb_going_idle(void);
237 extern void tlb_service(void);
238 
239 /*
240  * Hat switch function invoked to load a new context into %cr3
241  */
242 extern void hat_switch(struct hat *hat);
243 
244 #define	pfn_is_foreign(pfn)	__lintzero
245 
246 #endif	/* _KERNEL */
247 
248 #ifdef	__cplusplus
249 }
250 #endif
251 
252 #endif	/* _VM_HAT_I86_H */
253