bitkeeper revision 1.891.1.26 (40a53236dmYLlX-VydSRAnt7T6na3Q)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 14 May 2004 20:55:18 +0000 (20:55 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 14 May 2004 20:55:18 +0000 (20:55 +0000)
Fix page-ownership reassignment operation. Now race-free and places page
on the new owner's page list.

xen/common/domain.c
xen/common/memory.c

index c40c052425f93de2a7ff053fc5906bfdc1aaadbb..f907a8c1045664c6daee6e9f53ed9aebf6e474f9 100644 (file)
@@ -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) )
             {
index 87ddf4c9176c2aa781bbe79e164ff9947695412d..a157de09f2d8391fbfa98a6b4a63782159d29547 100644 (file)
@@ -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
         {