xref: /netbsd-src/sys/arch/xen/include/xenpmap.h (revision fad4c9f71477ae11cea2ee75ec82151ac770a534)
1 /*	$NetBSD: xenpmap.h,v 1.14 2006/03/06 19:57:31 bouyer Exp $	*/
2 
3 /*
4  *
5  * Copyright (c) 2004 Christian Limpach.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Christian Limpach.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 
35 #ifndef _XEN_XENPMAP_H_
36 #define _XEN_XENPMAP_H_
37 
38 #define	INVALID_P2M_ENTRY	(~0UL)
39 
40 void xpq_queue_machphys_update(paddr_t, paddr_t);
41 void xpq_queue_invlpg(vaddr_t);
42 void xpq_queue_pde_update(pd_entry_t *, pd_entry_t);
43 void xpq_queue_pte_update(pt_entry_t *, pt_entry_t);
44 void xpq_queue_unchecked_pte_update(pt_entry_t *, pt_entry_t);
45 void xpq_queue_pt_switch(paddr_t);
46 void xpq_flush_queue(void);
47 void xpq_queue_set_ldt(vaddr_t, uint32_t);
48 void xpq_queue_tlb_flush(void);
49 void xpq_queue_pin_table(paddr_t, int);
50 void xpq_queue_unpin_table(paddr_t);
51 int  xpq_update_foreign(pt_entry_t *, pt_entry_t, int);
52 
53 extern paddr_t *xpmap_phys_to_machine_mapping;
54 
55 #define	XPQ_PIN_L1_TABLE 1
56 #define	XPQ_PIN_L2_TABLE 2
57 
58 #ifndef XEN
59 #define	PDE_GET(_pdp)						\
60 	*(_pdp)
61 #define PDE_SET(_pdp,_mapdp,_npde)				\
62 	*(_mapdp) = (_npde)
63 #define PDE_CLEAR(_pdp,_mapdp)					\
64 	*(_mapdp) = 0
65 #define PTE_SET(_ptp,_maptp,_npte)				\
66 	*(_maptp) = (_npte)
67 #define PTE_CLEAR(_ptp,_maptp)					\
68 	*(_maptp) = 0
69 #define PTE_ATOMIC_SET(_ptp,_maptp,_npte,_opte)			\
70 	(_opte) = x86_atomic_testset_ul((_maptp), (_npte))
71 #define PTE_ATOMIC_CLEAR(_ptp,_maptp,_opte)			\
72 	(_opte) = x86_atomic_testset_ul((_maptp), 0)
73 #define PDE_CLEARBITS(_pdp,_mapdp,_bits)			\
74 	*(_mapdp) &= ~(_bits)
75 #define PTE_ATOMIC_CLEARBITS(_ptp,_maptp,_bits)			\
76 	x86_atomic_clearbits_l((_maptp), (_bits))
77 #define PTE_SETBITS(_ptp,_maptp,_bits)				\
78 	*(_maptp) |= (_bits)
79 #define PTE_ATOMIC_SETBITS(_ptp,_maptp,_bits)			\
80 	x86_atomic_setbits_l((_maptp), (_bits))
81 #else
82 paddr_t *xpmap_phys_to_machine_mapping;
83 
84 #define	PDE_GET(_pdp)						\
85 	(pmap_valid_entry(*(_pdp)) ? xpmap_mtop(*(_pdp)) : *(_pdp))
86 #define PDE_SET(_pdp,_mapdp,_npde) do {				\
87 	int _s = splvm();					\
88 	xpq_queue_pde_update((_mapdp), xpmap_ptom((_npde)));	\
89 	xpq_flush_queue();					\
90 	splx(_s);						\
91 } while (/*CONSTCOND*/0)
92 #define PDE_CLEAR(_pdp,_mapdp) do {				\
93 	int _s = splvm();					\
94 	xpq_queue_pde_update((_mapdp), 0);			\
95 	xpq_flush_queue();					\
96 	splx(_s);						\
97 } while (/*CONSTCOND*/0)
98 #define	PTE_GET(_ptp)						\
99 	(pmap_valid_entry(*(_ptp)) ? xpmap_mtop(*(_ptp)) : *(_ptp))
100 #define	PTE_GET_MA(_ptp)					\
101 	*(_ptp)
102 #define PTE_SET(_ptp,_maptp,_npte) do {				\
103 	int _s = splvm();					\
104 	xpq_queue_pte_update((_maptp), xpmap_ptom((_npte)));	\
105 	xpq_flush_queue();					\
106 	splx(_s);						\
107 } while (/*CONSTCOND*/0)
108 #define PTE_SET_MA(_ptp,_maptp,_npte) do {			\
109 	int _s = splvm();					\
110 	xpq_queue_pte_update((_maptp), (_npte));		\
111 	xpq_flush_queue();					\
112 	splx(_s);						\
113 } while (/*CONSTCOND*/0)
114 #define PTE_SET_MA_UNCHECKED(_ptp,_maptp,_npte) do {		\
115 	_s = splvm();						\
116 	xpq_queue_unchecked_pte_update((_maptp), (_npte));	\
117 	xpq_flush_queue();					\
118 	splx(_s);						\
119 } while (/*CONSTCOND*/0)
120 #define PTE_CLEAR(_ptp,_maptp) do {				\
121 	int _s = splvm();					\
122 	xpq_queue_pte_update((_maptp), 0);			\
123 	xpq_flush_queue();					\
124 	splx(_s);						\
125 } while (/*CONSTCOND*/0)
126 #define PTE_ATOMIC_SET(_ptp,_maptp,_npte,_opte) do {		\
127 	int _s;							\
128 	(_opte) = PTE_GET(_ptp);				\
129 	_s = splvm();						\
130 	xpq_queue_pte_update((_maptp), xpmap_ptom((_npte)));	\
131 	xpq_flush_queue();					\
132 	splx(_s);						\
133 } while (/*CONSTCOND*/0)
134 #define PTE_ATOMIC_SET_MA(_ptp,_maptp,_npte,_opte) do {		\
135 	int _s;							\
136 	(_opte) = *(_ptp);					\
137 	_s = splvm();						\
138 	xpq_queue_pte_update((_maptp), (_npte));		\
139 	xpq_flush_queue();					\
140 	splx(_s);						\
141 } while (/*CONSTCOND*/0)
142 #define PTE_ATOMIC_CLEAR(_ptp,_maptp,_opte) do {		\
143 	int _s;							\
144 	(_opte) = PTE_GET(_ptp);				\
145 	_s = splvm();						\
146 	xpq_queue_pte_update((_maptp), 0);			\
147 	xpq_flush_queue();					\
148 	splx(_s);						\
149 } while (/*CONSTCOND*/0)
150 #define PTE_ATOMIC_CLEAR_MA(_ptp,_maptp,_opte) do {		\
151 	int _s;							\
152 	(_opte) = *(_ptp);					\
153 	_s = splvm();						\
154 	xpq_queue_pte_update((_maptp), 0);			\
155 	xpq_flush_queue();					\
156 	splx(_s);						\
157 } while (/*CONSTCOND*/0)
158 #define PDE_CLEARBITS(_pdp,_mapdp,_bits) do {			\
159 	int _s = splvm();					\
160 	xpq_queue_pte_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
161 	xpq_flush_queue();					\
162 	splx(_s);						\
163 } while (/*CONSTCOND*/0)
164 #define PTE_CLEARBITS(_ptp,_maptp,_bits) do {			\
165 	int _s = splvm();					\
166 	xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
167 	xpq_flush_queue();					\
168 	splx(_s);						\
169 } while (/*CONSTCOND*/0)
170 #define PDE_ATOMIC_CLEARBITS(_pdp,_mapdp,_bits) do {		\
171 	int _s = splvm();					\
172 	xpq_queue_pde_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
173 	xpq_flush_queue();					\
174 	splx(_s);						\
175 } while (/*CONSTCOND*/0)
176 #define PTE_ATOMIC_CLEARBITS(_ptp,_maptp,_bits) do {		\
177 	int _s = splvm();					\
178 	xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
179 	xpq_flush_queue();					\
180 	splx(_s);						\
181 } while (/*CONSTCOND*/0)
182 #define PTE_SETBITS(_ptp,_maptp,_bits) do {			\
183 	int _s = splvm();					\
184 	xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
185 	xpq_flush_queue();					\
186 	splx(_s);						\
187 } while (/*CONSTCOND*/0)
188 #define PDE_ATOMIC_SETBITS(_pdp,_mapdp,_bits) do {		\
189 	int _s = splvm();					\
190 	xpq_queue_pde_update((_mapdp), *(_pdp) | ((_bits) & ~PG_FRAME)); \
191 	xpq_flush_queue();					\
192 	splx(_s);						\
193 } while (/*CONSTCOND*/0)
194 #define PTE_ATOMIC_SETBITS(_ptp,_maptp,_bits) do {		\
195 	int _s = splvm();					\
196 	xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
197 	xpq_flush_queue();					\
198 	splx(_s);						\
199 } while (/*CONSTCOND*/0)
200 #define PDE_COPY(_dpdp,_madpdp,_spdp) do {			\
201 	int _s = splvm();					\
202 	xpq_queue_pde_update((_madpdp), *(_spdp));		\
203 	xpq_flush_queue();					\
204 	splx(_s);						\
205 } while (/*CONSTCOND*/0)
206 #define	PTE_UPDATES_FLUSH() do {				\
207 	int _s = splvm();					\
208 	xpq_flush_queue();					\
209 	splx(_s);						\
210 } while (/*CONSTCOND*/0)
211 
212 #endif
213 
214 /*
215  * On Xen-2, the start of the day virual memory starts at KERNTEXTOFF
216  * (0xc0100000). On Xen-3 for domain0 it starts at KERNBASE (0xc0000000).
217  * So the offset between physical and virtual address is different on
218  * Xen-2 and Xen-3 for domain0.
219  */
220 #if defined(XEN3) && defined(DOM0OPS)
221 #define XPMAP_OFFSET	0
222 #else
223 #define	XPMAP_OFFSET	(KERNTEXTOFF - KERNBASE)
224 #endif
225 
226 static __inline paddr_t
227 xpmap_mtop(paddr_t mpa)
228 {
229 	return ((machine_to_phys_mapping[mpa >> PAGE_SHIFT] << PAGE_SHIFT) +
230 	    XPMAP_OFFSET) | (mpa & ~PG_FRAME);
231 }
232 
233 static __inline paddr_t
234 xpmap_ptom(paddr_t ppa)
235 {
236 	return (xpmap_phys_to_machine_mapping[(ppa -
237 	    XPMAP_OFFSET) >> PAGE_SHIFT] << PAGE_SHIFT)
238 		| (ppa & ~PG_FRAME);
239 }
240 
241 static __inline paddr_t
242 xpmap_ptom_masked(paddr_t ppa)
243 {
244 	return (xpmap_phys_to_machine_mapping[(ppa -
245 	    XPMAP_OFFSET) >> PAGE_SHIFT] << PAGE_SHIFT);
246 }
247 
248 #ifdef XEN3
249 static inline void
250 MULTI_update_va_mapping(
251 	multicall_entry_t *mcl, vaddr_t va,
252 	paddr_t new_val, unsigned long flags)
253 {
254 	mcl->op = __HYPERVISOR_update_va_mapping;
255 	mcl->args[0] = va;
256 #if defined(__x86_64__)
257 	mcl->args[1] = new_val;
258 	mcl->args[2] = flags;
259 #else
260 	mcl->args[1] = new_val;
261 	mcl->args[2] = 0;
262 	mcl->args[3] = flags;
263 #endif
264 }
265 
266 static inline void
267 MULTI_update_va_mapping_otherdomain(
268 	multicall_entry_t *mcl, vaddr_t va,
269 	paddr_t new_val, unsigned long flags, domid_t domid)
270 {
271 	mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
272 	mcl->args[0] = va;
273 #if defined(__x86_64__)
274 	mcl->args[1] = new_val;
275 	mcl->args[2] = flags;
276 	mcl->args[3] = domid;
277 #else
278 	mcl->args[1] = new_val;
279 	mcl->args[2] = 0;
280 	mcl->args[3] = flags;
281 	mcl->args[4] = domid;
282 #endif
283 }
284 #if defined(__x86_64__)
285 #define MULTI_UVMFLAGS_INDEX 2
286 #define MULTI_UVMDOMID_INDEX 3
287 #else
288 #define MULTI_UVMFLAGS_INDEX 3
289 #define MULTI_UVMDOMID_INDEX 4
290 #endif
291 
292 #endif /* XEN3 */
293 
294 #endif /* _XEN_XENPMAP_H_ */
295