aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-05-14 20:55:18 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-05-14 20:55:18 +0000
commitaea7233c353457abe7ae567e08835d8352a83b8d (patch)
tree09e08d07de13d0b5212fa49b6d6eae261dd7c50f /xen
parente34c52ae9aebdb63c9e438ee71c29bc63f877274 (diff)
downloadxen-aea7233c353457abe7ae567e08835d8352a83b8d.tar.gz
xen-aea7233c353457abe7ae567e08835d8352a83b8d.tar.bz2
xen-aea7233c353457abe7ae567e08835d8352a83b8d.zip
bitkeeper revision 1.891.1.26 (40a53236dmYLlX-VydSRAnt7T6na3Q)
Fix page-ownership reassignment operation. Now race-free and places page on the new owner's page list.
Diffstat (limited to 'xen')
-rw-r--r--xen/common/domain.c2
-rw-r--r--xen/common/memory.c46
2 files changed, 28 insertions, 20 deletions
diff --git a/xen/common/domain.c b/xen/common/domain.c
index c40c052425..f907a8c104 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -299,7 +299,7 @@ struct pfn_info *alloc_domain_page(struct task_struct *p)
if ( (mask = page->u.cpu_mask) != 0 )
{
pfn_stamp = page->tlbflush_timestamp;
- for ( i = 0; (mask != 0) && (i < NR_CPUS); i++ )
+ for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
{
if ( mask & (1<<i) )
{
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 87ddf4c917..a157de09f2 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -798,6 +798,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
unsigned long pfn = ptr >> PAGE_SHIFT;
unsigned long old_base_pfn;
struct pfn_info *page = &frame_table[pfn];
+ struct task_struct *p = current, *q;
switch ( cmd )
{
@@ -846,18 +847,18 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
break;
case MMUEXT_NEW_BASEPTR:
- okay = get_page_and_type_from_pagenr(pfn, PGT_l2_page_table, current);
+ okay = get_page_and_type_from_pagenr(pfn, PGT_l2_page_table, p);
if ( likely(okay) )
{
invalidate_shadow_ldt();
percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
- old_base_pfn = pagetable_val(current->mm.pagetable) >> PAGE_SHIFT;
- current->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
+ old_base_pfn = pagetable_val(p->mm.pagetable) >> PAGE_SHIFT;
+ p->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
- shadow_mk_pagetable(&current->mm);
+ shadow_mk_pagetable(&p->mm);
- write_ptbase(&current->mm);
+ write_ptbase(&p->mm);
put_page_and_type(&frame_table[old_base_pfn]);
@@ -893,13 +894,13 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
okay = 0;
MEM_LOG("Bad args to SET_LDT: ptr=%08lx, ents=%08lx", ptr, ents);
}
- else if ( (current->mm.ldt_ents != ents) ||
- (current->mm.ldt_base != ptr) )
+ else if ( (p->mm.ldt_ents != ents) ||
+ (p->mm.ldt_base != ptr) )
{
invalidate_shadow_ldt();
- current->mm.ldt_base = ptr;
- current->mm.ldt_ents = ents;
- load_LDT(current);
+ p->mm.ldt_base = ptr;
+ p->mm.ldt_ents = ents;
+ load_LDT(p);
percpu_info[cpu].deferred_ops &= ~DOP_RELOAD_LDT;
if ( ents != 0 )
percpu_info[cpu].deferred_ops |= DOP_RELOAD_LDT;
@@ -915,10 +916,10 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
percpu_info[cpu].subject_id |=
((domid_t)((ptr&~0xFFFF)|(val>>16)))<<32;
- if ( !IS_PRIV(current) )
+ if ( !IS_PRIV(p) )
{
MEM_LOG("Dom %llu has no privilege to set subject domain",
- current->domain);
+ p->domain);
okay = 0;
}
else
@@ -937,19 +938,26 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
}
break;
- /* XXX This function is racey! */
case MMUEXT_REASSIGN_PAGE:
- if ( unlikely(!IS_PRIV(current)) )
+ if ( unlikely(!IS_PRIV(p)) )
{
MEM_LOG("Dom %llu has no privilege to reassign page ownership",
- current->domain);
+ p->domain);
okay = 0;
}
- else if ( likely(percpu_info[cpu].gps != NULL) )
+ else if ( likely((q = percpu_info[cpu].gps) != NULL) &&
+ likely(test_bit(_PGC_allocated, &page->count_and_flags)) &&
+ likely(page->u.domain == p) ) /* won't be smp-guest safe */
{
- current->tot_pages--;
- percpu_info[cpu].gps->tot_pages++;
- page->u.domain = percpu_info[cpu].gps;
+ spin_lock(&p->page_list_lock);
+ p->tot_pages--;
+ list_del(&page->list);
+ spin_unlock(&p->page_list_lock);
+ page->u.domain = q;
+ spin_lock(&q->page_list_lock);
+ q->tot_pages++;
+ list_add_tail(&page->list, &q->page_list);
+ spin_unlock(&q->page_list_lock);
}
else
{