debuggers.hg

view xen/include/asm-x86/shadow.h @ 4660:37be770f866c

bitkeeper revision 1.1340.1.2 (4267e33asTxlaqmSE5FbomPUak_0JQ)

Shadow mode should (for now) *not* set the _PAGE_GLOBAL mode in any of the shadow page tables.

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author maf46@burn.cl.cam.ac.uk
date Thu Apr 21 17:30:34 2005 +0000 (2005-04-21)
parents 8e987582b901
children 9a768d11cc7b
line source
1 /******************************************************************************
2 * include/asm-x86/shadow.h
3 *
4 * Copyright (c) 2005 Michael A Fetterman
5 * Based on an earlier implementation by Ian Pratt et al
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
22 #ifndef _XEN_SHADOW_H
23 #define _XEN_SHADOW_H
25 #include <xen/config.h>
26 #include <xen/types.h>
27 #include <xen/perfc.h>
28 #include <xen/sched.h>
29 #include <asm/processor.h>
30 #include <asm/domain_page.h>
31 #include <public/dom0_ops.h>
33 /* Shadow PT operation mode : shadow-mode variable in arch_domain. */
35 #define SHM_enable (1<<0) /* we're in one of the shadow modes */
36 #define SHM_log_dirty (1<<1) /* enable log dirty mode */
37 #define SHM_translate (1<<2) /* do p2m tranaltion on guest tables */
38 #define SHM_external (1<<3) /* external page table, not used by Xen */
40 #define shadow_mode_enabled(_d) ((_d)->arch.shadow_mode)
41 #define shadow_mode_log_dirty(_d) ((_d)->arch.shadow_mode & SHM_log_dirty)
42 #define shadow_mode_translate(_d) ((_d)->arch.shadow_mode & SHM_translate)
43 #define shadow_mode_external(_d) ((_d)->arch.shadow_mode & SHM_external)
45 #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
46 #define __shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START + \
47 (SH_LINEAR_PT_VIRT_START >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT))))
48 #define shadow_linear_l2_table(_ed) ((_ed)->arch.shadow_vtable)
50 // easy access to the hl2 table (for translated but not external modes only)
51 #define __linear_hl2_table ((l1_pgentry_t *)(LINEAR_PT_VIRT_START + \
52 (PERDOMAIN_VIRT_START >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT))))
54 #define shadow_lock_init(_d) spin_lock_init(&(_d)->arch.shadow_lock)
55 #define shadow_lock(_d) do { ASSERT(!spin_is_locked(&(_d)->arch.shadow_lock)); spin_lock(&(_d)->arch.shadow_lock); } while (0)
56 #define shadow_unlock(_d) spin_unlock(&(_d)->arch.shadow_lock)
58 #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
59 #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
60 #define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
62 extern void shadow_mode_init(void);
63 extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc);
64 extern int shadow_fault(unsigned long va, struct xen_regs *regs);
65 extern int shadow_mode_enable(struct domain *p, unsigned int mode);
66 extern void shadow_invlpg(struct exec_domain *, unsigned long);
67 extern struct out_of_sync_entry *shadow_mark_mfn_out_of_sync(
68 struct exec_domain *ed, unsigned long gpfn, unsigned long mfn);
69 extern void free_monitor_pagetable(struct exec_domain *ed);
70 extern void __shadow_sync_all(struct domain *d);
71 extern int __shadow_out_of_sync(struct exec_domain *ed, unsigned long va);
72 extern int set_p2m_entry(
73 struct domain *d, unsigned long pfn, unsigned long mfn);
75 static inline unsigned long __shadow_status(
76 struct domain *d, unsigned long gpfn, unsigned long stype);
77 static inline void update_hl2e(struct exec_domain *ed, unsigned long va);
79 extern void vmx_shadow_clear_state(struct domain *);
81 static inline int page_is_page_table(struct pfn_info *page)
82 {
83 return page->count_info & PGC_page_table;
84 }
86 static inline int mfn_is_page_table(unsigned long mfn)
87 {
88 if ( !pfn_valid(mfn) )
89 return 0;
91 return frame_table[mfn].count_info & PGC_page_table;
92 }
94 static inline int page_out_of_sync(struct pfn_info *page)
95 {
96 return page->count_info & PGC_out_of_sync;
97 }
99 static inline int mfn_out_of_sync(unsigned long mfn)
100 {
101 if ( !pfn_valid(mfn) )
102 return 0;
104 return frame_table[mfn].count_info & PGC_out_of_sync;
105 }
108 /************************************************************************/
110 static void inline
111 __shadow_sync_mfn(struct domain *d, unsigned long mfn)
112 {
113 if ( d->arch.out_of_sync )
114 {
115 // XXX - could be smarter
116 //
117 __shadow_sync_all(d);
118 }
119 }
121 static void inline
122 __shadow_sync_va(struct exec_domain *ed, unsigned long va)
123 {
124 struct domain *d = ed->domain;
126 if ( d->arch.out_of_sync && __shadow_out_of_sync(ed, va) )
127 {
128 perfc_incrc(shadow_sync_va);
130 // XXX - could be smarter
131 //
132 __shadow_sync_all(ed->domain);
133 }
135 // Also make sure the HL2 is up-to-date for this address.
136 //
137 if ( unlikely(shadow_mode_translate(ed->domain)) )
138 update_hl2e(ed, va);
139 }
141 static void inline
142 shadow_sync_all(struct domain *d)
143 {
144 if ( unlikely(shadow_mode_enabled(d)) )
145 {
146 shadow_lock(d);
148 if ( d->arch.out_of_sync )
149 __shadow_sync_all(d);
151 ASSERT(d->arch.out_of_sync == NULL);
153 shadow_unlock(d);
154 }
155 }
157 // SMP BUG: This routine can't ever be used properly in an SMP context.
158 // It should be something like get_shadow_and_sync_va().
159 // This probably shouldn't exist.
160 //
161 static void inline
162 shadow_sync_va(struct exec_domain *ed, unsigned long gva)
163 {
164 struct domain *d = ed->domain;
165 if ( unlikely(shadow_mode_enabled(d)) )
166 {
167 shadow_lock(d);
168 __shadow_sync_va(ed, gva);
169 shadow_unlock(d);
170 }
171 }
173 extern void __shadow_mode_disable(struct domain *d);
174 static inline void shadow_mode_disable(struct domain *d)
175 {
176 if ( shadow_mode_enabled(d) )
177 __shadow_mode_disable(d);
178 }
180 extern void shadow_mode_destroy(struct domain *d);
182 /************************************************************************/
184 #define __mfn_to_gpfn(_d, mfn) \
185 ( (shadow_mode_translate(_d)) \
186 ? machine_to_phys_mapping[(mfn)] \
187 : (mfn) )
189 #define __gpfn_to_mfn(_d, gpfn) \
190 ( (shadow_mode_translate(_d)) \
191 ? ({ ASSERT(current->domain == (_d)); \
192 phys_to_machine_mapping(gpfn); }) \
193 : (gpfn) )
195 #define __gpfn_to_mfn_foreign(_d, gpfn) \
196 ( (shadow_mode_translate(_d)) \
197 ? gpfn_to_mfn_foreign(_d, gpfn) \
198 : (gpfn) )
200 extern unsigned long gpfn_to_mfn_foreign(
201 struct domain *d, unsigned long gpfn);
203 /************************************************************************/
205 struct shadow_status {
206 struct shadow_status *next; /* Pull-to-front list per hash bucket. */
207 unsigned long gpfn_and_flags; /* Guest pfn plus flags. */
208 unsigned long smfn; /* Shadow mfn. */
209 };
211 #define shadow_ht_extra_size 128
212 #define shadow_ht_buckets 256
214 struct out_of_sync_entry {
215 struct out_of_sync_entry *next;
216 unsigned long gpfn; /* why is this here? */
217 unsigned long gmfn;
218 unsigned long snapshot_mfn;
219 unsigned long writable_pl1e; /* NB: this is a machine address */
220 };
222 #define out_of_sync_extra_size 127
224 #define SHADOW_SNAPSHOT_ELSEWHERE (-1L)
226 /************************************************************************/
227 #define SHADOW_DEBUG 0
228 #define SHADOW_VERBOSE_DEBUG 0
229 #define SHADOW_VVERBOSE_DEBUG 0
230 #define SHADOW_HASH_DEBUG 0
231 #define FULLSHADOW_DEBUG 0
233 #if SHADOW_DEBUG
234 extern int shadow_status_noswap;
235 #endif
237 #ifdef VERBOSE
238 #define SH_LOG(_f, _a...) \
239 printk("DOM%uP%u: SH_LOG(%d): " _f "\n", \
240 current->domain->id , current->processor, __LINE__ , ## _a )
241 #else
242 #define SH_LOG(_f, _a...)
243 #endif
245 #if SHADOW_VERBOSE_DEBUG
246 #define SH_VLOG(_f, _a...) \
247 printk("DOM%uP%u: SH_VLOG(%d): " _f "\n", \
248 current->domain->id, current->processor, __LINE__ , ## _a )
249 #else
250 #define SH_VLOG(_f, _a...)
251 #endif
253 #if SHADOW_VVERBOSE_DEBUG
254 #define SH_VVLOG(_f, _a...) \
255 printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n", \
256 current->domain->id, current->processor, __LINE__ , ## _a )
257 #else
258 #define SH_VVLOG(_f, _a...)
259 #endif
261 #if FULLSHADOW_DEBUG
262 #define FSH_LOG(_f, _a...) \
263 printk("DOM%uP%u: FSH_LOG(%d): " _f "\n", \
264 current->domain->id, current->processor, __LINE__ , ## _a )
265 #else
266 #define FSH_LOG(_f, _a...)
267 #endif
270 /************************************************************************/
272 static inline int
273 shadow_get_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
274 {
275 l1_pgentry_t nl1e;
276 int res;
277 unsigned long mfn;
278 struct domain *owner;
280 ASSERT(l1e_get_flags(l1e) & _PAGE_PRESENT);
282 nl1e = l1e;
283 l1e_remove_flags(&nl1e, _PAGE_GLOBAL);
284 res = get_page_from_l1e(nl1e, d);
286 if ( unlikely(!res) && IS_PRIV(d) && !shadow_mode_translate(d) &&
287 !(l1e_get_flags(l1e) & L1_DISALLOW_MASK) &&
288 (mfn = l1e_get_pfn(l1e)) &&
289 pfn_valid(mfn) &&
290 (owner = page_get_owner(pfn_to_page(l1e_get_pfn(l1e)))) &&
291 (d != owner) )
292 {
293 res = get_page_from_l1e(nl1e, owner);
294 printk("tried to map mfn %p from domain %d into shadow page tables "
295 "of domain %d; %s\n",
296 mfn, owner->id, d->id, res ? "success" : "failed");
297 }
299 if ( unlikely(!res) )
300 {
301 perfc_incrc(shadow_get_page_fail);
302 FSH_LOG("%s failed to get ref l1e=%p\n", __func__, l1e_get_value(l1e));
303 }
305 return res;
306 }
308 /************************************************************************/
310 static inline void
311 __shadow_get_l2e(
312 struct exec_domain *ed, unsigned long va, l2_pgentry_t *psl2e)
313 {
314 ASSERT(shadow_mode_enabled(ed->domain));
316 *psl2e = ed->arch.shadow_vtable[l2_table_offset(va)];
317 }
319 static inline void
320 __shadow_set_l2e(
321 struct exec_domain *ed, unsigned long va, l2_pgentry_t value)
322 {
323 ASSERT(shadow_mode_enabled(ed->domain));
325 ed->arch.shadow_vtable[l2_table_offset(va)] = value;
326 }
328 static inline void
329 __guest_get_l2e(
330 struct exec_domain *ed, unsigned long va, l2_pgentry_t *pl2e)
331 {
332 *pl2e = ed->arch.guest_vtable[l2_table_offset(va)];
333 }
335 static inline void
336 __guest_set_l2e(
337 struct exec_domain *ed, unsigned long va, l2_pgentry_t value)
338 {
339 ed->arch.guest_vtable[l2_table_offset(va)] = value;
341 if ( unlikely(shadow_mode_translate(ed->domain)) )
342 update_hl2e(ed, va);
343 }
345 static inline void
346 update_hl2e(struct exec_domain *ed, unsigned long va)
347 {
348 int index = l2_table_offset(va);
349 unsigned long mfn;
350 l2_pgentry_t gl2e = ed->arch.guest_vtable[index];
351 l1_pgentry_t old_hl2e, new_hl2e;
352 int need_flush = 0;
354 ASSERT(shadow_mode_translate(ed->domain));
356 old_hl2e = ed->arch.hl2_vtable[index];
358 if ( (l2e_get_flags(gl2e) & _PAGE_PRESENT) &&
359 VALID_MFN(mfn = phys_to_machine_mapping(l2e_get_pfn(gl2e)) ))
360 new_hl2e = l1e_create_pfn(mfn, __PAGE_HYPERVISOR);
361 else
362 new_hl2e = l1e_empty();
364 // only do the ref counting if something important changed.
365 //
366 if ( (l1e_has_changed(&old_hl2e, &new_hl2e, _PAGE_PRESENT)) )
367 {
368 if ( (l1e_get_flags(new_hl2e) & _PAGE_PRESENT) &&
369 !get_page(pfn_to_page(l1e_get_pfn(new_hl2e)), ed->domain) )
370 new_hl2e = l1e_empty();
371 if ( l1e_get_flags(old_hl2e) & _PAGE_PRESENT )
372 {
373 put_page(pfn_to_page(l1e_get_pfn(old_hl2e)));
374 need_flush = 1;
375 }
376 }
378 ed->arch.hl2_vtable[l2_table_offset(va)] = new_hl2e;
380 if ( need_flush )
381 {
382 perfc_incrc(update_hl2e_invlpg);
383 local_flush_tlb_one(&linear_pg_table[l1_linear_offset(va)]);
384 }
385 }
387 static inline void shadow_drop_references(
388 struct domain *d, struct pfn_info *page)
389 {
390 if ( likely(!shadow_mode_enabled(d)) ||
391 ((page->u.inuse.type_info & PGT_count_mask) == 0) )
392 return;
394 /* XXX This needs more thought... */
395 printk("%s: needing to call shadow_remove_all_access for mfn=%p\n",
396 __func__, page_to_pfn(page));
397 printk("Before: mfn=%p c=%p t=%p\n", page_to_pfn(page),
398 page->count_info, page->u.inuse.type_info);
400 shadow_lock(d);
401 shadow_remove_all_access(d, page_to_pfn(page));
402 shadow_unlock(d);
404 printk("After: mfn=%p c=%p t=%p\n", page_to_pfn(page),
405 page->count_info, page->u.inuse.type_info);
406 }
408 /* XXX Needs more thought. Neither pretty nor fast: a place holder. */
409 static inline void shadow_sync_and_drop_references(
410 struct domain *d, struct pfn_info *page)
411 {
412 if ( likely(!shadow_mode_enabled(d)) )
413 return;
415 shadow_lock(d);
417 if ( page_out_of_sync(page) )
418 __shadow_sync_mfn(d, page_to_pfn(page));
420 shadow_remove_all_access(d, page_to_pfn(page));
422 shadow_unlock(d);
423 }
425 /************************************************************************/
427 /*
428 * Add another shadow reference to smfn.
429 */
430 static inline int
431 get_shadow_ref(unsigned long smfn)
432 {
433 u32 x, nx;
435 ASSERT(pfn_valid(smfn));
437 x = frame_table[smfn].count_info;
438 nx = x + 1;
440 if ( unlikely(nx == 0) )
441 {
442 printk("get_shadow_ref overflow, gmfn=%p smfn=%p\n",
443 frame_table[smfn].u.inuse.type_info & PGT_mfn_mask, smfn);
444 BUG();
445 }
447 // Guarded by the shadow lock...
448 //
449 frame_table[smfn].count_info = nx;
451 return 1;
452 }
454 extern void free_shadow_page(unsigned long smfn);
456 /*
457 * Drop a shadow reference to smfn.
458 */
459 static inline void
460 put_shadow_ref(unsigned long smfn)
461 {
462 u32 x, nx;
464 ASSERT(pfn_valid(smfn));
466 x = frame_table[smfn].count_info;
467 nx = x - 1;
469 if ( unlikely(x == 0) )
470 {
471 printk("put_shadow_ref underflow, smfn=%p oc=%p t=%p\n",
472 smfn,
473 frame_table[smfn].count_info,
474 frame_table[smfn].u.inuse.type_info);
475 BUG();
476 }
478 // Guarded by the shadow lock...
479 //
480 frame_table[smfn].count_info = nx;
482 if ( unlikely(nx == 0) )
483 {
484 free_shadow_page(smfn);
485 }
486 }
488 static inline void
489 shadow_pin(unsigned long smfn)
490 {
491 ASSERT( !(frame_table[smfn].u.inuse.type_info & PGT_pinned) );
493 frame_table[smfn].u.inuse.type_info |= PGT_pinned;
494 if ( unlikely(!get_shadow_ref(smfn)) )
495 BUG();
496 }
498 static inline void
499 shadow_unpin(unsigned long smfn)
500 {
501 ASSERT( (frame_table[smfn].u.inuse.type_info & PGT_pinned) );
503 frame_table[smfn].u.inuse.type_info &= ~PGT_pinned;
504 put_shadow_ref(smfn);
505 }
508 /************************************************************************/
510 static inline int __mark_dirty(struct domain *d, unsigned int mfn)
511 {
512 unsigned long pfn;
513 int rc = 0;
515 ASSERT(spin_is_locked(&d->arch.shadow_lock));
516 ASSERT(d->arch.shadow_dirty_bitmap != NULL);
518 if ( !VALID_MFN(mfn) )
519 return rc;
521 pfn = __mfn_to_gpfn(d, mfn);
523 /*
524 * Values with the MSB set denote MFNs that aren't really part of the
525 * domain's pseudo-physical memory map (e.g., the shared info frame).
526 * Nothing to do here...
527 */
528 if ( unlikely(IS_INVALID_M2P_ENTRY(pfn)) )
529 return rc;
531 if ( likely(pfn < d->arch.shadow_dirty_bitmap_size) )
532 {
533 /* N.B. Can use non-atomic TAS because protected by shadow_lock. */
534 if ( !__test_and_set_bit(pfn, d->arch.shadow_dirty_bitmap) )
535 {
536 d->arch.shadow_dirty_count++;
537 rc = 1;
538 }
539 }
540 #ifndef NDEBUG
541 else if ( mfn < max_page )
542 {
543 SH_LOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)",
544 mfn, pfn, d->arch.shadow_dirty_bitmap_size, d);
545 SH_LOG("dom=%p caf=%08x taf=%08x\n",
546 page_get_owner(&frame_table[mfn]),
547 frame_table[mfn].count_info,
548 frame_table[mfn].u.inuse.type_info );
549 }
550 #endif
552 return rc;
553 }
556 static inline int mark_dirty(struct domain *d, unsigned int mfn)
557 {
558 int rc;
559 shadow_lock(d);
560 rc = __mark_dirty(d, mfn);
561 shadow_unlock(d);
562 return rc;
563 }
566 /************************************************************************/
568 extern void shadow_mark_va_out_of_sync(
569 struct exec_domain *ed, unsigned long gpfn, unsigned long mfn,
570 unsigned long va);
572 static inline int l1pte_write_fault(
573 struct exec_domain *ed, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
574 unsigned long va)
575 {
576 struct domain *d = ed->domain;
577 l1_pgentry_t gpte = *gpte_p;
578 l1_pgentry_t spte;
579 unsigned long gpfn = l1e_get_pfn(gpte);
580 unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
582 //printk("l1pte_write_fault gmfn=%p\n", gmfn);
584 if ( unlikely(!VALID_MFN(gmfn)) )
585 {
586 SH_LOG("l1pte_write_fault: invalid gpfn=%p", gpfn);
587 *spte_p = l1e_empty();
588 return 0;
589 }
591 ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
592 l1e_add_flags(&gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
593 spte = l1e_create_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
595 SH_VVLOG("l1pte_write_fault: updating spte=0x%p gpte=0x%p",
596 l1e_get_value(spte), l1e_get_value(gpte));
598 if ( shadow_mode_log_dirty(d) )
599 __mark_dirty(d, gmfn);
601 if ( mfn_is_page_table(gmfn) )
602 shadow_mark_va_out_of_sync(ed, gpfn, gmfn, va);
604 *gpte_p = gpte;
605 *spte_p = spte;
607 return 1;
608 }
610 static inline int l1pte_read_fault(
611 struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
612 {
613 l1_pgentry_t gpte = *gpte_p;
614 l1_pgentry_t spte = *spte_p;
615 unsigned long pfn = l1e_get_pfn(gpte);
616 unsigned long mfn = __gpfn_to_mfn(d, pfn);
618 if ( unlikely(!VALID_MFN(mfn)) )
619 {
620 SH_LOG("l1pte_read_fault: invalid gpfn=%p", pfn);
621 *spte_p = l1e_empty();
622 return 0;
623 }
625 l1e_add_flags(&gpte, _PAGE_ACCESSED);
626 spte = l1e_create_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
628 if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
629 mfn_is_page_table(mfn) )
630 {
631 l1e_remove_flags(&spte, _PAGE_RW);
632 }
634 SH_VVLOG("l1pte_read_fault: updating spte=0x%p gpte=0x%p",
635 l1e_get_value(spte), l1e_get_value(gpte));
636 *gpte_p = gpte;
637 *spte_p = spte;
639 return 1;
640 }
642 static inline void l1pte_propagate_from_guest(
643 struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p)
644 {
645 unsigned long mfn;
646 l1_pgentry_t spte;
648 spte = l1e_empty();
650 if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
651 (_PAGE_PRESENT|_PAGE_ACCESSED)) &&
652 VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) )
653 {
654 spte = l1e_create_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
656 if ( shadow_mode_log_dirty(d) ||
657 !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
658 mfn_is_page_table(mfn) )
659 {
660 l1e_remove_flags(&spte, _PAGE_RW);
661 }
662 }
664 #if 0
665 if ( l1e_get_value(spte) || l1e_get_value(gpte) )
666 SH_VVLOG("%s: gpte=%p, new spte=%p",
667 __func__, l1e_get_value(gpte), l1e_get_value(spte));
668 #endif
670 *spte_p = spte;
671 }
673 static inline void hl2e_propagate_from_guest(
674 struct domain *d, l2_pgentry_t gpde, l1_pgentry_t *hl2e_p)
675 {
676 unsigned long pfn = l2e_get_pfn(gpde);
677 unsigned long mfn;
678 l1_pgentry_t hl2e;
680 hl2e = l1e_empty();
682 if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
683 {
684 if ( unlikely((current->domain != d) && !shadow_mode_external(d)) )
685 {
686 // Can't use __gpfn_to_mfn() if we don't have one of this domain's
687 // page tables currently installed.
688 // This isn't common -- it only happens during shadow mode setup
689 // and mode changes.
690 //
691 mfn = gpfn_to_mfn_foreign(d, pfn);
692 }
693 else
694 mfn = __gpfn_to_mfn(d, pfn);
696 if ( VALID_MFN(mfn) && (mfn < max_page) )
697 hl2e = l1e_create_pfn(mfn, __PAGE_HYPERVISOR);
698 }
700 if ( l1e_get_value(hl2e) || l2e_get_value(gpde) )
701 SH_VVLOG("%s: gpde=%p hl2e=%p", __func__,
702 l2e_get_value(gpde), l1e_get_value(hl2e));
704 *hl2e_p = hl2e;
705 }
707 static inline void l2pde_general(
708 struct domain *d,
709 l2_pgentry_t *gpde_p,
710 l2_pgentry_t *spde_p,
711 unsigned long sl1mfn)
712 {
713 l2_pgentry_t gpde = *gpde_p;
714 l2_pgentry_t spde;
716 spde = l2e_empty();
717 if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
718 {
719 spde = l2e_create_pfn(sl1mfn,
720 l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED);
721 l2e_add_flags(&gpde, _PAGE_ACCESSED); /* N.B. PDEs do not have a dirty bit. */
723 // XXX mafetter: Hmm...
724 // Shouldn't the dirty log be checked/updated here?
725 // Actually, it needs to be done in this function's callers.
726 //
727 *gpde_p = gpde;
728 }
730 if ( l2e_get_value(spde) || l2e_get_value(gpde) )
731 SH_VVLOG("%s: gpde=%p, new spde=%p", __func__,
732 l2e_get_value(gpde), l2e_get_value(spde));
734 *spde_p = spde;
735 }
737 static inline void l2pde_propagate_from_guest(
738 struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
739 {
740 l2_pgentry_t gpde = *gpde_p;
741 unsigned long sl1mfn = 0;
743 if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
744 sl1mfn = __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow);
745 l2pde_general(d, gpde_p, spde_p, sl1mfn);
746 }
748 /************************************************************************/
750 // returns true if a tlb flush is needed
751 //
752 static int inline
753 validate_pte_change(
754 struct domain *d,
755 l1_pgentry_t new_pte,
756 l1_pgentry_t *shadow_pte_p)
757 {
758 l1_pgentry_t old_spte, new_spte;
760 perfc_incrc(validate_pte_calls);
762 #if 0
763 FSH_LOG("validate_pte(old=%p new=%p)", old_pte, new_pte);
764 #endif
766 old_spte = *shadow_pte_p;
767 l1pte_propagate_from_guest(d, new_pte, &new_spte);
769 // only do the ref counting if something important changed.
770 //
771 if ( ((l1e_get_value(old_spte) | l1e_get_value(new_spte)) & _PAGE_PRESENT ) &&
772 l1e_has_changed(&old_spte, &new_spte, _PAGE_RW | _PAGE_PRESENT) )
773 {
774 perfc_incrc(validate_pte_changes);
776 if ( (l1e_get_flags(new_spte) & _PAGE_PRESENT) &&
777 !shadow_get_page_from_l1e(new_spte, d) )
778 new_spte = l1e_empty();
779 if ( l1e_get_flags(old_spte) & _PAGE_PRESENT )
780 put_page_from_l1e(old_spte, d);
781 }
783 *shadow_pte_p = new_spte;
785 // paranoia rules!
786 return 1;
787 }
789 // returns true if a tlb flush is needed
790 //
791 static int inline
792 validate_hl2e_change(
793 struct domain *d,
794 l2_pgentry_t new_gpde,
795 l1_pgentry_t *shadow_hl2e_p)
796 {
797 l1_pgentry_t old_hl2e, new_hl2e;
799 perfc_incrc(validate_hl2e_calls);
801 old_hl2e = *shadow_hl2e_p;
802 hl2e_propagate_from_guest(d, new_gpde, &new_hl2e);
804 // Only do the ref counting if something important changed.
805 //
806 if ( ((l1e_get_flags(old_hl2e) | l1e_get_flags(new_hl2e)) & _PAGE_PRESENT) &&
807 l1e_has_changed(&old_hl2e, &new_hl2e, _PAGE_PRESENT) )
808 {
809 perfc_incrc(validate_hl2e_changes);
811 if ( (l1e_get_flags(new_hl2e) & _PAGE_PRESENT) &&
812 !get_page(pfn_to_page(l1e_get_pfn(new_hl2e)), d) )
813 new_hl2e = l1e_empty();
814 if ( l1e_get_flags(old_hl2e) & _PAGE_PRESENT )
815 put_page(pfn_to_page(l1e_get_pfn(old_hl2e)));
816 }
818 *shadow_hl2e_p = new_hl2e;
820 // paranoia rules!
821 return 1;
823 }
825 // returns true if a tlb flush is needed
826 //
827 static int inline
828 validate_pde_change(
829 struct domain *d,
830 l2_pgentry_t new_gpde,
831 l2_pgentry_t *shadow_pde_p)
832 {
833 l2_pgentry_t old_spde, new_spde;
835 perfc_incrc(validate_pde_calls);
837 old_spde = *shadow_pde_p;
838 l2pde_propagate_from_guest(d, &new_gpde, &new_spde);
840 // XXX Shouldn't we propagate the new_gpde to the guest?
841 // And then mark the guest's L2 page as dirty?
843 // Only do the ref counting if something important changed.
844 //
845 if ( ((l2e_get_value(old_spde) | l2e_get_value(new_spde)) & _PAGE_PRESENT) &&
846 l2e_has_changed(&old_spde, &new_spde, _PAGE_PRESENT) )
847 {
848 perfc_incrc(validate_pde_changes);
850 if ( (l2e_get_flags(new_spde) & _PAGE_PRESENT) &&
851 !get_shadow_ref(l2e_get_pfn(new_spde)) )
852 BUG();
853 if ( l2e_get_flags(old_spde) & _PAGE_PRESENT )
854 put_shadow_ref(l2e_get_pfn(old_spde));
855 }
857 *shadow_pde_p = new_spde;
859 // paranoia rules!
860 return 1;
861 }
863 /*********************************************************************/
865 #if SHADOW_HASH_DEBUG
867 static void shadow_audit(struct domain *d, int print)
868 {
869 int live = 0, free = 0, j = 0, abs;
870 struct shadow_status *a;
872 for ( j = 0; j < shadow_ht_buckets; j++ )
873 {
874 a = &d->arch.shadow_ht[j];
875 if ( a->gpfn_and_flags )
876 {
877 live++;
878 ASSERT(a->smfn);
879 }
880 else
881 ASSERT(!a->next);
883 a = a->next;
884 while ( a && (live < 9999) )
885 {
886 live++;
887 if ( (a->gpfn_and_flags == 0) || (a->smfn == 0) )
888 {
889 printk("XXX live=%d gpfn+flags=%p sp=%p next=%p\n",
890 live, a->gpfn_and_flags, a->smfn, a->next);
891 BUG();
892 }
893 ASSERT(a->smfn);
894 a = a->next;
895 }
896 ASSERT(live < 9999);
897 }
899 for ( a = d->arch.shadow_ht_free; a != NULL; a = a->next )
900 free++;
902 if ( print )
903 printk("Xlive=%d free=%d\n", live, free);
905 // BUG: this only works if there's only a single domain which is
906 // using shadow tables.
907 //
908 abs = (
909 perfc_value(shadow_l1_pages) +
910 perfc_value(shadow_l2_pages) +
911 perfc_value(hl2_table_pages) +
912 perfc_value(snapshot_pages) +
913 perfc_value(writable_pte_predictions)
914 ) - live;
915 #ifdef PERF_COUNTERS
916 if ( (abs < -1) || (abs > 1) )
917 {
918 printk("live=%d free=%d l1=%d l2=%d hl2=%d snapshot=%d writable_ptes=%d\n",
919 live, free,
920 perfc_value(shadow_l1_pages),
921 perfc_value(shadow_l2_pages),
922 perfc_value(hl2_table_pages),
923 perfc_value(snapshot_pages),
924 perfc_value(writable_pte_predictions));
925 BUG();
926 }
927 #endif
929 // XXX ought to add some code to audit the out-of-sync entries, too.
930 //
931 }
932 #else
933 #define shadow_audit(p, print) ((void)0)
934 #endif
937 static inline struct shadow_status *hash_bucket(
938 struct domain *d, unsigned int gpfn)
939 {
940 return &d->arch.shadow_ht[gpfn % shadow_ht_buckets];
941 }
944 /*
945 * N.B. This takes a guest pfn (i.e. a pfn in the guest's namespace,
946 * which, depending on full shadow mode, may or may not equal
947 * its mfn).
948 * It returns the shadow's mfn, or zero if it doesn't exist.
949 */
951 static inline unsigned long ___shadow_status(
952 struct domain *d, unsigned long gpfn, unsigned long stype)
953 {
954 struct shadow_status *p, *x, *head;
955 unsigned long key = gpfn | stype;
957 perfc_incrc(shadow_status_calls);
959 x = head = hash_bucket(d, gpfn);
960 p = NULL;
962 //SH_VVLOG("lookup gpfn=%08x type=%08x bucket=%p", gpfn, stype, x);
963 shadow_audit(d, 0);
965 do
966 {
967 ASSERT(x->gpfn_and_flags || ((x == head) && (x->next == NULL)));
969 if ( x->gpfn_and_flags == key )
970 {
971 #if SHADOW_DEBUG
972 if ( unlikely(shadow_status_noswap) )
973 return x->smfn;
974 #endif
975 /* Pull-to-front if 'x' isn't already the head item. */
976 if ( unlikely(x != head) )
977 {
978 /* Delete 'x' from list and reinsert immediately after head. */
979 p->next = x->next;
980 x->next = head->next;
981 head->next = x;
983 /* Swap 'x' contents with head contents. */
984 SWAP(head->gpfn_and_flags, x->gpfn_and_flags);
985 SWAP(head->smfn, x->smfn);
986 }
987 else
988 {
989 perfc_incrc(shadow_status_hit_head);
990 }
992 //SH_VVLOG("lookup gpfn=%p => status=%p", key, head->smfn);
993 return head->smfn;
994 }
996 p = x;
997 x = x->next;
998 }
999 while ( x != NULL );
1001 //SH_VVLOG("lookup gpfn=%p => status=0", key);
1002 perfc_incrc(shadow_status_miss);
1003 return 0;
1006 static inline unsigned long __shadow_status(
1007 struct domain *d, unsigned long gpfn, unsigned long stype)
1009 unsigned long gmfn = ((current->domain == d)
1010 ? __gpfn_to_mfn(d, gpfn)
1011 : INVALID_MFN);
1013 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1014 ASSERT(gpfn == (gpfn & PGT_mfn_mask));
1015 ASSERT(stype && !(stype & ~PGT_type_mask));
1017 if ( VALID_MFN(gmfn) && (gmfn < max_page) &&
1018 (stype != PGT_writable_pred) &&
1019 ((stype == PGT_snapshot)
1020 ? !mfn_out_of_sync(gmfn)
1021 : !mfn_is_page_table(gmfn)) )
1023 perfc_incrc(shadow_status_shortcut);
1024 #ifndef NDEBUG
1025 ASSERT(___shadow_status(d, gpfn, stype) == 0);
1027 // Undo the affects of the above ASSERT on ___shadow_status()'s perf
1028 // counters.
1029 //
1030 perfc_decrc(shadow_status_calls);
1031 perfc_decrc(shadow_status_miss);
1032 #endif
1033 return 0;
1036 return ___shadow_status(d, gpfn, stype);
1039 /*
1040 * Not clear if pull-to-front is worth while for this or not,
1041 * as it generally needs to scan the entire bucket anyway.
1042 * Much simpler without.
1044 * Either returns PGT_none, or PGT_l{1,2,3,4}_page_table.
1045 */
1046 static inline unsigned long
1047 shadow_max_pgtable_type(struct domain *d, unsigned long gpfn,
1048 unsigned long *smfn)
1050 struct shadow_status *x;
1051 unsigned long pttype = PGT_none, type;
1053 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1054 ASSERT(gpfn == (gpfn & PGT_mfn_mask));
1056 perfc_incrc(shadow_max_type);
1058 x = hash_bucket(d, gpfn);
1060 while ( x && x->gpfn_and_flags )
1062 if ( (x->gpfn_and_flags & PGT_mfn_mask) == gpfn )
1064 type = x->gpfn_and_flags & PGT_type_mask;
1066 switch ( type )
1068 case PGT_hl2_shadow:
1069 // Treat an HL2 as if it's an L1
1070 //
1071 type = PGT_l1_shadow;
1072 break;
1073 case PGT_snapshot:
1074 case PGT_writable_pred:
1075 // Ignore snapshots -- they don't in and of themselves constitute
1076 // treating a page as a page table
1077 //
1078 goto next;
1079 case PGT_base_page_table:
1080 // Early exit if we found the max possible value
1081 //
1082 return type;
1083 default:
1084 break;
1087 if ( type > pttype )
1089 pttype = type;
1090 if ( smfn )
1091 *smfn = x->smfn;
1094 next:
1095 x = x->next;
1098 return pttype;
1101 /*
1102 * N.B. We can make this locking more fine grained (e.g., per shadow page) if
1103 * it ever becomes a problem, but since we need a spin lock on the hash table
1104 * anyway it's probably not worth being too clever.
1105 */
1106 static inline unsigned long get_shadow_status(
1107 struct domain *d, unsigned long gpfn, unsigned long stype)
1109 unsigned long res;
1111 ASSERT(shadow_mode_enabled(d));
1113 /*
1114 * If we get here we know that some sort of update has happened to the
1115 * underlying page table page: either a PTE has been updated, or the page
1116 * has changed type. If we're in log dirty mode, we should set the
1117 * appropriate bit in the dirty bitmap.
1118 * N.B. The VA update path doesn't use this and is handled independently.
1120 * XXX need to think this through for vmx guests, but probably OK
1121 */
1123 shadow_lock(d);
1125 if ( shadow_mode_log_dirty(d) )
1126 __mark_dirty(d, __gpfn_to_mfn(d, gpfn));
1128 if ( !(res = __shadow_status(d, gpfn, stype)) )
1129 shadow_unlock(d);
1131 return res;
1135 static inline void put_shadow_status(struct domain *d)
1137 shadow_unlock(d);
1141 static inline void delete_shadow_status(
1142 struct domain *d, unsigned long gpfn, unsigned long gmfn, unsigned int stype)
1144 struct shadow_status *p, *x, *n, *head;
1145 unsigned long key = gpfn | stype;
1147 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1148 ASSERT(gpfn && !(gpfn & ~PGT_mfn_mask));
1149 ASSERT(stype && !(stype & ~PGT_type_mask));
1151 head = hash_bucket(d, gpfn);
1153 SH_VLOG("delete gpfn=%p t=%p bucket=%p", gpfn, stype, head);
1154 shadow_audit(d, 0);
1156 /* Match on head item? */
1157 if ( head->gpfn_and_flags == key )
1159 if ( (n = head->next) != NULL )
1161 /* Overwrite head with contents of following node. */
1162 head->gpfn_and_flags = n->gpfn_and_flags;
1163 head->smfn = n->smfn;
1165 /* Delete following node. */
1166 head->next = n->next;
1168 /* Add deleted node to the free list. */
1169 n->gpfn_and_flags = 0;
1170 n->smfn = 0;
1171 n->next = d->arch.shadow_ht_free;
1172 d->arch.shadow_ht_free = n;
1174 else
1176 /* This bucket is now empty. Initialise the head node. */
1177 head->gpfn_and_flags = 0;
1178 head->smfn = 0;
1181 goto found;
1184 p = head;
1185 x = head->next;
1187 do
1189 if ( x->gpfn_and_flags == key )
1191 /* Delete matching node. */
1192 p->next = x->next;
1194 /* Add deleted node to the free list. */
1195 x->gpfn_and_flags = 0;
1196 x->smfn = 0;
1197 x->next = d->arch.shadow_ht_free;
1198 d->arch.shadow_ht_free = x;
1200 goto found;
1203 p = x;
1204 x = x->next;
1206 while ( x != NULL );
1208 /* If we got here, it wasn't in the list! */
1209 BUG();
1211 found:
1212 // release ref to page
1213 if ( stype != PGT_writable_pred )
1214 put_page(pfn_to_page(gmfn));
1216 shadow_audit(d, 0);
1219 static inline void set_shadow_status(
1220 struct domain *d, unsigned long gpfn, unsigned long gmfn,
1221 unsigned long smfn, unsigned long stype)
1223 struct shadow_status *x, *head, *extra;
1224 int i;
1225 unsigned long key = gpfn | stype;
1227 SH_VVLOG("set gpfn=%p gmfn=%p smfn=%p t=%p", gpfn, gmfn, smfn, stype);
1229 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1231 ASSERT(shadow_mode_translate(d) || gpfn);
1232 ASSERT(!(gpfn & ~PGT_mfn_mask));
1234 // XXX - need to be more graceful.
1235 ASSERT(VALID_MFN(gmfn));
1237 ASSERT(stype && !(stype & ~PGT_type_mask));
1239 x = head = hash_bucket(d, gpfn);
1241 SH_VLOG("set gpfn=%p smfn=%p t=%p bucket=%p(%p)",
1242 gpfn, smfn, stype, x, x->next);
1243 shadow_audit(d, 0);
1245 // grab a reference to the guest page to represent the entry in the shadow
1246 // hash table
1247 //
1248 // XXX - Should PGT_writable_pred grab a page ref?
1249 // - Who/how are these hash table entry refs flushed if/when a page
1250 // is given away by the domain?
1251 //
1252 if ( stype != PGT_writable_pred )
1253 get_page(pfn_to_page(gmfn), d);
1255 /*
1256 * STEP 1. If page is already in the table, update it in place.
1257 */
1258 do
1260 if ( unlikely(x->gpfn_and_flags == key) )
1262 if ( stype != PGT_writable_pred )
1263 BUG(); // we should never replace entries into the hash table
1264 x->smfn = smfn;
1265 put_page(pfn_to_page(gmfn)); // already had a ref...
1266 goto done;
1269 x = x->next;
1271 while ( x != NULL );
1273 /*
1274 * STEP 2. The page must be inserted into the table.
1275 */
1277 /* If the bucket is empty then insert the new page as the head item. */
1278 if ( head->gpfn_and_flags == 0 )
1280 head->gpfn_and_flags = key;
1281 head->smfn = smfn;
1282 ASSERT(head->next == NULL);
1283 goto done;
1286 /* We need to allocate a new node. Ensure the quicklist is non-empty. */
1287 if ( unlikely(d->arch.shadow_ht_free == NULL) )
1289 SH_LOG("Allocate more shadow hashtable blocks.");
1291 extra = xmalloc_bytes(
1292 sizeof(void *) + (shadow_ht_extra_size * sizeof(*x)));
1294 /* XXX Should be more graceful here. */
1295 if ( extra == NULL )
1296 BUG();
1298 memset(extra, 0, sizeof(void *) + (shadow_ht_extra_size * sizeof(*x)));
1300 /* Record the allocation block so it can be correctly freed later. */
1301 d->arch.shadow_extras_count++;
1302 *((struct shadow_status **)&extra[shadow_ht_extra_size]) =
1303 d->arch.shadow_ht_extras;
1304 d->arch.shadow_ht_extras = &extra[0];
1306 /* Thread a free chain through the newly-allocated nodes. */
1307 for ( i = 0; i < (shadow_ht_extra_size - 1); i++ )
1308 extra[i].next = &extra[i+1];
1309 extra[i].next = NULL;
1311 /* Add the new nodes to the free list. */
1312 d->arch.shadow_ht_free = &extra[0];
1315 /* Allocate a new node from the quicklist. */
1316 x = d->arch.shadow_ht_free;
1317 d->arch.shadow_ht_free = x->next;
1319 /* Initialise the new node and insert directly after the head item. */
1320 x->gpfn_and_flags = key;
1321 x->smfn = smfn;
1322 x->next = head->next;
1323 head->next = x;
1325 done:
1326 shadow_audit(d, 0);
1328 if ( stype <= PGT_l4_shadow )
1330 // add to front of list of pages to check when removing write
1331 // permissions for a page...
1332 //
1336 /************************************************************************/
1338 void static inline
1339 shadow_update_min_max(unsigned long smfn, int index)
1341 struct pfn_info *sl1page = pfn_to_page(smfn);
1342 u32 min_max = sl1page->tlbflush_timestamp;
1343 int min = SHADOW_MIN(min_max);
1344 int max = SHADOW_MAX(min_max);
1345 int update = 0;
1347 if ( index < min )
1349 min = index;
1350 update = 1;
1352 if ( index > max )
1354 max = index;
1355 update = 1;
1357 if ( update )
1358 sl1page->tlbflush_timestamp = SHADOW_ENCODE_MIN_MAX(min, max);
1361 extern void shadow_map_l1_into_current_l2(unsigned long va);
1363 void static inline
1364 shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow)
1366 struct exec_domain *ed = current;
1367 struct domain *d = ed->domain;
1368 l2_pgentry_t sl2e;
1369 l1_pgentry_t old_spte;
1371 #if 0
1372 printk("shadow_set_l1e(va=%p, new_spte=%p, create=%d)\n",
1373 va, l1e_get_value(new_spte), create_l1_shadow);
1374 #endif
1376 __shadow_get_l2e(ed, va, &sl2e);
1377 if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
1379 /*
1380 * Either the L1 is not shadowed, or the shadow isn't linked into
1381 * the current shadow L2.
1382 */
1383 if ( create_l1_shadow )
1385 perfc_incrc(shadow_set_l1e_force_map);
1386 shadow_map_l1_into_current_l2(va);
1388 else /* check to see if it exists; if so, link it in */
1390 l2_pgentry_t gpde = linear_l2_table(ed)[l2_table_offset(va)];
1391 unsigned long gl1pfn = l2e_get_pfn(gpde);
1392 unsigned long sl1mfn = __shadow_status(d, gl1pfn, PGT_l1_shadow);
1394 ASSERT( l2e_get_flags(gpde) & _PAGE_PRESENT );
1396 if ( sl1mfn )
1398 perfc_incrc(shadow_set_l1e_unlinked);
1399 if ( !get_shadow_ref(sl1mfn) )
1400 BUG();
1401 l2pde_general(d, &gpde, &sl2e, sl1mfn);
1402 __guest_set_l2e(ed, va, gpde);
1403 __shadow_set_l2e(ed, va, sl2e);
1405 else
1407 // no shadow exists, so there's nothing to do.
1408 perfc_incrc(shadow_set_l1e_fail);
1409 return;
1414 old_spte = shadow_linear_pg_table[l1_linear_offset(va)];
1416 // only do the ref counting if something important changed.
1417 //
1418 if ( l1e_has_changed(&old_spte, &new_spte, _PAGE_RW | _PAGE_PRESENT) )
1420 if ( (l1e_get_flags(new_spte) & _PAGE_PRESENT) &&
1421 !shadow_get_page_from_l1e(new_spte, d) )
1422 new_spte = l1e_empty();
1423 if ( l1e_get_flags(old_spte) & _PAGE_PRESENT )
1424 put_page_from_l1e(old_spte, d);
1427 shadow_linear_pg_table[l1_linear_offset(va)] = new_spte;
1429 shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va));
1432 /************************************************************************/
1434 static inline l1_pgentry_t gva_to_gpte(unsigned long gva)
1436 l2_pgentry_t gpde;
1437 l1_pgentry_t gpte;
1438 struct exec_domain *ed = current;
1440 ASSERT( shadow_mode_translate(current->domain) );
1442 __guest_get_l2e(ed, gva, &gpde);
1443 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
1444 return l1e_empty();;
1446 // This is actually overkill - we only need to make sure the hl2
1447 // is in-sync.
1448 //
1449 shadow_sync_va(ed, gva);
1451 if ( unlikely(__copy_from_user(&gpte,
1452 &linear_pg_table[gva >> PAGE_SHIFT],
1453 sizeof(gpte))) )
1455 FSH_LOG("gva_to_gpte got a fault on gva=%p", gva);
1456 return l1e_empty();
1459 return gpte;
1462 static inline unsigned long gva_to_gpa(unsigned long gva)
1464 l1_pgentry_t gpte;
1466 gpte = gva_to_gpte(gva);
1467 if ( !(l1e_get_flags(gpte) & _PAGE_PRESENT) )
1468 return 0;
1470 return l1e_get_phys(gpte) + (gva & ~PAGE_MASK);
1473 /************************************************************************/
1475 extern void __update_pagetables(struct exec_domain *ed);
1476 static inline void update_pagetables(struct exec_domain *ed)
1478 struct domain *d = ed->domain;
1479 int paging_enabled;
1481 #ifdef CONFIG_VMX
1482 if ( VMX_DOMAIN(ed) )
1483 paging_enabled =
1484 test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state);
1485 else
1486 #endif
1487 // HACK ALERT: there's currently no easy way to figure out if a domU
1488 // has set its arch.guest_table to zero, vs not yet initialized it.
1489 //
1490 paging_enabled = !!pagetable_val(ed->arch.guest_table);
1492 /*
1493 * We don't call __update_pagetables() when vmx guest paging is
1494 * disabled as we want the linear_pg_table to be inaccessible so that
1495 * we bail out early of shadow_fault() if the vmx guest tries illegal
1496 * accesses while it thinks paging is turned off.
1497 */
1498 if ( unlikely(shadow_mode_enabled(d)) && paging_enabled )
1500 shadow_lock(d);
1501 __update_pagetables(ed);
1502 shadow_unlock(d);
1505 if ( likely(!shadow_mode_external(d)) )
1507 #ifdef __x86_64__
1508 if ( !(ed->arch.flags & TF_kernel_mode) )
1509 ed->arch.monitor_table = ed->arch.guest_table_user;
1510 else
1511 #endif
1512 if ( shadow_mode_enabled(d) )
1513 ed->arch.monitor_table = ed->arch.shadow_table;
1514 else
1515 ed->arch.monitor_table = ed->arch.guest_table;
1519 #if SHADOW_DEBUG
1520 extern int _check_pagetable(struct exec_domain *ed, char *s);
1521 extern int _check_all_pagetables(struct exec_domain *ed, char *s);
1523 #define check_pagetable(_ed, _s) _check_pagetable(_ed, _s)
1524 //#define check_pagetable(_ed, _s) _check_all_pagetables(_ed, _s)
1526 #else
1527 #define check_pagetable(_ed, _s) ((void)0)
1528 #endif
1530 #endif /* XEN_SHADOW_H */
1532 /*
1533 * Local variables:
1534 * mode: C
1535 * c-set-style: "BSD"
1536 * c-basic-offset: 4
1537 * tab-width: 4
1538 * indent-tabs-mode: nil
1539 * End:
1540 */