debuggers.hg

view xen/include/asm-x86/shadow.h @ 4671:18a8f5216548

bitkeeper revision 1.1366 (4268c126o36cKcnzrSkVxkbrPsoz1g)

Clean up shadow destruction and fix domain destroy when shadow mode
is disabled.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Apr 22 09:17:26 2005 +0000 (2005-04-22)
parents 303fb016437c
children ccc4ee412321
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_tainted_refcnts(_d) ((_d)->arch.shadow_tainted_refcnts)
47 #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
48 #define __shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START + \
49 (SH_LINEAR_PT_VIRT_START >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT))))
50 #define shadow_linear_l2_table(_ed) ((_ed)->arch.shadow_vtable)
52 // easy access to the hl2 table (for translated but not external modes only)
53 #define __linear_hl2_table ((l1_pgentry_t *)(LINEAR_PT_VIRT_START + \
54 (PERDOMAIN_VIRT_START >> (L2_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT))))
56 #define shadow_lock_init(_d) spin_lock_init(&(_d)->arch.shadow_lock)
57 #define shadow_lock(_d) do { ASSERT(!spin_is_locked(&(_d)->arch.shadow_lock)); spin_lock(&(_d)->arch.shadow_lock); } while (0)
58 #define shadow_unlock(_d) spin_unlock(&(_d)->arch.shadow_lock)
60 #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
61 #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
62 #define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
64 extern void shadow_mode_init(void);
65 extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc);
66 extern int shadow_fault(unsigned long va, struct xen_regs *regs);
67 extern int shadow_mode_enable(struct domain *p, unsigned int mode);
68 extern void shadow_invlpg(struct exec_domain *, unsigned long);
69 extern struct out_of_sync_entry *shadow_mark_mfn_out_of_sync(
70 struct exec_domain *ed, unsigned long gpfn, unsigned long mfn);
71 extern void free_monitor_pagetable(struct exec_domain *ed);
72 extern void __shadow_sync_all(struct domain *d);
73 extern int __shadow_out_of_sync(struct exec_domain *ed, unsigned long va);
74 extern int set_p2m_entry(
75 struct domain *d, unsigned long pfn, unsigned long mfn);
77 static inline unsigned long __shadow_status(
78 struct domain *d, unsigned long gpfn, unsigned long stype);
79 static inline void update_hl2e(struct exec_domain *ed, unsigned long va);
81 extern void vmx_shadow_clear_state(struct domain *);
83 static inline int page_is_page_table(struct pfn_info *page)
84 {
85 return page->count_info & PGC_page_table;
86 }
88 static inline int mfn_is_page_table(unsigned long mfn)
89 {
90 if ( !pfn_valid(mfn) )
91 return 0;
93 return frame_table[mfn].count_info & PGC_page_table;
94 }
96 static inline int page_out_of_sync(struct pfn_info *page)
97 {
98 return page->count_info & PGC_out_of_sync;
99 }
101 static inline int mfn_out_of_sync(unsigned long mfn)
102 {
103 if ( !pfn_valid(mfn) )
104 return 0;
106 return frame_table[mfn].count_info & PGC_out_of_sync;
107 }
110 /************************************************************************/
112 static void inline
113 __shadow_sync_mfn(struct domain *d, unsigned long mfn)
114 {
115 if ( d->arch.out_of_sync )
116 {
117 // XXX - could be smarter
118 //
119 __shadow_sync_all(d);
120 }
121 }
123 static void inline
124 __shadow_sync_va(struct exec_domain *ed, unsigned long va)
125 {
126 struct domain *d = ed->domain;
128 if ( d->arch.out_of_sync && __shadow_out_of_sync(ed, va) )
129 {
130 perfc_incrc(shadow_sync_va);
132 // XXX - could be smarter
133 //
134 __shadow_sync_all(ed->domain);
135 }
137 // Also make sure the HL2 is up-to-date for this address.
138 //
139 if ( unlikely(shadow_mode_translate(ed->domain)) )
140 update_hl2e(ed, va);
141 }
143 static void inline
144 shadow_sync_all(struct domain *d)
145 {
146 if ( unlikely(shadow_mode_enabled(d)) )
147 {
148 shadow_lock(d);
150 if ( d->arch.out_of_sync )
151 __shadow_sync_all(d);
153 ASSERT(d->arch.out_of_sync == NULL);
155 shadow_unlock(d);
156 }
157 }
159 // SMP BUG: This routine can't ever be used properly in an SMP context.
160 // It should be something like get_shadow_and_sync_va().
161 // This probably shouldn't exist.
162 //
163 static void inline
164 shadow_sync_va(struct exec_domain *ed, unsigned long gva)
165 {
166 struct domain *d = ed->domain;
167 if ( unlikely(shadow_mode_enabled(d)) )
168 {
169 shadow_lock(d);
170 __shadow_sync_va(ed, gva);
171 shadow_unlock(d);
172 }
173 }
175 extern void __shadow_mode_disable(struct domain *d);
176 static inline void shadow_mode_disable(struct domain *d)
177 {
178 if ( unlikely(shadow_mode_enabled(d)) )
179 {
180 shadow_lock(d);
181 __shadow_mode_disable(d);
182 shadow_unlock(d);
183 }
184 }
186 /************************************************************************/
188 #define __mfn_to_gpfn(_d, mfn) \
189 ( (shadow_mode_translate(_d)) \
190 ? machine_to_phys_mapping[(mfn)] \
191 : (mfn) )
193 #define __gpfn_to_mfn(_d, gpfn) \
194 ( (shadow_mode_translate(_d)) \
195 ? ({ ASSERT(current->domain == (_d)); \
196 phys_to_machine_mapping(gpfn); }) \
197 : (gpfn) )
199 #define __gpfn_to_mfn_foreign(_d, gpfn) \
200 ( (shadow_mode_translate(_d)) \
201 ? gpfn_to_mfn_foreign(_d, gpfn) \
202 : (gpfn) )
204 extern unsigned long gpfn_to_mfn_foreign(
205 struct domain *d, unsigned long gpfn);
207 /************************************************************************/
209 struct shadow_status {
210 struct shadow_status *next; /* Pull-to-front list per hash bucket. */
211 unsigned long gpfn_and_flags; /* Guest pfn plus flags. */
212 unsigned long smfn; /* Shadow mfn. */
213 };
215 #define shadow_ht_extra_size 128
216 #define shadow_ht_buckets 256
218 struct out_of_sync_entry {
219 struct out_of_sync_entry *next;
220 unsigned long gpfn; /* why is this here? */
221 unsigned long gmfn;
222 unsigned long snapshot_mfn;
223 unsigned long writable_pl1e; /* NB: this is a machine address */
224 };
226 #define out_of_sync_extra_size 127
228 #define SHADOW_SNAPSHOT_ELSEWHERE (-1L)
230 /************************************************************************/
231 #define SHADOW_DEBUG 0
232 #define SHADOW_VERBOSE_DEBUG 0
233 #define SHADOW_VVERBOSE_DEBUG 0
234 #define SHADOW_VVVERBOSE_DEBUG 0
235 #define SHADOW_HASH_DEBUG 0
236 #define FULLSHADOW_DEBUG 0
238 #if SHADOW_DEBUG
239 extern int shadow_status_noswap;
240 #endif
242 #ifdef VERBOSE
243 #define SH_LOG(_f, _a...) \
244 printk("DOM%uP%u: SH_LOG(%d): " _f "\n", \
245 current->domain->id , current->processor, __LINE__ , ## _a )
246 #else
247 #define SH_LOG(_f, _a...) ((void)0)
248 #endif
250 #if SHADOW_VERBOSE_DEBUG
251 #define SH_VLOG(_f, _a...) \
252 printk("DOM%uP%u: SH_VLOG(%d): " _f "\n", \
253 current->domain->id, current->processor, __LINE__ , ## _a )
254 #else
255 #define SH_VLOG(_f, _a...) ((void)0)
256 #endif
258 #if SHADOW_VVERBOSE_DEBUG
259 #define SH_VVLOG(_f, _a...) \
260 printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n", \
261 current->domain->id, current->processor, __LINE__ , ## _a )
262 #else
263 #define SH_VVLOG(_f, _a...) ((void)0)
264 #endif
266 #if SHADOW_VVVERBOSE_DEBUG
267 #define SH_VVVLOG(_f, _a...) \
268 printk("DOM%uP%u: SH_VVVLOG(%d): " _f "\n", \
269 current->domain->id, current->processor, __LINE__ , ## _a )
270 #else
271 #define SH_VVVLOG(_f, _a...) ((void)0)
272 #endif
274 #if FULLSHADOW_DEBUG
275 #define FSH_LOG(_f, _a...) \
276 printk("DOM%uP%u: FSH_LOG(%d): " _f "\n", \
277 current->domain->id, current->processor, __LINE__ , ## _a )
278 #else
279 #define FSH_LOG(_f, _a...) ((void)0)
280 #endif
283 /************************************************************************/
285 static inline int
286 shadow_get_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
287 {
288 l1_pgentry_t nl1e;
289 int res;
290 unsigned long mfn;
291 struct domain *owner;
293 ASSERT(l1e_get_flags(l1e) & _PAGE_PRESENT);
295 nl1e = l1e;
296 l1e_remove_flags(&nl1e, _PAGE_GLOBAL);
297 res = get_page_from_l1e(nl1e, d);
299 if ( unlikely(!res) && IS_PRIV(d) && !shadow_mode_translate(d) &&
300 !(l1e_get_flags(l1e) & L1_DISALLOW_MASK) &&
301 (mfn = l1e_get_pfn(l1e)) &&
302 pfn_valid(mfn) &&
303 (owner = page_get_owner(pfn_to_page(l1e_get_pfn(l1e)))) &&
304 (d != owner) )
305 {
306 res = get_page_from_l1e(nl1e, owner);
307 printk("tried to map mfn %p from domain %d into shadow page tables "
308 "of domain %d; %s\n",
309 mfn, owner->id, d->id, res ? "success" : "failed");
310 }
312 if ( unlikely(!res) )
313 {
314 perfc_incrc(shadow_get_page_fail);
315 FSH_LOG("%s failed to get ref l1e=%p\n", __func__, l1e_get_value(l1e));
316 }
318 return res;
319 }
321 /************************************************************************/
323 static inline void
324 __shadow_get_l2e(
325 struct exec_domain *ed, unsigned long va, l2_pgentry_t *psl2e)
326 {
327 ASSERT(shadow_mode_enabled(ed->domain));
329 *psl2e = ed->arch.shadow_vtable[l2_table_offset(va)];
330 }
332 static inline void
333 __shadow_set_l2e(
334 struct exec_domain *ed, unsigned long va, l2_pgentry_t value)
335 {
336 ASSERT(shadow_mode_enabled(ed->domain));
338 ed->arch.shadow_vtable[l2_table_offset(va)] = value;
339 }
341 static inline void
342 __guest_get_l2e(
343 struct exec_domain *ed, unsigned long va, l2_pgentry_t *pl2e)
344 {
345 *pl2e = ed->arch.guest_vtable[l2_table_offset(va)];
346 }
348 static inline void
349 __guest_set_l2e(
350 struct exec_domain *ed, unsigned long va, l2_pgentry_t value)
351 {
352 ed->arch.guest_vtable[l2_table_offset(va)] = value;
354 if ( unlikely(shadow_mode_translate(ed->domain)) )
355 update_hl2e(ed, va);
356 }
358 static inline void
359 update_hl2e(struct exec_domain *ed, unsigned long va)
360 {
361 int index = l2_table_offset(va);
362 unsigned long mfn;
363 l2_pgentry_t gl2e = ed->arch.guest_vtable[index];
364 l1_pgentry_t old_hl2e, new_hl2e;
365 int need_flush = 0;
367 ASSERT(shadow_mode_translate(ed->domain));
369 old_hl2e = ed->arch.hl2_vtable[index];
371 if ( (l2e_get_flags(gl2e) & _PAGE_PRESENT) &&
372 VALID_MFN(mfn = phys_to_machine_mapping(l2e_get_pfn(gl2e)) ))
373 new_hl2e = l1e_create_pfn(mfn, __PAGE_HYPERVISOR);
374 else
375 new_hl2e = l1e_empty();
377 // only do the ref counting if something important changed.
378 //
379 if ( (l1e_has_changed(&old_hl2e, &new_hl2e, _PAGE_PRESENT)) )
380 {
381 if ( (l1e_get_flags(new_hl2e) & _PAGE_PRESENT) &&
382 !get_page(pfn_to_page(l1e_get_pfn(new_hl2e)), ed->domain) )
383 new_hl2e = l1e_empty();
384 if ( l1e_get_flags(old_hl2e) & _PAGE_PRESENT )
385 {
386 put_page(pfn_to_page(l1e_get_pfn(old_hl2e)));
387 need_flush = 1;
388 }
389 }
391 ed->arch.hl2_vtable[l2_table_offset(va)] = new_hl2e;
393 if ( need_flush )
394 {
395 perfc_incrc(update_hl2e_invlpg);
396 local_flush_tlb_one(&linear_pg_table[l1_linear_offset(va)]);
397 }
398 }
400 static inline void shadow_drop_references(
401 struct domain *d, struct pfn_info *page)
402 {
403 if ( likely(!shadow_mode_enabled(d)) ||
404 ((page->u.inuse.type_info & PGT_count_mask) == 0) )
405 return;
407 /* XXX This needs more thought... */
408 printk("%s: needing to call shadow_remove_all_access for mfn=%p\n",
409 __func__, page_to_pfn(page));
410 printk("Before: mfn=%p c=%p t=%p\n", page_to_pfn(page),
411 page->count_info, page->u.inuse.type_info);
413 shadow_lock(d);
414 shadow_remove_all_access(d, page_to_pfn(page));
415 shadow_unlock(d);
417 printk("After: mfn=%p c=%p t=%p\n", page_to_pfn(page),
418 page->count_info, page->u.inuse.type_info);
419 }
421 /* XXX Needs more thought. Neither pretty nor fast: a place holder. */
422 static inline void shadow_sync_and_drop_references(
423 struct domain *d, struct pfn_info *page)
424 {
425 if ( likely(!shadow_mode_enabled(d)) )
426 return;
428 shadow_lock(d);
430 if ( page_out_of_sync(page) )
431 __shadow_sync_mfn(d, page_to_pfn(page));
433 shadow_remove_all_access(d, page_to_pfn(page));
435 shadow_unlock(d);
436 }
438 /************************************************************************/
440 /*
441 * Add another shadow reference to smfn.
442 */
443 static inline int
444 get_shadow_ref(unsigned long smfn)
445 {
446 u32 x, nx;
448 ASSERT(pfn_valid(smfn));
450 x = frame_table[smfn].count_info;
451 nx = x + 1;
453 if ( unlikely(nx == 0) )
454 {
455 printk("get_shadow_ref overflow, gmfn=%p smfn=%p\n",
456 frame_table[smfn].u.inuse.type_info & PGT_mfn_mask, smfn);
457 BUG();
458 }
460 // Guarded by the shadow lock...
461 //
462 frame_table[smfn].count_info = nx;
464 return 1;
465 }
467 extern void free_shadow_page(unsigned long smfn);
469 /*
470 * Drop a shadow reference to smfn.
471 */
472 static inline void
473 put_shadow_ref(unsigned long smfn)
474 {
475 u32 x, nx;
477 ASSERT(pfn_valid(smfn));
479 x = frame_table[smfn].count_info;
480 nx = x - 1;
482 if ( unlikely(x == 0) )
483 {
484 printk("put_shadow_ref underflow, smfn=%p oc=%p t=%p\n",
485 smfn,
486 frame_table[smfn].count_info,
487 frame_table[smfn].u.inuse.type_info);
488 BUG();
489 }
491 // Guarded by the shadow lock...
492 //
493 frame_table[smfn].count_info = nx;
495 if ( unlikely(nx == 0) )
496 {
497 free_shadow_page(smfn);
498 }
499 }
501 static inline void
502 shadow_pin(unsigned long smfn)
503 {
504 ASSERT( !(frame_table[smfn].u.inuse.type_info & PGT_pinned) );
506 frame_table[smfn].u.inuse.type_info |= PGT_pinned;
507 if ( unlikely(!get_shadow_ref(smfn)) )
508 BUG();
509 }
511 static inline void
512 shadow_unpin(unsigned long smfn)
513 {
514 ASSERT( (frame_table[smfn].u.inuse.type_info & PGT_pinned) );
516 frame_table[smfn].u.inuse.type_info &= ~PGT_pinned;
517 put_shadow_ref(smfn);
518 }
521 /************************************************************************/
523 static inline int __mark_dirty(struct domain *d, unsigned int mfn)
524 {
525 unsigned long pfn;
526 int rc = 0;
528 ASSERT(spin_is_locked(&d->arch.shadow_lock));
529 ASSERT(d->arch.shadow_dirty_bitmap != NULL);
531 if ( !VALID_MFN(mfn) )
532 return rc;
534 pfn = __mfn_to_gpfn(d, mfn);
536 /*
537 * Values with the MSB set denote MFNs that aren't really part of the
538 * domain's pseudo-physical memory map (e.g., the shared info frame).
539 * Nothing to do here...
540 */
541 if ( unlikely(IS_INVALID_M2P_ENTRY(pfn)) )
542 return rc;
544 if ( likely(pfn < d->arch.shadow_dirty_bitmap_size) )
545 {
546 /* N.B. Can use non-atomic TAS because protected by shadow_lock. */
547 if ( !__test_and_set_bit(pfn, d->arch.shadow_dirty_bitmap) )
548 {
549 d->arch.shadow_dirty_count++;
550 rc = 1;
551 }
552 }
553 #ifndef NDEBUG
554 else if ( mfn < max_page )
555 {
556 SH_LOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)",
557 mfn, pfn, d->arch.shadow_dirty_bitmap_size, d);
558 SH_LOG("dom=%p caf=%08x taf=%08x\n",
559 page_get_owner(&frame_table[mfn]),
560 frame_table[mfn].count_info,
561 frame_table[mfn].u.inuse.type_info );
562 }
563 #endif
565 return rc;
566 }
569 static inline int mark_dirty(struct domain *d, unsigned int mfn)
570 {
571 int rc;
572 shadow_lock(d);
573 rc = __mark_dirty(d, mfn);
574 shadow_unlock(d);
575 return rc;
576 }
579 /************************************************************************/
581 extern void shadow_mark_va_out_of_sync(
582 struct exec_domain *ed, unsigned long gpfn, unsigned long mfn,
583 unsigned long va);
585 static inline int l1pte_write_fault(
586 struct exec_domain *ed, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
587 unsigned long va)
588 {
589 struct domain *d = ed->domain;
590 l1_pgentry_t gpte = *gpte_p;
591 l1_pgentry_t spte;
592 unsigned long gpfn = l1e_get_pfn(gpte);
593 unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
595 //printk("l1pte_write_fault gmfn=%p\n", gmfn);
597 if ( unlikely(!VALID_MFN(gmfn)) )
598 {
599 SH_LOG("l1pte_write_fault: invalid gpfn=%p", gpfn);
600 *spte_p = l1e_empty();
601 return 0;
602 }
604 ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
605 l1e_add_flags(&gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
606 spte = l1e_create_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
608 SH_VVLOG("l1pte_write_fault: updating spte=0x%p gpte=0x%p",
609 l1e_get_value(spte), l1e_get_value(gpte));
611 if ( shadow_mode_log_dirty(d) )
612 __mark_dirty(d, gmfn);
614 if ( mfn_is_page_table(gmfn) )
615 shadow_mark_va_out_of_sync(ed, gpfn, gmfn, va);
617 *gpte_p = gpte;
618 *spte_p = spte;
620 return 1;
621 }
623 static inline int l1pte_read_fault(
624 struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
625 {
626 l1_pgentry_t gpte = *gpte_p;
627 l1_pgentry_t spte = *spte_p;
628 unsigned long pfn = l1e_get_pfn(gpte);
629 unsigned long mfn = __gpfn_to_mfn(d, pfn);
631 if ( unlikely(!VALID_MFN(mfn)) )
632 {
633 SH_LOG("l1pte_read_fault: invalid gpfn=%p", pfn);
634 *spte_p = l1e_empty();
635 return 0;
636 }
638 l1e_add_flags(&gpte, _PAGE_ACCESSED);
639 spte = l1e_create_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
641 if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
642 mfn_is_page_table(mfn) )
643 {
644 l1e_remove_flags(&spte, _PAGE_RW);
645 }
647 SH_VVLOG("l1pte_read_fault: updating spte=0x%p gpte=0x%p",
648 l1e_get_value(spte), l1e_get_value(gpte));
649 *gpte_p = gpte;
650 *spte_p = spte;
652 return 1;
653 }
655 static inline void l1pte_propagate_from_guest(
656 struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p)
657 {
658 unsigned long mfn;
659 l1_pgentry_t spte;
661 spte = l1e_empty();
663 if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
664 (_PAGE_PRESENT|_PAGE_ACCESSED)) &&
665 VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) )
666 {
667 spte = l1e_create_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
669 if ( shadow_mode_log_dirty(d) ||
670 !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
671 mfn_is_page_table(mfn) )
672 {
673 l1e_remove_flags(&spte, _PAGE_RW);
674 }
675 }
677 if ( l1e_get_value(spte) || l1e_get_value(gpte) )
678 SH_VVVLOG("%s: gpte=%p, new spte=%p",
679 __func__, l1e_get_value(gpte), l1e_get_value(spte));
681 *spte_p = spte;
682 }
684 static inline void hl2e_propagate_from_guest(
685 struct domain *d, l2_pgentry_t gpde, l1_pgentry_t *hl2e_p)
686 {
687 unsigned long pfn = l2e_get_pfn(gpde);
688 unsigned long mfn;
689 l1_pgentry_t hl2e;
691 hl2e = l1e_empty();
693 if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
694 {
695 if ( unlikely((current->domain != d) && !shadow_mode_external(d)) )
696 {
697 // Can't use __gpfn_to_mfn() if we don't have one of this domain's
698 // page tables currently installed.
699 // This isn't common -- it only happens during shadow mode setup
700 // and mode changes.
701 //
702 mfn = gpfn_to_mfn_foreign(d, pfn);
703 }
704 else
705 mfn = __gpfn_to_mfn(d, pfn);
707 if ( VALID_MFN(mfn) && (mfn < max_page) )
708 hl2e = l1e_create_pfn(mfn, __PAGE_HYPERVISOR);
709 }
711 if ( l1e_get_value(hl2e) || l2e_get_value(gpde) )
712 SH_VVLOG("%s: gpde=%p hl2e=%p", __func__,
713 l2e_get_value(gpde), l1e_get_value(hl2e));
715 *hl2e_p = hl2e;
716 }
718 static inline void l2pde_general(
719 struct domain *d,
720 l2_pgentry_t *gpde_p,
721 l2_pgentry_t *spde_p,
722 unsigned long sl1mfn)
723 {
724 l2_pgentry_t gpde = *gpde_p;
725 l2_pgentry_t spde;
727 spde = l2e_empty();
728 if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
729 {
730 spde = l2e_create_pfn(sl1mfn,
731 l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED);
732 l2e_add_flags(&gpde, _PAGE_ACCESSED); /* N.B. PDEs do not have a dirty bit. */
734 // XXX mafetter: Hmm...
735 // Shouldn't the dirty log be checked/updated here?
736 // Actually, it needs to be done in this function's callers.
737 //
738 *gpde_p = gpde;
739 }
741 if ( l2e_get_value(spde) || l2e_get_value(gpde) )
742 SH_VVLOG("%s: gpde=%p, new spde=%p", __func__,
743 l2e_get_value(gpde), l2e_get_value(spde));
745 *spde_p = spde;
746 }
748 static inline void l2pde_propagate_from_guest(
749 struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
750 {
751 l2_pgentry_t gpde = *gpde_p;
752 unsigned long sl1mfn = 0;
754 if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
755 sl1mfn = __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow);
756 l2pde_general(d, gpde_p, spde_p, sl1mfn);
757 }
759 /************************************************************************/
761 // returns true if a tlb flush is needed
762 //
763 static int inline
764 validate_pte_change(
765 struct domain *d,
766 l1_pgentry_t new_pte,
767 l1_pgentry_t *shadow_pte_p)
768 {
769 l1_pgentry_t old_spte, new_spte;
771 perfc_incrc(validate_pte_calls);
773 #if 0
774 FSH_LOG("validate_pte(old=%p new=%p)", old_pte, new_pte);
775 #endif
777 old_spte = *shadow_pte_p;
778 l1pte_propagate_from_guest(d, new_pte, &new_spte);
780 // only do the ref counting if something important changed.
781 //
782 if ( ((l1e_get_value(old_spte) | l1e_get_value(new_spte)) & _PAGE_PRESENT ) &&
783 l1e_has_changed(&old_spte, &new_spte, _PAGE_RW | _PAGE_PRESENT) )
784 {
785 perfc_incrc(validate_pte_changes);
787 if ( (l1e_get_flags(new_spte) & _PAGE_PRESENT) &&
788 !shadow_get_page_from_l1e(new_spte, d) )
789 new_spte = l1e_empty();
790 if ( l1e_get_flags(old_spte) & _PAGE_PRESENT )
791 put_page_from_l1e(old_spte, d);
792 }
794 *shadow_pte_p = new_spte;
796 // paranoia rules!
797 return 1;
798 }
800 // returns true if a tlb flush is needed
801 //
802 static int inline
803 validate_hl2e_change(
804 struct domain *d,
805 l2_pgentry_t new_gpde,
806 l1_pgentry_t *shadow_hl2e_p)
807 {
808 l1_pgentry_t old_hl2e, new_hl2e;
810 perfc_incrc(validate_hl2e_calls);
812 old_hl2e = *shadow_hl2e_p;
813 hl2e_propagate_from_guest(d, new_gpde, &new_hl2e);
815 // Only do the ref counting if something important changed.
816 //
817 if ( ((l1e_get_flags(old_hl2e) | l1e_get_flags(new_hl2e)) & _PAGE_PRESENT) &&
818 l1e_has_changed(&old_hl2e, &new_hl2e, _PAGE_PRESENT) )
819 {
820 perfc_incrc(validate_hl2e_changes);
822 if ( (l1e_get_flags(new_hl2e) & _PAGE_PRESENT) &&
823 !get_page(pfn_to_page(l1e_get_pfn(new_hl2e)), d) )
824 new_hl2e = l1e_empty();
825 if ( l1e_get_flags(old_hl2e) & _PAGE_PRESENT )
826 put_page(pfn_to_page(l1e_get_pfn(old_hl2e)));
827 }
829 *shadow_hl2e_p = new_hl2e;
831 // paranoia rules!
832 return 1;
834 }
836 // returns true if a tlb flush is needed
837 //
838 static int inline
839 validate_pde_change(
840 struct domain *d,
841 l2_pgentry_t new_gpde,
842 l2_pgentry_t *shadow_pde_p)
843 {
844 l2_pgentry_t old_spde, new_spde;
846 perfc_incrc(validate_pde_calls);
848 old_spde = *shadow_pde_p;
849 l2pde_propagate_from_guest(d, &new_gpde, &new_spde);
851 // XXX Shouldn't we propagate the new_gpde to the guest?
852 // And then mark the guest's L2 page as dirty?
854 // Only do the ref counting if something important changed.
855 //
856 if ( ((l2e_get_value(old_spde) | l2e_get_value(new_spde)) & _PAGE_PRESENT) &&
857 l2e_has_changed(&old_spde, &new_spde, _PAGE_PRESENT) )
858 {
859 perfc_incrc(validate_pde_changes);
861 if ( (l2e_get_flags(new_spde) & _PAGE_PRESENT) &&
862 !get_shadow_ref(l2e_get_pfn(new_spde)) )
863 BUG();
864 if ( l2e_get_flags(old_spde) & _PAGE_PRESENT )
865 put_shadow_ref(l2e_get_pfn(old_spde));
866 }
868 *shadow_pde_p = new_spde;
870 // paranoia rules!
871 return 1;
872 }
874 /*********************************************************************/
876 #if SHADOW_HASH_DEBUG
878 static void shadow_audit(struct domain *d, int print)
879 {
880 int live = 0, free = 0, j = 0, abs;
881 struct shadow_status *a;
883 for ( j = 0; j < shadow_ht_buckets; j++ )
884 {
885 a = &d->arch.shadow_ht[j];
886 if ( a->gpfn_and_flags )
887 {
888 live++;
889 ASSERT(a->smfn);
890 }
891 else
892 ASSERT(!a->next);
894 a = a->next;
895 while ( a && (live < 9999) )
896 {
897 live++;
898 if ( (a->gpfn_and_flags == 0) || (a->smfn == 0) )
899 {
900 printk("XXX live=%d gpfn+flags=%p sp=%p next=%p\n",
901 live, a->gpfn_and_flags, a->smfn, a->next);
902 BUG();
903 }
904 ASSERT(a->smfn);
905 a = a->next;
906 }
907 ASSERT(live < 9999);
908 }
910 for ( a = d->arch.shadow_ht_free; a != NULL; a = a->next )
911 free++;
913 if ( print )
914 printk("Xlive=%d free=%d\n", live, free);
916 // BUG: this only works if there's only a single domain which is
917 // using shadow tables.
918 //
919 abs = (
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 ) - live;
926 #ifdef PERF_COUNTERS
927 if ( (abs < -1) || (abs > 1) )
928 {
929 printk("live=%d free=%d l1=%d l2=%d hl2=%d snapshot=%d writable_ptes=%d\n",
930 live, free,
931 perfc_value(shadow_l1_pages),
932 perfc_value(shadow_l2_pages),
933 perfc_value(hl2_table_pages),
934 perfc_value(snapshot_pages),
935 perfc_value(writable_pte_predictions));
936 BUG();
937 }
938 #endif
940 // XXX ought to add some code to audit the out-of-sync entries, too.
941 //
942 }
943 #else
944 #define shadow_audit(p, print) ((void)0)
945 #endif
948 static inline struct shadow_status *hash_bucket(
949 struct domain *d, unsigned int gpfn)
950 {
951 return &d->arch.shadow_ht[gpfn % shadow_ht_buckets];
952 }
955 /*
956 * N.B. This takes a guest pfn (i.e. a pfn in the guest's namespace,
957 * which, depending on full shadow mode, may or may not equal
958 * its mfn).
959 * It returns the shadow's mfn, or zero if it doesn't exist.
960 */
962 static inline unsigned long ___shadow_status(
963 struct domain *d, unsigned long gpfn, unsigned long stype)
964 {
965 struct shadow_status *p, *x, *head;
966 unsigned long key = gpfn | stype;
968 perfc_incrc(shadow_status_calls);
970 x = head = hash_bucket(d, gpfn);
971 p = NULL;
973 //SH_VVLOG("lookup gpfn=%08x type=%08x bucket=%p", gpfn, stype, x);
974 shadow_audit(d, 0);
976 do
977 {
978 ASSERT(x->gpfn_and_flags || ((x == head) && (x->next == NULL)));
980 if ( x->gpfn_and_flags == key )
981 {
982 #if SHADOW_DEBUG
983 if ( unlikely(shadow_status_noswap) )
984 return x->smfn;
985 #endif
986 /* Pull-to-front if 'x' isn't already the head item. */
987 if ( unlikely(x != head) )
988 {
989 /* Delete 'x' from list and reinsert immediately after head. */
990 p->next = x->next;
991 x->next = head->next;
992 head->next = x;
994 /* Swap 'x' contents with head contents. */
995 SWAP(head->gpfn_and_flags, x->gpfn_and_flags);
996 SWAP(head->smfn, x->smfn);
997 }
998 else
999 {
1000 perfc_incrc(shadow_status_hit_head);
1003 //SH_VVLOG("lookup gpfn=%p => status=%p", key, head->smfn);
1004 return head->smfn;
1007 p = x;
1008 x = x->next;
1010 while ( x != NULL );
1012 //SH_VVLOG("lookup gpfn=%p => status=0", key);
1013 perfc_incrc(shadow_status_miss);
1014 return 0;
1017 static inline unsigned long __shadow_status(
1018 struct domain *d, unsigned long gpfn, unsigned long stype)
1020 unsigned long gmfn = ((current->domain == d)
1021 ? __gpfn_to_mfn(d, gpfn)
1022 : INVALID_MFN);
1024 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1025 ASSERT(gpfn == (gpfn & PGT_mfn_mask));
1026 ASSERT(stype && !(stype & ~PGT_type_mask));
1028 if ( VALID_MFN(gmfn) && (gmfn < max_page) &&
1029 (stype != PGT_writable_pred) &&
1030 ((stype == PGT_snapshot)
1031 ? !mfn_out_of_sync(gmfn)
1032 : !mfn_is_page_table(gmfn)) )
1034 perfc_incrc(shadow_status_shortcut);
1035 #ifndef NDEBUG
1036 ASSERT(___shadow_status(d, gpfn, stype) == 0);
1038 // Undo the affects of the above ASSERT on ___shadow_status()'s perf
1039 // counters.
1040 //
1041 perfc_decrc(shadow_status_calls);
1042 perfc_decrc(shadow_status_miss);
1043 #endif
1044 return 0;
1047 return ___shadow_status(d, gpfn, stype);
1050 /*
1051 * Not clear if pull-to-front is worth while for this or not,
1052 * as it generally needs to scan the entire bucket anyway.
1053 * Much simpler without.
1055 * Either returns PGT_none, or PGT_l{1,2,3,4}_page_table.
1056 */
1057 static inline unsigned long
1058 shadow_max_pgtable_type(struct domain *d, unsigned long gpfn,
1059 unsigned long *smfn)
1061 struct shadow_status *x;
1062 unsigned long pttype = PGT_none, type;
1064 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1065 ASSERT(gpfn == (gpfn & PGT_mfn_mask));
1067 perfc_incrc(shadow_max_type);
1069 x = hash_bucket(d, gpfn);
1071 while ( x && x->gpfn_and_flags )
1073 if ( (x->gpfn_and_flags & PGT_mfn_mask) == gpfn )
1075 type = x->gpfn_and_flags & PGT_type_mask;
1077 switch ( type )
1079 case PGT_hl2_shadow:
1080 // Treat an HL2 as if it's an L1
1081 //
1082 type = PGT_l1_shadow;
1083 break;
1084 case PGT_snapshot:
1085 case PGT_writable_pred:
1086 // Ignore snapshots -- they don't in and of themselves constitute
1087 // treating a page as a page table
1088 //
1089 goto next;
1090 case PGT_base_page_table:
1091 // Early exit if we found the max possible value
1092 //
1093 return type;
1094 default:
1095 break;
1098 if ( type > pttype )
1100 pttype = type;
1101 if ( smfn )
1102 *smfn = x->smfn;
1105 next:
1106 x = x->next;
1109 return pttype;
1112 /*
1113 * N.B. We can make this locking more fine grained (e.g., per shadow page) if
1114 * it ever becomes a problem, but since we need a spin lock on the hash table
1115 * anyway it's probably not worth being too clever.
1116 */
1117 static inline unsigned long get_shadow_status(
1118 struct domain *d, unsigned long gpfn, unsigned long stype)
1120 unsigned long res;
1122 ASSERT(shadow_mode_enabled(d));
1124 /*
1125 * If we get here we know that some sort of update has happened to the
1126 * underlying page table page: either a PTE has been updated, or the page
1127 * has changed type. If we're in log dirty mode, we should set the
1128 * appropriate bit in the dirty bitmap.
1129 * N.B. The VA update path doesn't use this and is handled independently.
1131 * XXX need to think this through for vmx guests, but probably OK
1132 */
1134 shadow_lock(d);
1136 if ( shadow_mode_log_dirty(d) )
1137 __mark_dirty(d, __gpfn_to_mfn(d, gpfn));
1139 if ( !(res = __shadow_status(d, gpfn, stype)) )
1140 shadow_unlock(d);
1142 return res;
1146 static inline void put_shadow_status(struct domain *d)
1148 shadow_unlock(d);
1152 static inline void delete_shadow_status(
1153 struct domain *d, unsigned long gpfn, unsigned long gmfn, unsigned int stype)
1155 struct shadow_status *p, *x, *n, *head;
1156 unsigned long key = gpfn | stype;
1158 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1159 ASSERT(!(gpfn & ~PGT_mfn_mask));
1160 ASSERT(stype && !(stype & ~PGT_type_mask));
1162 head = hash_bucket(d, gpfn);
1164 SH_VLOG("delete gpfn=%p t=%p bucket=%p", gpfn, stype, head);
1165 shadow_audit(d, 0);
1167 /* Match on head item? */
1168 if ( head->gpfn_and_flags == key )
1170 if ( (n = head->next) != NULL )
1172 /* Overwrite head with contents of following node. */
1173 head->gpfn_and_flags = n->gpfn_and_flags;
1174 head->smfn = n->smfn;
1176 /* Delete following node. */
1177 head->next = n->next;
1179 /* Add deleted node to the free list. */
1180 n->gpfn_and_flags = 0;
1181 n->smfn = 0;
1182 n->next = d->arch.shadow_ht_free;
1183 d->arch.shadow_ht_free = n;
1185 else
1187 /* This bucket is now empty. Initialise the head node. */
1188 head->gpfn_and_flags = 0;
1189 head->smfn = 0;
1192 goto found;
1195 p = head;
1196 x = head->next;
1198 do
1200 if ( x->gpfn_and_flags == key )
1202 /* Delete matching node. */
1203 p->next = x->next;
1205 /* Add deleted node to the free list. */
1206 x->gpfn_and_flags = 0;
1207 x->smfn = 0;
1208 x->next = d->arch.shadow_ht_free;
1209 d->arch.shadow_ht_free = x;
1211 goto found;
1214 p = x;
1215 x = x->next;
1217 while ( x != NULL );
1219 /* If we got here, it wasn't in the list! */
1220 BUG();
1222 found:
1223 // release ref to page
1224 if ( stype != PGT_writable_pred )
1225 put_page(pfn_to_page(gmfn));
1227 shadow_audit(d, 0);
1230 static inline void set_shadow_status(
1231 struct domain *d, unsigned long gpfn, unsigned long gmfn,
1232 unsigned long smfn, unsigned long stype)
1234 struct shadow_status *x, *head, *extra;
1235 int i;
1236 unsigned long key = gpfn | stype;
1238 SH_VVLOG("set gpfn=%p gmfn=%p smfn=%p t=%p", gpfn, gmfn, smfn, stype);
1240 ASSERT(spin_is_locked(&d->arch.shadow_lock));
1242 ASSERT(shadow_mode_translate(d) || gpfn);
1243 ASSERT(!(gpfn & ~PGT_mfn_mask));
1245 // XXX - need to be more graceful.
1246 ASSERT(VALID_MFN(gmfn));
1248 ASSERT(stype && !(stype & ~PGT_type_mask));
1250 x = head = hash_bucket(d, gpfn);
1252 SH_VLOG("set gpfn=%p smfn=%p t=%p bucket=%p(%p)",
1253 gpfn, smfn, stype, x, x->next);
1254 shadow_audit(d, 0);
1256 // grab a reference to the guest page to represent the entry in the shadow
1257 // hash table
1258 //
1259 // XXX - Should PGT_writable_pred grab a page ref?
1260 // - Who/how are these hash table entry refs flushed if/when a page
1261 // is given away by the domain?
1262 //
1263 if ( stype != PGT_writable_pred )
1264 get_page(pfn_to_page(gmfn), d);
1266 /*
1267 * STEP 1. If page is already in the table, update it in place.
1268 */
1269 do
1271 if ( unlikely(x->gpfn_and_flags == key) )
1273 if ( stype != PGT_writable_pred )
1274 BUG(); // we should never replace entries into the hash table
1275 x->smfn = smfn;
1276 put_page(pfn_to_page(gmfn)); // already had a ref...
1277 goto done;
1280 x = x->next;
1282 while ( x != NULL );
1284 /*
1285 * STEP 2. The page must be inserted into the table.
1286 */
1288 /* If the bucket is empty then insert the new page as the head item. */
1289 if ( head->gpfn_and_flags == 0 )
1291 head->gpfn_and_flags = key;
1292 head->smfn = smfn;
1293 ASSERT(head->next == NULL);
1294 goto done;
1297 /* We need to allocate a new node. Ensure the quicklist is non-empty. */
1298 if ( unlikely(d->arch.shadow_ht_free == NULL) )
1300 SH_LOG("Allocate more shadow hashtable blocks.");
1302 extra = xmalloc_bytes(
1303 sizeof(void *) + (shadow_ht_extra_size * sizeof(*x)));
1305 /* XXX Should be more graceful here. */
1306 if ( extra == NULL )
1307 BUG();
1309 memset(extra, 0, sizeof(void *) + (shadow_ht_extra_size * sizeof(*x)));
1311 /* Record the allocation block so it can be correctly freed later. */
1312 d->arch.shadow_extras_count++;
1313 *((struct shadow_status **)&extra[shadow_ht_extra_size]) =
1314 d->arch.shadow_ht_extras;
1315 d->arch.shadow_ht_extras = &extra[0];
1317 /* Thread a free chain through the newly-allocated nodes. */
1318 for ( i = 0; i < (shadow_ht_extra_size - 1); i++ )
1319 extra[i].next = &extra[i+1];
1320 extra[i].next = NULL;
1322 /* Add the new nodes to the free list. */
1323 d->arch.shadow_ht_free = &extra[0];
1326 /* Allocate a new node from the quicklist. */
1327 x = d->arch.shadow_ht_free;
1328 d->arch.shadow_ht_free = x->next;
1330 /* Initialise the new node and insert directly after the head item. */
1331 x->gpfn_and_flags = key;
1332 x->smfn = smfn;
1333 x->next = head->next;
1334 head->next = x;
1336 done:
1337 shadow_audit(d, 0);
1339 if ( stype <= PGT_l4_shadow )
1341 // add to front of list of pages to check when removing write
1342 // permissions for a page...
1343 //
1347 /************************************************************************/
1349 void static inline
1350 shadow_update_min_max(unsigned long smfn, int index)
1352 struct pfn_info *sl1page = pfn_to_page(smfn);
1353 u32 min_max = sl1page->tlbflush_timestamp;
1354 int min = SHADOW_MIN(min_max);
1355 int max = SHADOW_MAX(min_max);
1356 int update = 0;
1358 if ( index < min )
1360 min = index;
1361 update = 1;
1363 if ( index > max )
1365 max = index;
1366 update = 1;
1368 if ( update )
1369 sl1page->tlbflush_timestamp = SHADOW_ENCODE_MIN_MAX(min, max);
1372 extern void shadow_map_l1_into_current_l2(unsigned long va);
1374 void static inline
1375 shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow)
1377 struct exec_domain *ed = current;
1378 struct domain *d = ed->domain;
1379 l2_pgentry_t sl2e;
1380 l1_pgentry_t old_spte;
1382 #if 0
1383 printk("shadow_set_l1e(va=%p, new_spte=%p, create=%d)\n",
1384 va, l1e_get_value(new_spte), create_l1_shadow);
1385 #endif
1387 __shadow_get_l2e(ed, va, &sl2e);
1388 if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
1390 /*
1391 * Either the L1 is not shadowed, or the shadow isn't linked into
1392 * the current shadow L2.
1393 */
1394 if ( create_l1_shadow )
1396 perfc_incrc(shadow_set_l1e_force_map);
1397 shadow_map_l1_into_current_l2(va);
1399 else /* check to see if it exists; if so, link it in */
1401 l2_pgentry_t gpde = linear_l2_table(ed)[l2_table_offset(va)];
1402 unsigned long gl1pfn = l2e_get_pfn(gpde);
1403 unsigned long sl1mfn = __shadow_status(d, gl1pfn, PGT_l1_shadow);
1405 ASSERT( l2e_get_flags(gpde) & _PAGE_PRESENT );
1407 if ( sl1mfn )
1409 perfc_incrc(shadow_set_l1e_unlinked);
1410 if ( !get_shadow_ref(sl1mfn) )
1411 BUG();
1412 l2pde_general(d, &gpde, &sl2e, sl1mfn);
1413 __guest_set_l2e(ed, va, gpde);
1414 __shadow_set_l2e(ed, va, sl2e);
1416 else
1418 // no shadow exists, so there's nothing to do.
1419 perfc_incrc(shadow_set_l1e_fail);
1420 return;
1425 old_spte = shadow_linear_pg_table[l1_linear_offset(va)];
1427 // only do the ref counting if something important changed.
1428 //
1429 if ( l1e_has_changed(&old_spte, &new_spte, _PAGE_RW | _PAGE_PRESENT) )
1431 if ( (l1e_get_flags(new_spte) & _PAGE_PRESENT) &&
1432 !shadow_get_page_from_l1e(new_spte, d) )
1433 new_spte = l1e_empty();
1434 if ( l1e_get_flags(old_spte) & _PAGE_PRESENT )
1435 put_page_from_l1e(old_spte, d);
1438 shadow_linear_pg_table[l1_linear_offset(va)] = new_spte;
1440 shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va));
1443 /************************************************************************/
1445 static inline l1_pgentry_t gva_to_gpte(unsigned long gva)
1447 l2_pgentry_t gpde;
1448 l1_pgentry_t gpte;
1449 struct exec_domain *ed = current;
1451 ASSERT( shadow_mode_translate(current->domain) );
1453 __guest_get_l2e(ed, gva, &gpde);
1454 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
1455 return l1e_empty();;
1457 // This is actually overkill - we only need to make sure the hl2
1458 // is in-sync.
1459 //
1460 shadow_sync_va(ed, gva);
1462 if ( unlikely(__copy_from_user(&gpte,
1463 &linear_pg_table[gva >> PAGE_SHIFT],
1464 sizeof(gpte))) )
1466 FSH_LOG("gva_to_gpte got a fault on gva=%p", gva);
1467 return l1e_empty();
1470 return gpte;
1473 static inline unsigned long gva_to_gpa(unsigned long gva)
1475 l1_pgentry_t gpte;
1477 gpte = gva_to_gpte(gva);
1478 if ( !(l1e_get_flags(gpte) & _PAGE_PRESENT) )
1479 return 0;
1481 return l1e_get_phys(gpte) + (gva & ~PAGE_MASK);
1484 /************************************************************************/
1486 extern void __update_pagetables(struct exec_domain *ed);
1487 static inline void update_pagetables(struct exec_domain *ed)
1489 struct domain *d = ed->domain;
1490 int paging_enabled;
1492 #ifdef CONFIG_VMX
1493 if ( VMX_DOMAIN(ed) )
1494 paging_enabled =
1495 test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state);
1496 else
1497 #endif
1498 // HACK ALERT: there's currently no easy way to figure out if a domU
1499 // has set its arch.guest_table to zero, vs not yet initialized it.
1500 //
1501 paging_enabled = !!pagetable_val(ed->arch.guest_table);
1503 /*
1504 * We don't call __update_pagetables() when vmx guest paging is
1505 * disabled as we want the linear_pg_table to be inaccessible so that
1506 * we bail out early of shadow_fault() if the vmx guest tries illegal
1507 * accesses while it thinks paging is turned off.
1508 */
1509 if ( unlikely(shadow_mode_enabled(d)) && paging_enabled )
1511 shadow_lock(d);
1512 __update_pagetables(ed);
1513 shadow_unlock(d);
1516 if ( likely(!shadow_mode_external(d)) )
1518 #ifdef __x86_64__
1519 if ( !(ed->arch.flags & TF_kernel_mode) )
1520 ed->arch.monitor_table = ed->arch.guest_table_user;
1521 else
1522 #endif
1523 if ( shadow_mode_enabled(d) )
1524 ed->arch.monitor_table = ed->arch.shadow_table;
1525 else
1526 ed->arch.monitor_table = ed->arch.guest_table;
1530 #if SHADOW_DEBUG
1531 extern int _check_pagetable(struct exec_domain *ed, char *s);
1532 extern int _check_all_pagetables(struct exec_domain *ed, char *s);
1534 #define check_pagetable(_ed, _s) _check_pagetable(_ed, _s)
1535 //#define check_pagetable(_ed, _s) _check_all_pagetables(_ed, _s)
1537 #else
1538 #define check_pagetable(_ed, _s) ((void)0)
1539 #endif
1541 #endif /* XEN_SHADOW_H */
1543 /*
1544 * Local variables:
1545 * mode: C
1546 * c-set-style: "BSD"
1547 * c-basic-offset: 4
1548 * tab-width: 4
1549 * indent-tabs-mode: nil
1550 * End:
1551 */