diff options
-rw-r--r-- | xen/common/domain.c | 3 | ||||
-rw-r--r-- | xen/common/memory.c | 9 | ||||
-rw-r--r-- | xen/common/schedule.c | 10 | ||||
-rw-r--r-- | xen/common/shadow.c | 140 | ||||
-rw-r--r-- | xen/include/xen/shadow.h | 141 |
5 files changed, 161 insertions, 142 deletions
diff --git a/xen/common/domain.c b/xen/common/domain.c index 2db0331d89..7b55ee89d4 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -19,6 +19,7 @@ #include <xen/console.h> #include <xen/vbd.h> #include <asm/i387.h> +#include <xen/shadow.h> #ifdef CONFIG_X86_64BITMODE #define ELFSIZE 64 @@ -382,6 +383,8 @@ void free_all_dom_mem(struct task_struct *p) INIT_LIST_HEAD(&zombies); + if ( p->mm.shadow_mode ) shadow_mode_disable(p); + /* STEP 1. Drop the in-use reference to the page-table base. */ put_page_and_type(&frame_table[pagetable_val(p->mm.pagetable) >> PAGE_SHIFT]); diff --git a/xen/common/memory.c b/xen/common/memory.c index edba5c02de..b7896e3cfb 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -770,7 +770,14 @@ void free_page_type(struct pfn_info *page, unsigned int type) (get_shadow_status(¤t->mm, page-frame_table) & PSH_shadowed) ) { - unshadow_table( page-frame_table, type ); + /* using 'current-mm' is safe because page type changes only + occur within the context of the currently running domain as + pagetable pages can not be shared across domains. The one + exception is when destroying a domain. However, we get away + with this as there's no way the current domain can have this + mfn shadowed, so we won't get here... Phew! */ + + unshadow_table( page-frame_table, type ); put_shadow_status(¤t->mm); } return; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index fcdf860351..6692bacaa3 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -283,7 +283,13 @@ long do_sched_op(unsigned long op) } -/* sched_pause_sync - synchronously pause a domain's execution */ +/* sched_pause_sync - synchronously pause a domain's execution + +XXXX This is horibly broken -- here just as a place holder at present, + do not use. + +*/ + void sched_pause_sync(struct task_struct *p) { unsigned long flags; @@ -293,7 +299,7 @@ void sched_pause_sync(struct task_struct *p) if ( schedule_data[cpu].curr != p ) /* if not the current task, we can remove it from scheduling now */ - SCHED_FN(pause, p); + SCHED_OP(pause, p); p->state = TASK_PAUSED; diff --git a/xen/common/shadow.c b/xen/common/shadow.c index 8e7b53db86..14d395cbf7 100644 --- a/xen/common/shadow.c +++ b/xen/common/shadow.c @@ -225,7 +225,7 @@ nomem: return -ENOMEM; } -static void shadow_mode_disable( struct task_struct *p ) +void shadow_mode_disable( struct task_struct *p ) { struct mm_struct *m = &p->mm; struct shadow_status *next; @@ -353,144 +353,6 @@ static inline struct pfn_info *alloc_shadow_page( struct mm_struct *m ) return alloc_domain_page( NULL ); } -/************************************************************************/ - -static inline void mark_dirty( struct mm_struct *m, unsigned int mfn ) -{ - unsigned int pfn = machine_to_phys_mapping[mfn]; - ASSERT(m->shadow_dirty_bitmap); - if( likely(pfn<m->shadow_dirty_bitmap_size) ) - { - // XXX use setbit - m->shadow_dirty_bitmap[pfn/(sizeof(int)*8)] |= - (1<<(pfn%(sizeof(int)*8))); - } - else - { - printk("XXXX mark dirty overflow!"); - } - -} - -/************************************************************************/ - -static inline void l1pte_write_fault( struct mm_struct *m, - unsigned long *gpte_p, unsigned long *spte_p ) -{ - unsigned long gpte = *gpte_p; - unsigned long spte = *spte_p; - - switch( m->shadow_mode ) - { - case SHM_test: - spte = gpte; - gpte |= _PAGE_DIRTY | _PAGE_ACCESSED; - spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; - break; - - case SHM_logdirty: - spte = gpte; - gpte |= _PAGE_DIRTY | _PAGE_ACCESSED; - spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; - mark_dirty( m, gpte >> PAGE_SHIFT ); - break; - } - - *gpte_p = gpte; - *spte_p = spte; -} - -static inline void l1pte_read_fault( struct mm_struct *m, - unsigned long *gpte_p, unsigned long *spte_p ) -{ - unsigned long gpte = *gpte_p; - unsigned long spte = *spte_p; - - switch( m->shadow_mode ) - { - case SHM_test: - spte = gpte; - gpte |= _PAGE_ACCESSED; - spte |= _PAGE_ACCESSED; - if ( ! (gpte & _PAGE_DIRTY ) ) - spte &= ~ _PAGE_RW; - break; - - case SHM_logdirty: - spte = gpte; - gpte |= _PAGE_ACCESSED; - spte |= _PAGE_ACCESSED; - spte &= ~ _PAGE_RW; - break; - } - - *gpte_p = gpte; - *spte_p = spte; -} - -static inline void l1pte_no_fault( struct mm_struct *m, - unsigned long *gpte_p, unsigned long *spte_p ) -{ - unsigned long gpte = *gpte_p; - unsigned long spte = *spte_p; - - switch( m->shadow_mode ) - { - case SHM_test: - spte = 0; - if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == - (_PAGE_PRESENT|_PAGE_ACCESSED) ) - { - spte = gpte; - if ( ! (gpte & _PAGE_DIRTY ) ) - spte &= ~ _PAGE_RW; - } - break; - - case SHM_logdirty: - spte = 0; - if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == - (_PAGE_PRESENT|_PAGE_ACCESSED) ) - { - spte = gpte; - spte &= ~ _PAGE_RW; - } - - break; - } - - *gpte_p = gpte; - *spte_p = spte; -} - -static inline void l2pde_general( struct mm_struct *m, - unsigned long *gpde_p, unsigned long *spde_p, - unsigned long sl1pfn) -{ - unsigned long gpde = *gpde_p; - unsigned long spde = *spde_p; - - spde = 0; - - if ( sl1pfn ) - { - spde = (gpde & ~PAGE_MASK) | (sl1pfn<<PAGE_SHIFT) | - _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY; - gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY; - - if ( unlikely( (sl1pfn<<PAGE_SHIFT) == (gpde & PAGE_MASK) ) ) - { - // detect linear map, and keep pointing at guest - SH_VLOG("4c: linear mapping ( %08lx )",sl1pfn); - spde = gpde & ~_PAGE_RW; - } - } - - *gpde_p = gpde; - *spde_p = spde; -} - -/*********************************************************************/ void unshadow_table( unsigned long gpfn, unsigned int type ) { diff --git a/xen/include/xen/shadow.h b/xen/include/xen/shadow.h index 0f4e2e19d4..f5c0d5327a 100644 --- a/xen/include/xen/shadow.h +++ b/xen/include/xen/shadow.h @@ -31,6 +31,7 @@ extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte ); extern void unshadow_table( unsigned long gpfn, unsigned int type ); extern int shadow_mode_enable( struct task_struct *p, unsigned int mode ); +extern void shadow_mode_disable( struct task_struct *p ); extern unsigned long shadow_l2_table( struct mm_struct *m, unsigned long gpfn ); @@ -73,6 +74,146 @@ struct shadow_status { +/************************************************************************/ + +static inline void mark_dirty( struct mm_struct *m, unsigned int mfn ) +{ + unsigned int pfn = machine_to_phys_mapping[mfn]; + ASSERT(m->shadow_dirty_bitmap); + if( likely(pfn<m->shadow_dirty_bitmap_size) ) + { + // use setbit to be smp guest safe + set_bit( pfn, m->shadow_dirty_bitmap ); + } + else + { + SH_LOG("mark_dirty pfn out of range attempt!"); + } + +} + +/************************************************************************/ + +static inline void l1pte_write_fault( struct mm_struct *m, + unsigned long *gpte_p, unsigned long *spte_p ) +{ + unsigned long gpte = *gpte_p; + unsigned long spte = *spte_p; + + switch( m->shadow_mode ) + { + case SHM_test: + spte = gpte; + gpte |= _PAGE_DIRTY | _PAGE_ACCESSED; + spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; + break; + + case SHM_logdirty: + spte = gpte; + gpte |= _PAGE_DIRTY | _PAGE_ACCESSED; + spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; + mark_dirty( m, gpte >> PAGE_SHIFT ); + break; + } + + *gpte_p = gpte; + *spte_p = spte; +} + +static inline void l1pte_read_fault( struct mm_struct *m, + unsigned long *gpte_p, unsigned long *spte_p ) +{ + unsigned long gpte = *gpte_p; + unsigned long spte = *spte_p; + + switch( m->shadow_mode ) + { + case SHM_test: + spte = gpte; + gpte |= _PAGE_ACCESSED; + spte |= _PAGE_ACCESSED; + if ( ! (gpte & _PAGE_DIRTY ) ) + spte &= ~ _PAGE_RW; + break; + + case SHM_logdirty: + spte = gpte; + gpte |= _PAGE_ACCESSED; + spte |= _PAGE_ACCESSED; + spte &= ~ _PAGE_RW; + break; + } + + *gpte_p = gpte; + *spte_p = spte; +} + +static inline void l1pte_no_fault( struct mm_struct *m, + unsigned long *gpte_p, unsigned long *spte_p ) +{ + unsigned long gpte = *gpte_p; + unsigned long spte = *spte_p; + + switch( m->shadow_mode ) + { + case SHM_test: + spte = 0; + if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == + (_PAGE_PRESENT|_PAGE_ACCESSED) ) + { + spte = gpte; + if ( ! (gpte & _PAGE_DIRTY ) ) + spte &= ~ _PAGE_RW; + } + break; + + case SHM_logdirty: + spte = 0; + if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == + (_PAGE_PRESENT|_PAGE_ACCESSED) ) + { + spte = gpte; + spte &= ~ _PAGE_RW; + } + + break; + } + + *gpte_p = gpte; + *spte_p = spte; +} + +static inline void l2pde_general( struct mm_struct *m, + unsigned long *gpde_p, unsigned long *spde_p, + unsigned long sl1pfn) +{ + unsigned long gpde = *gpde_p; + unsigned long spde = *spde_p; + + spde = 0; + + if ( sl1pfn ) + { + spde = (gpde & ~PAGE_MASK) | (sl1pfn<<PAGE_SHIFT) | + _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY; + gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY; + + if ( unlikely( (sl1pfn<<PAGE_SHIFT) == (gpde & PAGE_MASK) ) ) + { + // detect linear map, and keep pointing at guest + SH_VLOG("4c: linear mapping ( %08lx )",sl1pfn); + spde = gpde & ~_PAGE_RW; + } + } + + *gpde_p = gpde; + *spde_p = spde; +} + +/*********************************************************************/ + + + #if SHADOW_HASH_DEBUG static void shadow_audit(struct mm_struct *m, int print) { |