[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Improved TLB flushing of subsets of CPUs. Can now do remote invlpg



ChangeSet 1.1410, 2005/03/31 14:12:29+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx

        Improved TLB flushing of subsets of CPUs. Can now do remote invlpg
        as well as complete flush.
        Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>



 arch/x86/mm.c              |   31 +++++++++++++++++++---------
 arch/x86/mtrr/generic.c    |    4 +--
 arch/x86/smp.c             |   15 +++++++++----
 arch/x86/x86_32/mm.c       |    4 +--
 arch/x86/x86_64/mm.c       |    4 +--
 common/grant_table.c       |   25 ++++++++++++----------
 include/asm-x86/flushtlb.h |   49 +++++++++++++++++----------------------------
 include/asm-x86/page.h     |   13 -----------
 8 files changed, 70 insertions(+), 75 deletions(-)


diff -Nru a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c 2005-03-31 09:02:28 -05:00
+++ b/xen/arch/x86/mm.c 2005-03-31 09:02:28 -05:00
@@ -1476,23 +1476,34 @@
             break;
     
         case MMUEXT_INVLPG_LOCAL:
-            __flush_tlb_one(op.linear_addr);
+            local_flush_tlb_one(op.linear_addr);
             break;
 
         case MMUEXT_TLB_FLUSH_MULTI:
-            flush_tlb_mask(d->cpuset); /* XXX KAF XXX */
-            break;
-    
         case MMUEXT_INVLPG_MULTI:
-            flush_tlb_mask(d->cpuset); /* XXX KAF XXX */
+        {
+            unsigned long inset = op.cpuset, outset = 0;
+            while ( inset != 0 )
+            {
+                unsigned int vcpu = find_first_set_bit(inset);
+                inset &= ~(1UL<<vcpu);
+                if ( (vcpu < MAX_VIRT_CPUS) &&
+                     ((ed = d->exec_domain[vcpu]) != NULL) )
+                    outset |= 1UL << ed->processor;
+            }
+            if ( op.cmd == MMUEXT_TLB_FLUSH_MULTI )
+                flush_tlb_mask(outset & d->cpuset);
+            else
+                flush_tlb_one_mask(outset & d->cpuset, op.linear_addr);
             break;
+        }
 
         case MMUEXT_TLB_FLUSH_ALL:
             flush_tlb_mask(d->cpuset);
             break;
     
         case MMUEXT_INVLPG_ALL:
-            flush_tlb_mask(d->cpuset); /* XXX KAF XXX */
+            flush_tlb_one_mask(d->cpuset, op.linear_addr);
             break;
 
         case MMUEXT_FLUSH_CACHE:
@@ -2029,10 +2040,10 @@
         percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
         break;
     case UVMF_INVLPG_LOCAL:
-        __flush_tlb_one(va);
+        local_flush_tlb_one(va);
         break;
     case UVMF_INVLPG_ALL:
-        flush_tlb_mask(d->cpuset); /* XXX KAF XXX */
+        flush_tlb_one_mask(d->cpuset, va);
         break;
     }
 
@@ -2317,7 +2328,7 @@
 
     /* Ensure that there are no stale writable mappings in any TLB. */
     /* NB. INVLPG is a serialising instruction: flushes pending updates. */
-    __flush_tlb_one(l1va); /* XXX Multi-CPU guests? */
+    local_flush_tlb_one(l1va); /* XXX Multi-CPU guests? */
     PTWR_PRINTK("[%c] disconnected_l1va at %p now %p\n",
                 PTWR_PRINT_WHICH, ptep, pte);
 
@@ -2636,7 +2647,7 @@
          likely(!shadow_mode_enabled(ed->domain)) )
     {
         *pl2e = mk_l2_pgentry(l2e & ~_PAGE_PRESENT);
-        flush_tlb(); /* XXX Multi-CPU guests? */
+        local_flush_tlb(); /* XXX Multi-CPU guests? */
     }
     
     /* Temporarily map the L1 page, and make a copy of it. */
diff -Nru a/xen/arch/x86/mtrr/generic.c b/xen/arch/x86/mtrr/generic.c
--- a/xen/arch/x86/mtrr/generic.c       2005-03-31 09:02:28 -05:00
+++ b/xen/arch/x86/mtrr/generic.c       2005-03-31 09:02:28 -05:00
@@ -261,7 +261,7 @@
        }
 
        /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
-       __flush_tlb();
+       local_flush_tlb();
 
        /*  Save MTRR state */
        rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
@@ -273,7 +273,7 @@
 static void post_set(void)
 {
        /*  Flush TLBs (no need to flush caches - they are disabled)  */
-       __flush_tlb();
+       local_flush_tlb();
 
        /* Intel (P6) standard MTRRs */
        wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
diff -Nru a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
--- a/xen/arch/x86/smp.c        2005-03-31 09:02:28 -05:00
+++ b/xen/arch/x86/smp.c        2005-03-31 09:02:28 -05:00
@@ -148,17 +148,20 @@
 }
 
 static spinlock_t flush_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long flush_cpumask;
+static unsigned long flush_cpumask, flush_va;
 
 asmlinkage void smp_invalidate_interrupt(void)
 {
     ack_APIC_irq();
     perfc_incrc(ipis);
-    local_flush_tlb();
+    if ( flush_va == FLUSHVA_ALL )
+        local_flush_tlb();
+    else
+        local_flush_tlb_one(flush_va);
     clear_bit(smp_processor_id(), &flush_cpumask);
 }
 
-void flush_tlb_mask(unsigned long mask)
+void __flush_tlb_mask(unsigned long mask, unsigned long va)
 {
     ASSERT(local_irq_is_enabled());
     
@@ -172,6 +175,7 @@
     {
         spin_lock(&flush_lock);
         flush_cpumask = mask;
+        flush_va      = va;
         send_IPI_mask(mask, INVALIDATE_TLB_VECTOR);
         while ( flush_cpumask != 0 )
             cpu_relax();
@@ -190,6 +194,7 @@
         spin_lock(&flush_lock);
         flush_cpumask  = (1UL << smp_num_cpus) - 1;
         flush_cpumask &= ~(1UL << smp_processor_id());
+        flush_va       = FLUSHVA_ALL;
         send_IPI_allbutself(INVALIDATE_TLB_VECTOR);
         while ( flush_cpumask != 0 )
             cpu_relax();
@@ -203,13 +208,13 @@
 
 static void flush_tlb_all_pge_ipi(void *info)
 {
-    __flush_tlb_pge();
+    local_flush_tlb_pge();
 }
 
 void flush_tlb_all_pge(void)
 {
     smp_call_function(flush_tlb_all_pge_ipi, 0, 1, 1);
-    __flush_tlb_pge();
+    local_flush_tlb_pge();
 }
 
 void smp_send_event_check_mask(unsigned long cpu_mask)
diff -Nru a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  2005-03-31 09:02:28 -05:00
+++ b/xen/arch/x86/x86_32/mm.c  2005-03-31 09:02:28 -05:00
@@ -48,7 +48,7 @@
         {
             /* Super-page mapping. */
             if ( (l2_pgentry_val(*pl2e) & _PAGE_PRESENT) )
-                __flush_tlb_pge();
+                local_flush_tlb_pge();
             *pl2e = mk_l2_pgentry(p|flags|_PAGE_PSE);
 
             v += 1 << L2_PAGETABLE_SHIFT;
@@ -66,7 +66,7 @@
             }
             pl1e = l2_pgentry_to_l1(*pl2e) + l1_table_offset(v);
             if ( (l1_pgentry_val(*pl1e) & _PAGE_PRESENT) )
-                __flush_tlb_one(v);
+                local_flush_tlb_one(v);
             *pl1e = mk_l1_pgentry(p|flags);
 
             v += 1 << L1_PAGETABLE_SHIFT;
diff -Nru a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  2005-03-31 09:02:28 -05:00
+++ b/xen/arch/x86/x86_64/mm.c  2005-03-31 09:02:28 -05:00
@@ -89,7 +89,7 @@
         {
             /* Super-page mapping. */
             if ( (l2_pgentry_val(*pl2e) & _PAGE_PRESENT) )
-                __flush_tlb_pge();
+                local_flush_tlb_pge();
             *pl2e = mk_l2_pgentry(p|flags|_PAGE_PSE);
 
             v += 1 << L2_PAGETABLE_SHIFT;
@@ -107,7 +107,7 @@
             }
             pl1e = l2_pgentry_to_l1(*pl2e) + l1_table_offset(v);
             if ( (l1_pgentry_val(*pl1e) & _PAGE_PRESENT) )
-                __flush_tlb_one(v);
+                local_flush_tlb_one(v);
             *pl1e = mk_l1_pgentry(p|flags);
 
             v += 1 << L1_PAGETABLE_SHIFT;
diff -Nru a/xen/common/grant_table.c b/xen/common/grant_table.c
--- a/xen/common/grant_table.c  2005-03-31 09:02:28 -05:00
+++ b/xen/common/grant_table.c  2005-03-31 09:02:28 -05:00
@@ -102,7 +102,8 @@
     if ( ((host_virt_addr != 0) || (flags & GNTMAP_host_map) ) &&
          unlikely(!__addr_ok(host_virt_addr)))
     {
-        DPRINTK("Bad virtual address (%x) or flags (%x).\n", host_virt_addr, 
flags);
+        DPRINTK("Bad virtual address (%x) or flags (%x).\n",
+                host_virt_addr, flags);
         (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
         return GNTST_bad_gntref;
     }
@@ -332,8 +333,10 @@
          */
     }
 
-    /* Only make the maptrack live _after_ writing the pte, in case
-     * we overwrite the same frame number, causing a maptrack walk to find it 
*/
+    /*
+     * Only make the maptrack live _after_ writing the pte, in case we 
+     * overwrite the same frame number, causing a maptrack walk to find it.
+     */
     ld->grant_table->maptrack[handle].domid         = dom;
     ld->grant_table->maptrack[handle].ref_and_flags =
         (ref << MAPTRACK_REF_SHIFT) | (flags & MAPTRACK_GNTMAP_MASK);
@@ -364,13 +367,14 @@
     unsigned long va = 0;
 
     for ( i = 0; i < count; i++ )
-        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0)
+        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 )
             flush++;
 
+    /* XXX KAF: I think we are probably flushing too much here. */
     if ( flush == 1 )
-        __flush_tlb_one(va);
+        flush_tlb_one_mask(current->domain->cpuset, va);
     else if ( flush != 0 )
-        local_flush_tlb();
+        flush_tlb_mask(current->domain->cpuset);
 
     return 0;
 }
@@ -457,7 +461,7 @@
         unsigned long   _ol1e;
 
         pl1e = &linear_pg_table[l1_linear_offset(virt)];
-                                                                               
             
+
         if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
         {
             DPRINTK("Could not find PTE entry for address %x\n", virt);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.