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