aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>2004-04-02 16:27:45 +0000
committeriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>2004-04-02 16:27:45 +0000
commit9582cc5affd7e0ea070ce57b968ff1999f3afebb (patch)
tree632a4804b1fe37b4c94ea9eb6cfd36bc6f83b1fa
parent72ab8c7adebff63d3a4b6ac540cf0ea842442b6a (diff)
downloadxen-9582cc5affd7e0ea070ce57b968ff1999f3afebb.tar.gz
xen-9582cc5affd7e0ea070ce57b968ff1999f3afebb.tar.bz2
xen-9582cc5affd7e0ea070ce57b968ff1999f3afebb.zip
bitkeeper revision 1.835 (406d9481GqoZ_RrT3GukXhamv7rulA)
Delete shadow page tables when destroying domain
-rw-r--r--xen/common/domain.c3
-rw-r--r--xen/common/memory.c9
-rw-r--r--xen/common/schedule.c10
-rw-r--r--xen/common/shadow.c140
-rw-r--r--xen/include/xen/shadow.h141
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(&current->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(&current->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)
{