debuggers.hg

view xen/include/asm-x86/paging.h @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 1b1174b7181f
children
line source
1 /******************************************************************************
2 * include/asm-x86/paging.h
3 *
4 * Common interface for paging support
5 * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
6 * Parts of this code are Copyright (c) 2006 by XenSource Inc.
7 * Parts of this code are Copyright (c) 2006 by Michael A Fetterman
8 * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
25 #ifndef _XEN_PAGING_H
26 #define _XEN_PAGING_H
28 #include <xen/mm.h>
29 #include <public/domctl.h>
30 #include <xen/sched.h>
31 #include <xen/perfc.h>
32 #include <xen/domain_page.h>
33 #include <asm/flushtlb.h>
34 #include <asm/domain.h>
36 /*****************************************************************************
37 * Macros to tell which paging mode a domain is in */
39 #define PG_SH_shift 20
40 #define PG_HAP_shift 21
41 /* We're in one of the shadow modes */
42 #define PG_SH_enable (1U << PG_SH_shift)
43 #define PG_HAP_enable (1U << PG_HAP_shift)
45 /* common paging mode bits */
46 #define PG_mode_shift 10
47 /* Refcounts based on shadow tables instead of guest tables */
48 #define PG_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << PG_mode_shift)
49 /* Enable log dirty mode */
50 #define PG_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << PG_mode_shift)
51 /* Xen does p2m translation, not guest */
52 #define PG_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << PG_mode_shift)
53 /* Xen does not steal address space from the domain for its own booking;
54 * requires VT or similar mechanisms */
55 #define PG_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << PG_mode_shift)
57 #define paging_mode_enabled(_d) ((_d)->arch.paging.mode)
58 #define paging_mode_shadow(_d) ((_d)->arch.paging.mode & PG_SH_enable)
59 #define paging_mode_hap(_d) ((_d)->arch.paging.mode & PG_HAP_enable)
61 #define paging_mode_refcounts(_d) ((_d)->arch.paging.mode & PG_refcounts)
62 #define paging_mode_log_dirty(_d) ((_d)->arch.paging.mode & PG_log_dirty)
63 #define paging_mode_translate(_d) ((_d)->arch.paging.mode & PG_translate)
64 #define paging_mode_external(_d) ((_d)->arch.paging.mode & PG_external)
66 /* flags used for paging debug */
67 #define PAGING_DEBUG_LOGDIRTY 0
69 /*****************************************************************************
70 * Mode-specific entry points into the shadow code.
71 *
72 * These shouldn't be used directly by callers; rather use the functions
73 * below which will indirect through this table as appropriate. */
75 struct sh_emulate_ctxt;
76 struct shadow_paging_mode {
77 void (*detach_old_tables )(struct vcpu *v);
78 int (*x86_emulate_write )(struct vcpu *v, unsigned long va,
79 void *src, u32 bytes,
80 struct sh_emulate_ctxt *sh_ctxt);
81 int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va,
82 unsigned long old,
83 unsigned long new,
84 unsigned int bytes,
85 struct sh_emulate_ctxt *sh_ctxt);
86 #ifdef __i386__
87 int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va,
88 unsigned long old_lo,
89 unsigned long old_hi,
90 unsigned long new_lo,
91 unsigned long new_hi,
92 struct sh_emulate_ctxt *sh_ctxt);
93 #endif
94 mfn_t (*make_monitor_table )(struct vcpu *v);
95 void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
96 int (*guess_wrmap )(struct vcpu *v,
97 unsigned long vaddr, mfn_t gmfn);
98 void (*pagetable_dying )(struct vcpu *v, paddr_t gpa);
99 /* For outsiders to tell what mode we're in */
100 unsigned int shadow_levels;
101 };
104 /************************************************/
105 /* common paging interface */
106 /************************************************/
107 struct paging_mode {
108 int (*page_fault )(struct vcpu *v, unsigned long va,
109 struct cpu_user_regs *regs);
110 int (*invlpg )(struct vcpu *v, unsigned long va);
111 unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va,
112 uint32_t *pfec);
113 void (*update_cr3 )(struct vcpu *v, int do_locking);
114 void (*update_paging_modes )(struct vcpu *v);
115 void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn,
116 l1_pgentry_t *p, mfn_t table_mfn,
117 l1_pgentry_t new,
118 unsigned int level);
119 int (*write_guest_entry )(struct vcpu *v, intpte_t *p,
120 intpte_t new, mfn_t gmfn);
121 int (*cmpxchg_guest_entry )(struct vcpu *v, intpte_t *p,
122 intpte_t *old, intpte_t new,
123 mfn_t gmfn);
124 void * (*guest_map_l1e )(struct vcpu *v, unsigned long va,
125 unsigned long *gl1mfn);
126 void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va,
127 void *eff_l1e);
128 unsigned int guest_levels;
130 /* paging support extension */
131 struct shadow_paging_mode shadow;
132 };
134 /*****************************************************************************
135 * Log dirty code */
137 /* free log dirty bitmap resource */
138 void paging_free_log_dirty_bitmap(struct domain *d);
140 /* get the dirty bitmap for a specific range of pfns */
141 int paging_log_dirty_range(struct domain *d,
142 unsigned long begin_pfn,
143 unsigned long nr,
144 XEN_GUEST_HANDLE_64(uint8) dirty_bitmap);
146 /* enable log dirty */
147 int paging_log_dirty_enable(struct domain *d);
149 /* disable log dirty */
150 int paging_log_dirty_disable(struct domain *d);
152 /* log dirty initialization */
153 void paging_log_dirty_init(struct domain *d,
154 int (*enable_log_dirty)(struct domain *d),
155 int (*disable_log_dirty)(struct domain *d),
156 void (*clean_dirty_bitmap)(struct domain *d));
158 /* mark a page as dirty */
159 void paging_mark_dirty(struct domain *d, unsigned long guest_mfn);
161 /* is this guest page dirty? */
162 int paging_mfn_is_dirty(struct domain *d, mfn_t gmfn);
164 /*
165 * Log-dirty radix tree indexing:
166 * All tree nodes are PAGE_SIZE bytes, mapped on-demand.
167 * Leaf nodes are simple bitmaps; 1 bit per guest pfn.
168 * Interior nodes are arrays of LOGDIRTY_NODE_ENTRIES mfns.
169 * TODO: Dynamic radix tree height. Most guests will only need 2 levels.
170 * The fourth level is basically unusable on 32-bit Xen.
171 * TODO2: Abstract out the radix-tree mechanics?
172 */
173 #define LOGDIRTY_NODE_ENTRIES (1 << PAGETABLE_ORDER)
174 #define L1_LOGDIRTY_IDX(pfn) ((pfn) & ((1 << (PAGE_SHIFT+3)) - 1))
175 #define L2_LOGDIRTY_IDX(pfn) (((pfn) >> (PAGE_SHIFT+3)) & \
176 (LOGDIRTY_NODE_ENTRIES-1))
177 #define L3_LOGDIRTY_IDX(pfn) (((pfn) >> (PAGE_SHIFT+3+PAGETABLE_ORDER)) & \
178 (LOGDIRTY_NODE_ENTRIES-1))
179 #if BITS_PER_LONG == 64
180 #define L4_LOGDIRTY_IDX(pfn) (((pfn) >> (PAGE_SHIFT+3+PAGETABLE_ORDER*2)) & \
181 (LOGDIRTY_NODE_ENTRIES-1))
182 #else
183 #define L4_LOGDIRTY_IDX(pfn) 0
184 #endif
186 /* VRAM dirty tracking support */
187 struct sh_dirty_vram {
188 unsigned long begin_pfn;
189 unsigned long end_pfn;
190 paddr_t *sl1ma;
191 uint8_t *dirty_bitmap;
192 s_time_t last_dirty;
193 };
195 /*****************************************************************************
196 * Entry points into the paging-assistance code */
198 /* Initialize the paging resource for vcpu struct. It is called by
199 * vcpu_initialise() in domain.c */
200 void paging_vcpu_init(struct vcpu *v);
202 /* Set up the paging-assistance-specific parts of a domain struct at
203 * start of day. Called for every domain from arch_domain_create() */
204 int paging_domain_init(struct domain *d, unsigned int domcr_flags);
206 /* Handler for paging-control ops: operations from user-space to enable
207 * and disable ephemeral shadow modes (test mode and log-dirty mode) and
208 * manipulate the log-dirty bitmap. */
209 int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
210 XEN_GUEST_HANDLE(void) u_domctl);
212 /* Call when destroying a domain */
213 void paging_teardown(struct domain *d);
215 /* Call once all of the references to the domain have gone away */
216 void paging_final_teardown(struct domain *d);
218 /* Enable an arbitrary paging-assistance mode. Call once at domain
219 * creation. */
220 int paging_enable(struct domain *d, u32 mode);
223 /* Page fault handler
224 * Called from pagefault handler in Xen, and from the HVM trap handlers
225 * for pagefaults. Returns 1 if this fault was an artefact of the
226 * paging code (and the guest should retry) or 0 if it is not (and the
227 * fault should be handled elsewhere or passed to the guest).
228 *
229 * Note: under shadow paging, this function handles all page faults;
230 * however, for hardware-assisted paging, this function handles only
231 * host page faults (i.e. nested page faults). */
232 static inline int
233 paging_fault(unsigned long va, struct cpu_user_regs *regs)
234 {
235 struct vcpu *v = current;
236 return v->arch.paging.mode->page_fault(v, va, regs);
237 }
239 /* Handle invlpg requests on vcpus.
240 * Returns 1 if the invlpg instruction should be issued on the hardware,
241 * or 0 if it's safe not to do so. */
242 static inline int paging_invlpg(struct vcpu *v, unsigned long va)
243 {
244 return v->arch.paging.mode->invlpg(v, va);
245 }
247 /* Translate a guest virtual address to the frame number that the
248 * *guest* pagetables would map it to. Returns INVALID_GFN if the guest
249 * tables don't map this address for this kind of access.
250 * pfec[0] is used to determine which kind of access this is when
251 * walking the tables. The caller should set the PFEC_page_present bit
252 * in pfec[0]; in the failure case, that bit will be cleared if appropriate. */
253 #define INVALID_GFN (-1UL)
254 static inline unsigned long paging_gva_to_gfn(struct vcpu *v,
255 unsigned long va,
256 uint32_t *pfec)
257 {
258 return v->arch.paging.mode->gva_to_gfn(v, va, pfec);
259 }
261 /* Update all the things that are derived from the guest's CR3.
262 * Called when the guest changes CR3; the caller can then use v->arch.cr3
263 * as the value to load into the host CR3 to schedule this vcpu */
264 static inline void paging_update_cr3(struct vcpu *v)
265 {
266 v->arch.paging.mode->update_cr3(v, 1);
267 }
269 /* Update all the things that are derived from the guest's CR0/CR3/CR4.
270 * Called to initialize paging structures if the paging mode
271 * has changed, and when bringing up a VCPU for the first time. */
272 static inline void paging_update_paging_modes(struct vcpu *v)
273 {
274 v->arch.paging.mode->update_paging_modes(v);
275 }
278 /* Write a new value into the guest pagetable, and update the
279 * paging-assistance state appropriately. Returns 0 if we page-faulted,
280 * 1 for success. */
281 static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p,
282 intpte_t new, mfn_t gmfn)
283 {
284 if ( unlikely(paging_mode_enabled(v->domain)
285 && v->arch.paging.mode != NULL) )
286 return v->arch.paging.mode->write_guest_entry(v, p, new, gmfn);
287 else
288 return (!__copy_to_user(p, &new, sizeof(new)));
289 }
292 /* Cmpxchg a new value into the guest pagetable, and update the
293 * paging-assistance state appropriately. Returns 0 if we page-faulted,
294 * 1 if not. N.B. caller should check the value of "old" to see if the
295 * cmpxchg itself was successful. */
296 static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
297 intpte_t *old, intpte_t new,
298 mfn_t gmfn)
299 {
300 if ( unlikely(paging_mode_enabled(v->domain)
301 && v->arch.paging.mode != NULL) )
302 return v->arch.paging.mode->cmpxchg_guest_entry(v, p, old, new, gmfn);
303 else
304 return (!cmpxchg_user(p, *old, new));
305 }
307 /* Helper function that writes a pte in such a way that a concurrent read
308 * never sees a half-written entry that has _PAGE_PRESENT set */
309 static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new)
310 {
311 #if CONFIG_PAGING_LEVELS == 3
312 /* PAE machines write 64bit PTEs as two 32bit writes. */
313 volatile unsigned long *d = (unsigned long *) p;
314 unsigned long *s = (unsigned long *) &new;
315 BUILD_BUG_ON(sizeof (l1_pgentry_t) != 2 * sizeof (unsigned long));
316 d[0] = 0;
317 d[1] = s[1];
318 d[0] = s[0];
319 #else
320 *p = new;
321 #endif
322 }
324 /* Atomically write a P2M entry and update the paging-assistance state
325 * appropriately.
326 * Arguments: the domain in question, the GFN whose mapping is being updated,
327 * a pointer to the entry to be written, the MFN in which the entry resides,
328 * the new contents of the entry, and the level in the p2m tree at which
329 * we are writing. */
330 static inline void paging_write_p2m_entry(struct domain *d, unsigned long gfn,
331 l1_pgentry_t *p, mfn_t table_mfn,
332 l1_pgentry_t new, unsigned int level)
333 {
334 struct vcpu *v = current;
335 if ( v->domain != d )
336 v = d->vcpu ? d->vcpu[0] : NULL;
337 if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
338 {
339 return v->arch.paging.mode->write_p2m_entry(v, gfn, p, table_mfn,
340 new, level);
341 }
342 else
343 safe_write_pte(p, new);
344 }
346 /* Called from the guest to indicate that the a process is being
347 * torn down and its pagetables will soon be discarded */
348 void pagetable_dying(struct domain *d, paddr_t gpa);
350 /* Print paging-assistance info to the console */
351 void paging_dump_domain_info(struct domain *d);
352 void paging_dump_vcpu_info(struct vcpu *v);
355 /*****************************************************************************
356 * Access to the guest pagetables */
358 /* Get a mapping of a PV guest's l1e for this virtual address. */
359 static inline l1_pgentry_t *
360 guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn)
361 {
362 l2_pgentry_t l2e;
364 if ( unlikely(paging_mode_translate(v->domain)) )
365 return v->arch.paging.mode->guest_map_l1e(v, addr, gl1mfn);
367 /* Find this l1e and its enclosing l1mfn in the linear map */
368 if ( __copy_from_user(&l2e,
369 &__linear_l2_table[l2_linear_offset(addr)],
370 sizeof(l2_pgentry_t)) != 0 )
371 return NULL;
372 /* Check flags that it will be safe to read the l1e */
373 if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE))
374 != _PAGE_PRESENT )
375 return NULL;
376 *gl1mfn = l2e_get_pfn(l2e);
377 return (l1_pgentry_t *)map_domain_page(*gl1mfn) + l1_table_offset(addr);
378 }
380 /* Pull down the mapping we got from guest_map_l1e() */
381 static inline void
382 guest_unmap_l1e(struct vcpu *v, void *p)
383 {
384 unmap_domain_page(p);
385 }
387 /* Read the guest's l1e that maps this address. */
388 static inline void
389 guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e)
390 {
391 if ( likely(!paging_mode_translate(v->domain)) )
392 {
393 ASSERT(!paging_mode_external(v->domain));
394 if ( __copy_from_user(eff_l1e,
395 &__linear_l1_table[l1_linear_offset(addr)],
396 sizeof(l1_pgentry_t)) != 0 )
397 *(l1_pgentry_t *)eff_l1e = l1e_empty();
398 return;
399 }
401 v->arch.paging.mode->guest_get_eff_l1e(v, addr, eff_l1e);
402 }
404 /* Read the guest's l1e that maps this address, from the kernel-mode
405 * pagetables. */
406 static inline void
407 guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e)
408 {
409 #if defined(__x86_64__)
410 int user_mode = !(v->arch.flags & TF_kernel_mode);
411 #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v)
412 #else
413 #define TOGGLE_MODE() ((void)0)
414 #endif
416 TOGGLE_MODE();
417 guest_get_eff_l1e(v, addr, eff_l1e);
418 TOGGLE_MODE();
419 }
423 #endif /* XEN_PAGING_H */
425 /*
426 * Local variables:
427 * mode: C
428 * c-set-style: "BSD"
429 * c-basic-offset: 4
430 * indent-tabs-mode: nil
431 * End:
432 */