Skip to contentSkip to conversation

Use superpages on restore/migrate

PATCH New George Dunlap 6 participants 15 messages May 6, 2011 – Jun 14, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Use superpages on restore/migrate

This patch series restores the use of superpages when restoring or migrating a VM, while retaining efficient batching of 4k pages when superpages are not appropriate or available.

#1 lore raw

PATCH 1/1 p2m: Keep statistics on order of p2m entries

Count the number of 4kiB, 2MiB, and 1GiB p2m entries.

xen/arch/x86/mm/hap/p2m-ept.c +24 -4
diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
@@ -39,6 +39,8 @@
 
 #define is_epte_present(ept_entry)      ((ept_entry)->epte & 0x7)
 #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+#define is_epte_countable(ept_entry)    (is_epte_present(ept_entry) \
+                                         || ((ept_entry)->sa_p2mt == p2m_populate_on_demand))
 
 /* Non-ept "lock-and-check" wrapper */
 static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,
@@ -167,11 +169,14 @@
 void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
 {
     /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
         return;
+    }
 
-    if ( level > 1 )
+    if ( level > 0 )
     {
         ept_entry_t *epte = map_domain_page(ept_entry->mfn);
         for ( int i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
@@ -217,7 +222,10 @@
         ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
 
         if ( (level - 1) == target )
+        {
+            p2m->stats.entries[target]++;
             continue;
+        }
 
         ASSERT(is_epte_superpage(epte));
 
@@ -400,6 +408,10 @@
             ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
         }
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
         atomic_write_ept_entry(ept_entry, new_entry);
     }
     else
@@ -412,12 +424,16 @@
 
         split_ept_entry = atomic_read_ept_entry(ept_entry);
 
+        /* Accounting should be OK here; split_ept_entry bump the counts,
+         * free_entry will reduce them. */
         if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
         {
             ept_free_entry(p2m, &split_ept_entry, i);
             goto out;
         }
 
+        /* We know this was countable or we wouldn't be here.*/
+        p2m->stats.entries[i]--;
         /* now install the newly split ept sub-tree */
         /* NB: please make sure domian is paused and no in-fly VT-d DMA. */
         atomic_write_ept_entry(ept_entry, split_ept_entry);
@@ -449,9 +465,13 @@
 
         ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
         atomic_write_ept_entry(ept_entry, new_entry);
     }
-
+ 
     /* Track the highest gfn for which we have ever had a valid mapping */
     if ( mfn_valid(mfn_x(mfn)) &&
          (gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
xen/arch/x86/mm/p2m.c +42 -3

111 lines not on this page · raw message

xen/include/asm-x86/p2m.h +4 -0
diff -r 4b0692880dfa -r be5d93d38f28 xen/include/asm-x86/p2m.h
@@ -278,6 +278,10 @@
         unsigned         reclaim_single; /* Last gpfn of a scan */
         unsigned         max_guest;    /* gpfn of max guest demand-populate */
     } pod;
+
+    struct {
+        long entries[3]; 
+    } stats;
 };
 
 /* get host p2m table */
#12 lore raw

PATCH 1/1 tools: Detect superpages on domain restore

In reply to George Dunlap

When receiving pages, look for contiguous 2-meg aligned regions and attempt to allocate a superpage for that region, falling back to 4k pages if the allocation fails.

tools/libxc/xc_domain_restore.c +106 -16
diff -r be5d93d38f28 -r 9b4c0f2f5b9e tools/libxc/xc_domain_restore.c
@@ -48,6 +48,11 @@
 
 #define HEARTBEAT_MS 1000
 
+#define SUPERPAGE_PFN_SHIFT  9
+#define SUPERPAGE_NR_PFNS    (1UL << SUPERPAGE_PFN_SHIFT)
+
+#define SUPER_PAGE_START(pfn)    (((pfn) & (SUPERPAGE_NR_PFNS-1)) == 0 )
+
 #ifndef __MINIOS__
 static ssize_t rdexact(xc_interface *xch, struct restore_ctx *ctx,
                        int fd, void* buf, size_t size)
@@ -882,9 +887,11 @@
 static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
                        xen_pfn_t* region_mfn, unsigned long* pfn_type, int pae_extended_cr3,
                        unsigned int hvm, struct xc_mmu* mmu,
-                       pagebuf_t* pagebuf, int curbatch)
+                       pagebuf_t* pagebuf, int curbatch, int superpages)
 {
     int i, j, curpage, nr_mfns;
+    int k, scount;
+    unsigned long superpage_start=INVALID_P2M_ENTRY;
     /* used by debug verify code */
     unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
     /* Our mapping of the current region (batch) */
@@ -902,8 +909,8 @@
     if (j > MAX_BATCH_SIZE)
         j = MAX_BATCH_SIZE;
 
-    /* First pass for this batch: work out how much memory to alloc */
-    nr_mfns = 0; 
+    /* First pass for this batch: work out how much memory to alloc, and detect superpages */
+    nr_mfns = scount = 0;
     for ( i = 0; i < j; i++ )
     {
         unsigned long pfn, pagetype;
@@ -914,19 +921,103 @@
              (ctx->p2m[pfn] == INVALID_P2M_ENTRY) )
         {
             /* Have a live PFN which hasn't had an MFN allocated */
+
+            /* Logic if we're in the middle of detecting a candidate superpage */
+            if ( superpage_start != INVALID_P2M_ENTRY )
+            {
+                /* Is this the next expected continuation? */
+                if ( pfn == superpage_start + scount )
+                {
+                    if ( !superpages )
+                    {
+                        ERROR("Unexpexted codepath with no superpages");
+                        return -1;
+                    }
+
+                    scount++;
+
+                    /* If we've found a whole superpage, allocate it and update p2m */
+                    if ( scount  == SUPERPAGE_NR_PFNS )
+                    {
+                        unsigned long supermfn;
+
+
+                        supermfn=superpage_start;
+                        if ( xc_domain_populate_physmap_exact(xch, dom, 1,
+                                         SUPERPAGE_PFN_SHIFT, 0, &supermfn) != 0 )
+                        {
+                            DPRINTF("No 2M page available for pfn 0x%lx, fall back to 4K page.\n",
+                                    superpage_start);
+                            /* If we're falling back from a failed allocation, subtract one
+                             * from count, since the last page == pfn, which will behandled
+                             * anyway. */
+                            scount--;
+                            goto fallback;
+                        }
+
+                        DPRINTF("Mapping superpage (%d) pfn %lx, mfn %lx\n", scount, superpage_start, supermfn);
+                        for (k=0; k<scount; k++)
+                        {
+                            /* We just allocated a new mfn above; update p2m */
+                            ctx->p2m[superpage_start+k] = supermfn+k;
+                            ctx->nr_pfns++;
+                            /* region_map[] will be set below */
+                        }
+                        superpage_start=INVALID_P2M_ENTRY;
+                        scount=0;
+                    }
+                    continue;
+                }
+                
+            fallback:
+                DPRINTF("Falling back %d pages pfn %lx\n", scount, superpage_start);
+                for (k=0; k<scount; k++)
+                {
+                    ctx->p2m_batch[nr_mfns++] = superpage_start+k; 
+                    ctx->p2m[superpage_start+k]--;
+                }
+                superpage_start = INVALID_P2M_ENTRY;
+                scount=0;
+            }
+
+            /* Are we ready to start a new superpage candidate? */
+            if ( superpages && SUPER_PAGE_START(pfn) )
+            {
+                superpage_start=pfn;
+                scount++;
+                continue;
+            }
+            
+            /* Add the current pfn to pfn_batch */
             ctx->p2m_batch[nr_mfns++] = pfn; 
             ctx->p2m[pfn]--;
         }
-    } 
+    }
+
+    /* Clean up any partial superpage candidates */
+    if ( superpage_start != INVALID_P2M_ENTRY )
+    {
+        DPRINTF("Falling back %d pages pfn %lx\n", scount, superpage_start);
+        for (k=0; k<scount; k++)
+        {
+            ctx->p2m_batch[nr_mfns++] = superpage_start+k; 
+            ctx->p2m[superpage_start+k]--;
+        }
+        superpage_start = INVALID_P2M_ENTRY;
+    }
 
     /* Now allocate a bunch of mfns for this batch */
-    if ( nr_mfns &&
-         (xc_domain_populate_physmap_exact(xch, dom, nr_mfns, 0,
-                                            0, ctx->p2m_batch) != 0) )
-    { 
-        ERROR("Failed to allocate memory for batch.!\n"); 
-        errno = ENOMEM;
-        return -1;
+    if ( nr_mfns )
+    {
+        DPRINTF("Mapping order 0,  %d; first pfn %lx\n", nr_mfns, ctx->p2m_batch[0]);
+    
+        if(xc_domain_populate_physmap_exact(xch, dom, nr_mfns, 0,
+                                            0, ctx->p2m_batch) != 0) 
+        { 
+            ERROR("Failed to allocate memory for batch.!\n"); 
+            errno = ENOMEM;
+            return -1;
+        }
     }
 
     /* Second pass for this batch: update p2m[] and region_mfn[] */
@@ -977,7 +1068,8 @@
 
         if (pfn_err[i])
         {
-            ERROR("unexpected PFN mapping failure");
+            ERROR("unexpected PFN mapping failure pfn %lx map_mfn %lx p2m_mfn %lx",
+                  pfn, region_mfn[i], ctx->p2m[pfn]);
             goto err_mapped;
         }
 
@@ -1148,9 +1240,6 @@
     /* For info only */
     ctx->nr_pfns = 0;
 
-    if ( superpages )
-        return 1;
-
     ctxt = xc_hypercall_buffer_alloc(xch, ctxt, sizeof(*ctxt));
 
     if ( ctxt == NULL )
@@ -1298,7 +1387,8 @@
             int brc;
 
             brc = apply_batch(xch, dom, ctx, region_mfn, pfn_type,
-                              pae_extended_cr3, hvm, mmu, &pagebuf, curbatch);
+                              pae_extended_cr3, hvm, mmu, &pagebuf, curbatch,
+                              superpages);
             if ( brc < 0 )
                 goto out;
#13 lore raw

PATCH 1/1 tools: Save superpages in the same batch, to make detection easier

In reply to George Dunlap

On the first time through (when pfns are mostly allocated on the receiving side), try to keep superpages together in the same batch by ending a batch early if we see the first page of a potential superpage and there isn't enough room in the batch for a full superpage.

tools/libxc/xc_domain_save.c +12 -0
diff -r 9b4c0f2f5b9e -r 3fa5cca65bac tools/libxc/xc_domain_save.c
@@ -82,6 +82,11 @@
      ((mfn_to_pfn(_mfn) < (dinfo->p2m_size)) &&   \
       (pfn_to_mfn(mfn_to_pfn(_mfn)) == (_mfn))))
 
+#define SUPERPAGE_PFN_SHIFT  9
+#define SUPERPAGE_NR_PFNS    (1UL << SUPERPAGE_PFN_SHIFT)
+
+#define SUPER_PAGE_START(pfn)    (((pfn) & (SUPERPAGE_NR_PFNS-1)) == 0 )
+
 /*
 ** During (live) save/migrate, we maintain a number of bitmaps to track
 ** which pages we have to send, to fixup, and to skip.
@@ -906,6 +911,7 @@
     int rc = 1, frc, i, j, last_iter = 0, iter = 0;
     int live  = (flags & XCFLAGS_LIVE);
     int debug = (flags & XCFLAGS_DEBUG);
+    int superpages = !!hvm;
     int race = 0, sent_last_iter, skip_this_iter = 0;
     unsigned int sent_this_iter = 0;
     int tmem_saved = 0;
@@ -1262,6 +1268,12 @@
                            (test_bit(n, to_fix)  && last_iter)) )
                         continue;
 
+                    /* First time through, try to keep superpages in the same batch */
+                    if ( superpages && iter == 1
+                         && SUPER_PAGE_START(n)
+                         && batch + SUPERPAGE_NR_PFNS > MAX_BATCH_SIZE )
+                        break;
+
                     /*
                     ** we get here if:
                     **  1. page is marked to_send & hasn't already been re-dirtied
#14 lore raw

PATCH 1/1 tools: Introduce "allocate-only" page type for migration

In reply to George Dunlap

To detect presence of superpages on the receiver side, we need to have strings of sequential pfns sent across on the first iteration through the memory. However, as we go through the memory, more and more of it will be marked dirty, making it wasteful to send those pages.

This patch introduces a new PFINFO type, "XALLOC". Like PFINFO_XTAB, it indicates that there is no corresponding page present in the subsquent page buffer. However, unlike PFINFO_XTAB, it contains a pfn which should be allocated.

This new type is only used for migration; but it's placed in xen/public/domctl.h so that the value isn't reused.

tools/libxc/xc_domain_restore.c +19 -16
diff -r 3fa5cca65bac -r aeb70017bf60 tools/libxc/xc_domain_restore.c
@@ -839,7 +839,8 @@
 
     countpages = count;
     for (i = oldcount; i < buf->nr_pages; ++i)
-        if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB)
+        if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB
+            ||(buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XALLOC)
             --countpages;
 
     if (!countpages)
@@ -917,6 +918,7 @@
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
+        /* For allocation purposes, treat XEN_DOMCTL_PFINFO_XALLOC as a normal page */
         if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
              (ctx->p2m[pfn] == INVALID_P2M_ENTRY) )
         {
@@ -1028,21 +1030,21 @@
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
-        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
+        if ( pagetype != XEN_DOMCTL_PFINFO_XTAB
+             && ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) )
+        {
+            /* We just allocated a new mfn above; update p2m */
+            ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; 
+            ctx->nr_pfns++; 
+        }
+
+        /* setup region_mfn[] for batch map, if necessary.
+         * For HVM guests, this interface takes PFNs, not MFNs */
+        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
+             || pagetype == XEN_DOMCTL_PFINFO_XALLOC )
             region_mfn[i] = ~0UL; /* map will fail but we don't care */
-        else 
-        {
-            if ( ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) )
-            {
-                /* We just allocated a new mfn above; update p2m */
-                ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; 
-                ctx->nr_pfns++; 
-            }
-
-            /* setup region_mfn[] for batch map.
-             * For HVM guests, this interface takes PFNs, not MFNs */
+        else
             region_mfn[i] = hvm ? pfn : ctx->p2m[pfn]; 
-        }
     }
 
     /* Map relevant mfns */
@@ -1062,8 +1064,9 @@
         pfn      = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
         pagetype = pagebuf->pfn_types[i + curbatch] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
 
-        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
-            /* a bogus/unmapped page: skip it */
+        if ( pagetype == XEN_DOMCTL_PFINFO_XTAB 
+             || pagetype == XEN_DOMCTL_PFINFO_XALLOC)
+            /* a bogus/unmapped/allocate-only page: skip it */
             continue;
 
         if (pfn_err[i])
tools/libxc/xc_domain_save.c +13 -6
diff -r 3fa5cca65bac -r aeb70017bf60 tools/libxc/xc_domain_save.c
@@ -1258,13 +1258,15 @@
                 }
                 else
                 {
-                    if ( !last_iter &&
+                    int dont_skip = (last_iter || (superpages && iter==1));
+
+                    if ( !dont_skip &&
                          test_bit(n, to_send) &&
                          test_bit(n, to_skip) )
                         skip_this_iter++; /* stats keeping */
 
                     if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
-                           (test_bit(n, to_send) && last_iter) ||
+                           (test_bit(n, to_send) && dont_skip) ||
                            (test_bit(n, to_fix)  && last_iter)) )
                         continue;
 
@@ -1277,7 +1279,7 @@
                     /*
                     ** we get here if:
                     **  1. page is marked to_send & hasn't already been re-dirtied
-                    **  2. (ignore to_skip in last iteration)
+                    **  2. (ignore to_skip in first and last iterations)
                     **  3. add in pages that still need fixup (net bufs)
                     */
 
@@ -1301,7 +1303,7 @@
                         set_bit(n, to_fix);
                         continue;
                     }
-
+                    
                     if ( last_iter &&
                          test_bit(n, to_fix) &&
                          !test_bit(n, to_send) )
@@ -1346,6 +1348,7 @@
                 {
                     if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB )
                         continue;
+
                     DPRINTF("map fail: page %i mfn %08lx err %d\n",
                             j, gmfn, pfn_err[j]);
                     pfn_type[j] = XEN_DOMCTL_PFINFO_XTAB;
@@ -1358,6 +1361,9 @@
                     continue;
                 }
 
+                if ( superpages && iter==1 && test_bit(gmfn, to_skip))
+                    pfn_type[j] = XEN_DOMCTL_PFINFO_XALLOC;
+
                 /* canonicalise mfn->pfn */
                 pfn_type[j] |= pfn_batch[j];
                 ++run;
@@ -1432,8 +1438,9 @@
                     }
                 }
 
-                /* skip pages that aren't present */
-                if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
+                /* skip pages that aren't present or are alloc-only */
+                if ( pagetype == XEN_DOMCTL_PFINFO_XTAB
+                    || pagetype == XEN_DOMCTL_PFINFO_XALLOC )
                     continue;
 
                 pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
xen/include/public/domctl.h +1 -0
diff -r 3fa5cca65bac -r aeb70017bf60 xen/include/public/domctl.h
@@ -133,6 +133,7 @@
 #define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
 #define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
 #define XEN_DOMCTL_PFINFO_XTAB    (0xfU<<28) /* invalid page */
+#define XEN_DOMCTL_PFINFO_XALLOC  (0xeU<<28) /* allocate-only page */
 #define XEN_DOMCTL_PFINFO_PAGEDTAB (0x8U<<28)
 #define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)
#2 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to George Dunlap

Hi,

Can you please add this:

[diff]
showfunc = True

to your .hgrc? It makes reviewing much easier.

There are two places where this patch changes the control flow of p2m operations:

Quoted 6 lines
xen/arch/x86/mm/hap/p2m-ept.c +0 -2
@@ -167,11 +169,14 @@
 void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
 {
     /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )

xen/arch/x86/mm/hap/p2m-ept.c line 180

Quoted 10 lines
xen/arch/x86/mm/hap/p2m-ept.c +6 -1
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
         return;
+    }
 
-    if ( level > 1 )
+    if ( level > 0 )
     {

and similarly:

Quoted 6 lines
xen/arch/x86/mm/p2m.c +1 -1
@@ -184,11 +184,15 @@
 {
     /* End if the entry is a leaf entry. */
     if ( page_order == 0
-         || !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) 

xen/arch/x86/mm/p2m.c line 195

Quoted 10 lines
xen/arch/x86/mm/p2m.c +6 -2
          || (l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
         return;
-
-    if ( page_order > 9 )
+    }
+
+    if ( page_order )

here. Can you explain those in a bit more detail?

Cheers,

Tim.

Signature · 3 lines
Tim Deegan <[email protected]>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd.  (Company #02937203, SL9 0BG)
#4 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to George Dunlap

Hi,

Can you please use defines for the indexes of p2m->stats.entries[], please? That makes it easier to read what you are counting.

Christoph

Quoted 232 lines · George Dunlap

Count the number of 4kiB, 2MiB, and 1GiB p2m entries.

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c

xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100 +24 -4
@@ -39,6 +39,8 @@
 
  #define is_epte_present(ept_entry)      ((ept_entry)->epte&  0x7)
  #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+#define is_epte_countable(ept_entry)    (is_epte_present(ept_entry) \
+                                         || ((ept_entry)->sa_p2mt == p2m_populate_on_demand))
 
  /* Non-ept "lock-and-check" wrapper */
  static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,
@@ -167,11 +169,14 @@
  void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
  {
      /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
          return;
+    }
 
-    if ( level>  1 )
+    if ( level>  0 )
      {
          ept_entry_t *epte = map_domain_page(ept_entry->mfn);
          for ( int i = 0; i<  EPT_PAGETABLE_ENTRIES; i++ )
@@ -217,7 +222,10 @@
          ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
 
          if ( (level - 1) == target )
+        {
+            p2m->stats.entries[target]++;
              continue;
+        }
 
          ASSERT(is_epte_superpage(epte));
 
@@ -400,6 +408,10 @@
              ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
          }
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
          atomic_write_ept_entry(ept_entry, new_entry);
      }
      else
@@ -412,12 +424,16 @@
 
          split_ept_entry = atomic_read_ept_entry(ept_entry);
 
+        /* Accounting should be OK here; split_ept_entry bump the counts,
+         * free_entry will reduce them. */
          if ( !ept_split_super_page(p2m,&split_ept_entry, i, target) )
          {
              ept_free_entry(p2m,&split_ept_entry, i);
              goto out;
          }
 
+        /* We know this was countable or we wouldn't be here.*/
+        p2m->stats.entries[i]--;
          /* now install the newly split ept sub-tree */
          /* NB: please make sure domian is paused and no in-fly VT-d DMA. */
          atomic_write_ept_entry(ept_entry, split_ept_entry);
@@ -449,9 +465,13 @@
 
          ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
          atomic_write_ept_entry(ept_entry, new_entry);
      }
-
+
      /* Track the highest gfn for which we have ever had a valid mapping */
      if ( mfn_valid(mfn_x(mfn))&&
           (gfn + (1UL<<  order) - 1>  p2m->max_mapped_pfn) )

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/p2m.c

xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100 +42 -3
@@ -184,11 +184,15 @@
  {
      /* End if the entry is a leaf entry. */
      if ( page_order == 0
-         || !(l1e_get_flags(*p2m_entry)&  _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry)&  _PAGE_PRESENT)
           || (l1e_get_flags(*p2m_entry)&  _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
          return;
-
-    if ( page_order>  9 )
+    }
+
+    if ( page_order )
      {
          l1_pgentry_t *l3_table = map_domain_page(l1e_get_pfn(*p2m_entry));
          for ( int i = 0; i<  L3_PAGETABLE_ENTRIES; i++ )
@@ -242,6 +246,7 @@
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR | _PAGE_USER);
 
+        /* Stats: Empty entry, no mods needed */
          switch ( type ) {
          case PGT_l3_page_table:
              p2m_add_iommu_flags(&new_entry, 3, IOMMUF_readable|IOMMUF_writable);
@@ -285,10 +290,12 @@
          {
              new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
              p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+            p2m->stats.entries[1]++;
              p2m->write_p2m_entry(p2m, gfn,
                  l1_entry+i, *table_mfn, new_entry, 2);
          }
          unmap_domain_page(l1_entry);
+        p2m->stats.entries[2]--;
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
          p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
@@ -320,6 +327,7 @@
          {
              new_entry = l1e_from_pfn(pfn + i, flags);
              p2m_add_iommu_flags(&new_entry, 0, 0);
+            p2m->stats.entries[0]++;
              p2m->write_p2m_entry(p2m, gfn,
                  l1_entry+i, *table_mfn, new_entry, 1);
          }
@@ -328,6 +336,7 @@
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR|_PAGE_USER);
          p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+        p2m->stats.entries[1]--;
          p2m->write_p2m_entry(p2m, gfn,
              p2m_entry, *table_mfn, new_entry, 2);
      }
@@ -908,6 +917,15 @@
  void
  p2m_pod_dump_data(struct p2m_domain *p2m)
  {
+    int i;
+    long entries;
+    printk("    P2M entry stats:\n");
+    for ( i=0; i<3; i++)
+        if ( (entries=p2m->stats.entries[i]) )
+            printk("     L%d: %8ld entries, %ld bytes\n",
+                   i+1,
+                   entries,
+                   entries<<(i*9+12));
      printk("    PoD entries=%d cachesize=%d\n",
             p2m->pod.entry_count, p2m->pod.count);
  }
@@ -1475,6 +1493,12 @@
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -1519,6 +1543,13 @@
              p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
+
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          /* level 1 entry */
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -1556,6 +1587,12 @@
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -2750,6 +2787,8 @@
                  continue;
              }
 
+            /* STATS: Should change only type; no stats should need adjustment */
+
              l2mfn = _mfn(l3e_get_pfn(l3e[i3]));
              l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
              for ( i2 = 0; i2<  L2_PAGETABLE_ENTRIES; i2++ )

diff -r 4b0692880dfa -r be5d93d38f28 xen/include/asm-x86/p2m.h

xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100 renamed from xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100 +4 -0
@@ -278,6 +278,10 @@
          unsigned         reclaim_single; /* Last gpfn of a scan */
          unsigned         max_guest;    /* gpfn of max guest demand-populate */
      } pod;
+
+    struct {
+        long entries[3];
+    } stats;
  };
 
  /* get host p2m table */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

Signature · 6 lines
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85689 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632
#6 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to Tim Deegan
Quoted 10 lines · Tim Deegan

Hello,

Quoted 2 lines · Christoph Egger

Can you please use defines for the indexes of p2m->stats.entries[], please? That makes it easier to read what you are counting.

I'm not sure that's a great idea. The array is indexed in several places by integer already, and the defines are unlikely to be much more illuminating unless you can think of some better naming scheme than "#define LEVEL_0 0" etc.

What about this:

#define PAGE_ORDER_4K  0
#define PAGE_ORDER_2M  9
#define PAGE_ORDER_1G  18
Quoted 233 lines

On the other hand, maybe the array itself could have a more descriptive name than "stats.entries".

Tim.

Quoted 227 lines · George Dunlap
Quoted 226 lines

Count the number of 4kiB, 2MiB, and 1GiB p2m entries.

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c

xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100 +24 -4
@@ -39,6 +39,8 @@
 
   #define is_epte_present(ept_entry)      ((ept_entry)->epte&   0x7)
   #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+#define is_epte_countable(ept_entry)    (is_epte_present(ept_entry) \
+                                         || ((ept_entry)->sa_p2mt == p2m_populate_on_demand))
 
   /* Non-ept "lock-and-check" wrapper */
   static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,
@@ -167,11 +169,14 @@
   void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
   {
       /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
           return;
+    }
 
-    if ( level>   1 )
+    if ( level>   0 )
       {
           ept_entry_t *epte = map_domain_page(ept_entry->mfn);
           for ( int i = 0; i<   EPT_PAGETABLE_ENTRIES; i++ )
@@ -217,7 +222,10 @@
           ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
 
           if ( (level - 1) == target )
+        {
+            p2m->stats.entries[target]++;
               continue;
+        }
 
           ASSERT(is_epte_superpage(epte));
 
@@ -400,6 +408,10 @@
               ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
           }
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
           atomic_write_ept_entry(ept_entry, new_entry);
       }
       else
@@ -412,12 +424,16 @@
 
           split_ept_entry = atomic_read_ept_entry(ept_entry);
 
+        /* Accounting should be OK here; split_ept_entry bump the counts,
+         * free_entry will reduce them. */
           if ( !ept_split_super_page(p2m,&split_ept_entry, i, target) )
           {
               ept_free_entry(p2m,&split_ept_entry, i);
               goto out;
           }
 
+        /* We know this was countable or we wouldn't be here.*/
+        p2m->stats.entries[i]--;
           /* now install the newly split ept sub-tree */
           /* NB: please make sure domian is paused and no in-fly VT-d DMA. */
           atomic_write_ept_entry(ept_entry, split_ept_entry);
@@ -449,9 +465,13 @@
 
           ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
           atomic_write_ept_entry(ept_entry, new_entry);
       }
-
+
       /* Track the highest gfn for which we have ever had a valid mapping */
       if ( mfn_valid(mfn_x(mfn))&&
            (gfn + (1UL<<   order) - 1>   p2m->max_mapped_pfn) )

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/p2m.c

xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100 +42 -3
@@ -184,11 +184,15 @@
   {
       /* End if the entry is a leaf entry. */
       if ( page_order == 0
-         || !(l1e_get_flags(*p2m_entry)&   _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry)&   _PAGE_PRESENT)
            || (l1e_get_flags(*p2m_entry)&   _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
           return;
-
-    if ( page_order>   9 )
+    }
+
+    if ( page_order )
       {
           l1_pgentry_t *l3_table = map_domain_page(l1e_get_pfn(*p2m_entry));
           for ( int i = 0; i<   L3_PAGETABLE_ENTRIES; i++ )
@@ -242,6 +246,7 @@
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                    __PAGE_HYPERVISOR | _PAGE_USER);
 
+        /* Stats: Empty entry, no mods needed */
           switch ( type ) {
           case PGT_l3_page_table:
               p2m_add_iommu_flags(&new_entry, 3, IOMMUF_readable|IOMMUF_writable);
@@ -285,10 +290,12 @@
           {
               new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
               p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+            p2m->stats.entries[1]++;
               p2m->write_p2m_entry(p2m, gfn,
                   l1_entry+i, *table_mfn, new_entry, 2);
           }
           unmap_domain_page(l1_entry);
+        p2m->stats.entries[2]--;
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                    __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
           p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
@@ -320,6 +327,7 @@
           {
               new_entry = l1e_from_pfn(pfn + i, flags);
               p2m_add_iommu_flags(&new_entry, 0, 0);
+            p2m->stats.entries[0]++;
               p2m->write_p2m_entry(p2m, gfn,
                   l1_entry+i, *table_mfn, new_entry, 1);
           }
@@ -328,6 +336,7 @@
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                    __PAGE_HYPERVISOR|_PAGE_USER);
           p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+        p2m->stats.entries[1]--;
           p2m->write_p2m_entry(p2m, gfn,
               p2m_entry, *table_mfn, new_entry, 2);
       }
@@ -908,6 +917,15 @@
   void
   p2m_pod_dump_data(struct p2m_domain *p2m)
   {
+    int i;
+    long entries;
+    printk("    P2M entry stats:\n");
+    for ( i=0; i<3; i++)
+        if ( (entries=p2m->stats.entries[i]) )
+            printk("     L%d: %8ld entries, %ld bytes\n",
+                   i+1,
+                   entries,
+                   entries<<(i*9+12));
       printk("    PoD entries=%d cachesize=%d\n",
              p2m->pod.entry_count, p2m->pod.count);
   }
@@ -1475,6 +1493,12 @@
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
           /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -1519,6 +1543,13 @@
               p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
+
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           /* level 1 entry */
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
           /* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -1556,6 +1587,12 @@
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
           /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -2750,6 +2787,8 @@
                   continue;
               }
 
+            /* STATS: Should change only type; no stats should need adjustment */
+
               l2mfn = _mfn(l3e_get_pfn(l3e[i3]));
               l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
               for ( i2 = 0; i2<   L2_PAGETABLE_ENTRIES; i2++ )

diff -r 4b0692880dfa -r be5d93d38f28 xen/include/asm-x86/p2m.h

xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100 renamed from xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100 +4 -0
@@ -278,6 +278,10 @@
           unsigned         reclaim_single; /* Last gpfn of a scan */
           unsigned         max_guest;    /* gpfn of max guest demand-populate */
       } pod;
+
+    struct {
+        long entries[3];
+    } stats;
   };
 
   /* get host p2m table */
Signature · 6 lines
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85689 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632
#5 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to Christoph Egger

Hello,

Quoted 2 lines · Christoph Egger

Can you please use defines for the indexes of p2m->stats.entries[], please? That makes it easier to read what you are counting.

I'm not sure that's a great idea. The array is indexed in several places by integer already, and the defines are unlikely to be much more illuminating unless you can think of some better naming scheme than "#define LEVEL_0 0" etc.

On the other hand, maybe the array itself could have a more descriptive name than "stats.entries".

Tim.

Quoted 248 lines · George Dunlap
Quoted 227 lines

Count the number of 4kiB, 2MiB, and 1GiB p2m entries.

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c

xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100 +24 -4
@@ -39,6 +39,8 @@
 
  #define is_epte_present(ept_entry)      ((ept_entry)->epte&  0x7)
  #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+#define is_epte_countable(ept_entry)    (is_epte_present(ept_entry) \
+                                         || ((ept_entry)->sa_p2mt == p2m_populate_on_demand))
 
  /* Non-ept "lock-and-check" wrapper */
  static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,
@@ -167,11 +169,14 @@
  void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
  {
      /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
          return;
+    }
 
-    if ( level>  1 )
+    if ( level>  0 )
      {
          ept_entry_t *epte = map_domain_page(ept_entry->mfn);
          for ( int i = 0; i<  EPT_PAGETABLE_ENTRIES; i++ )
@@ -217,7 +222,10 @@
          ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
 
          if ( (level - 1) == target )
+        {
+            p2m->stats.entries[target]++;
              continue;
+        }
 
          ASSERT(is_epte_superpage(epte));
 
@@ -400,6 +408,10 @@
              ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
          }
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
          atomic_write_ept_entry(ept_entry, new_entry);
      }
      else
@@ -412,12 +424,16 @@
 
          split_ept_entry = atomic_read_ept_entry(ept_entry);
 
+        /* Accounting should be OK here; split_ept_entry bump the counts,
+         * free_entry will reduce them. */
          if ( !ept_split_super_page(p2m,&split_ept_entry, i, target) )
          {
              ept_free_entry(p2m,&split_ept_entry, i);
              goto out;
          }
 
+        /* We know this was countable or we wouldn't be here.*/
+        p2m->stats.entries[i]--;
          /* now install the newly split ept sub-tree */
          /* NB: please make sure domian is paused and no in-fly VT-d DMA. */
          atomic_write_ept_entry(ept_entry, split_ept_entry);
@@ -449,9 +465,13 @@
 
          ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
          atomic_write_ept_entry(ept_entry, new_entry);
      }
-
+
      /* Track the highest gfn for which we have ever had a valid mapping */
      if ( mfn_valid(mfn_x(mfn))&&
           (gfn + (1UL<<  order) - 1>  p2m->max_mapped_pfn) )

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/p2m.c

xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100 +42 -3
@@ -184,11 +184,15 @@
  {
      /* End if the entry is a leaf entry. */
      if ( page_order == 0
-         || !(l1e_get_flags(*p2m_entry)&  _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry)&  _PAGE_PRESENT)
           || (l1e_get_flags(*p2m_entry)&  _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
          return;
-
-    if ( page_order>  9 )
+    }
+
+    if ( page_order )
      {
          l1_pgentry_t *l3_table = map_domain_page(l1e_get_pfn(*p2m_entry));
          for ( int i = 0; i<  L3_PAGETABLE_ENTRIES; i++ )
@@ -242,6 +246,7 @@
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR | _PAGE_USER);
 
+        /* Stats: Empty entry, no mods needed */
          switch ( type ) {
          case PGT_l3_page_table:
              p2m_add_iommu_flags(&new_entry, 3, IOMMUF_readable|IOMMUF_writable);
@@ -285,10 +290,12 @@
          {
              new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
              p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+            p2m->stats.entries[1]++;
              p2m->write_p2m_entry(p2m, gfn,
                  l1_entry+i, *table_mfn, new_entry, 2);
          }
          unmap_domain_page(l1_entry);
+        p2m->stats.entries[2]--;
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
          p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
@@ -320,6 +327,7 @@
          {
              new_entry = l1e_from_pfn(pfn + i, flags);
              p2m_add_iommu_flags(&new_entry, 0, 0);
+            p2m->stats.entries[0]++;
              p2m->write_p2m_entry(p2m, gfn,
                  l1_entry+i, *table_mfn, new_entry, 1);
          }
@@ -328,6 +336,7 @@
          new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                   __PAGE_HYPERVISOR|_PAGE_USER);
          p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
+        p2m->stats.entries[1]--;
          p2m->write_p2m_entry(p2m, gfn,
              p2m_entry, *table_mfn, new_entry, 2);
      }
@@ -908,6 +917,15 @@
  void
  p2m_pod_dump_data(struct p2m_domain *p2m)
  {
+    int i;
+    long entries;
+    printk("    P2M entry stats:\n");
+    for ( i=0; i<3; i++)
+        if ( (entries=p2m->stats.entries[i]) )
+            printk("     L%d: %8ld entries, %ld bytes\n",
+                   i+1,
+                   entries,
+                   entries<<(i*9+12));
      printk("    PoD entries=%d cachesize=%d\n",
             p2m->pod.entry_count, p2m->pod.count);
  }
@@ -1475,6 +1493,12 @@
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -1519,6 +1543,13 @@
              p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
+
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          /* level 1 entry */
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -1556,6 +1587,12 @@
              old_mfn = l1e_get_pfn(*p2m_entry);
          }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
          p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
          /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -2750,6 +2787,8 @@
                  continue;
              }
 
+            /* STATS: Should change only type; no stats should need adjustment */
+
              l2mfn = _mfn(l3e_get_pfn(l3e[i3]));
              l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
              for ( i2 = 0; i2<  L2_PAGETABLE_ENTRIES; i2++ )

diff -r 4b0692880dfa -r be5d93d38f28 xen/include/asm-x86/p2m.h

xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100 renamed from xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100 +4 -0
@@ -278,6 +278,10 @@
          unsigned         reclaim_single; /* Last gpfn of a scan */
          unsigned         max_guest;    /* gpfn of max guest demand-populate */
      } pod;
+
+    struct {
+        long entries[3];
+    } stats;
  };
 
  /* get host p2m table */
Quoted 5 lines

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

--
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85689 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen Registergericht Muenchen, HRB Nr. 43632

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

Signature · 3 lines
Tim Deegan <[email protected]>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd.  (Company #02937203, SL9 0BG)
#3 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to Tim Deegan
Quoted 6 lines · Tim Deegan

Hi,

Can you please add this:

[diff]
showfunc = True

Ah, very helpful.

Quoted 2 lines

There are two places where this patch changes the control flow of p2m operations:

Oops -- yeah, those definitely need some comments.

The "*_free_entry()" functions are used when replacing smaller-order pages with a larger-order page. Most commonly this is replacing a bunch of 4k pages with a 2MiB page, but in theory you could be replacing a tree of mixed 4k and 2MiB pages with a 1G page as well.

When that happens, we also need to adjust the p2m order stats by:
* Decrementing stats on all the leaf entries being replaced
* Incrementing the stat for the new leaf entry.

Incrementing the stat for the new entry is done when the new entry is assigned. Decrementing stats requires walking the old p2m tables and finding valid leaf entries. Since *_free_entry() already do that, we just piggyback.

p2m entries are already checked at the entrance to the function to see if we're at a leaf. The patch adds appropriate reference counting if it is.

The other change is how far down the tree *_free_entry() functions go. Since their original purpose was only freeing intermediate tables, they don't bother to walk all the way down to l0. Since we want to do reference counting of the l0s as well, we just make it go all the way down.

This does mean making a function call for all 512 entries of the L1 table, but it should be a pretty rare operation. I could refactor the function to do the check before making the call instead, if desired.

Let me know if you want me to include this description in a new patch series.

-George

Quoted 43 lines
Quoted 7 lines
xen/arch/x86/mm/hap/p2m-ept.c +0 -2
@@ -167,11 +169,14 @@
 void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
 {
     /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )

xen/arch/x86/mm/hap/p2m-ept.c line 180

Quoted 10 lines
xen/arch/x86/mm/hap/p2m-ept.c +6 -1
+    if ( level == 0 || !is_epte_present(ept_entry) || is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
         return;
+    }
 
-    if ( level > 1 )
+    if ( level > 0 )
     {

and similarly:

Quoted 6 lines
xen/arch/x86/mm/p2m.c +1 -1
@@ -184,11 +184,15 @@
 {
     /* End if the entry is a leaf entry. */
     if ( page_order == 0
-         || !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) 

xen/arch/x86/mm/p2m.c line 195

Quoted 10 lines
xen/arch/x86/mm/p2m.c +6 -2
          || (l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
         return;
-
-    if ( page_order > 9 )
+    }
+
+    if ( page_order )

here. Can you explain those in a bit more detail?

Cheers,

Tim.

#11 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to Tim Deegan
Quoted 2 lines · Tim Deegan

On the other hand, maybe the array itself could have a more descriptive name than "stats.entries".

It's statistics on the number of 4k, 2M, and 1G entries. I admit it's not that great, though. Suggestions?
-G

#7 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

In reply to Christoph Egger
Quoted 5 lines · Christoph Egger

What about this:

#define PAGE_ORDER_4K  0
#define PAGE_ORDER_2M  9
#define PAGE_ORDER_1G  18

That would be 0, 1, and 2, respectively. I had thought about something like this, but the common usage seems to be to use L1-3 rather than 4k, 2M, or 1G; and

#define PAGE_ORDER_L1 0
#define PAGE_ORDER_L2 1
#define PAGE_ORDER_L3 2

seemed a bit redundant.

This patch is actually not necessary for the series -- just for the verification that it worked. I could drop this patch so we can discuss it, and send the other three by themselves (since they seem pretty uncontroversial).

-George

Quoted 273 lines
Quoted 256 lines

On the other hand, maybe the array itself could have a more descriptive name than "stats.entries".

Tim.

Quoted 249 lines · George Dunlap
Quoted 248 lines

Count the number of 4kiB, 2MiB, and 1GiB p2m entries.

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c

xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100 +2 -0
@@ -39,6 +39,8 @@
 
   #define is_epte_present(ept_entry)      ((ept_entry)->epte&   0x7)
   #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+#define is_epte_countable(ept_entry)    (is_epte_present(ept_entry) \
+                                         || ((ept_entry)->sa_p2mt ==
 p2m_populate_on_demand))
 
   /* Non-ept "lock-and-check" wrapper */

  static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn,

xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100 +6 -3
@@ -167,11 +169,14 @@
   void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry,
 int level)
   {
       /* End if the entry is a leaf entry. */
-    if ( level == 0 || !is_epte_present(ept_entry) ||
-         is_epte_superpage(ept_entry) )
+    if ( level == 0 || !is_epte_present(ept_entry) ||
 is_epte_superpage(ept_entry) )
+    {
+        if ( is_epte_countable(ept_entry) )
+            p2m->stats.entries[level]--;
           return;
+    }
 
-    if ( level>   1 )
+    if ( level>   0 )
       {

          ept_entry_t *epte = map_domain_page(ept_entry->mfn); for ( int i = 0; i<   EPT_PAGETABLE_ENTRIES; i++ )

xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100 +7 -0
@@ -217,7 +222,10 @@
           ept_p2m_type_to_flags(epte, epte->sa_p2mt, epte->access);
 
           if ( (level - 1) == target )
+        {
+            p2m->stats.entries[target]++;
               continue;
+        }
 
           ASSERT(is_epte_superpage(epte));
 
@@ -400,6 +408,10 @@
               ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
           }
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
           atomic_write_ept_entry(ept_entry, new_entry);
       }

      else

xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100 +4 -0
@@ -412,12 +424,16 @@
 
           split_ept_entry = atomic_read_ept_entry(ept_entry);
 
+        /* Accounting should be OK here; split_ept_entry bump the
 counts,
+         * free_entry will reduce them. */
           if ( !ept_split_super_page(p2m,&split_ept_entry, i, target) )
           {
               ept_free_entry(p2m,&split_ept_entry, i);
               goto out;
           }
 
+        /* We know this was countable or we wouldn't be here.*/
+        p2m->stats.entries[i]--;
           /* now install the newly split ept sub-tree */
           /* NB: please make sure domian is paused and no in-fly VT-d

DMA. */
          atomic_write_ept_entry(ept_entry, split_ept_entry);

xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100 +5 -1
@@ -449,9 +465,13 @@
 
           ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
 
+        /* old_entry will be handled by ept_free_entry below */
+        if ( is_epte_countable(&new_entry) )
+            p2m->stats.entries[i]++;
+
           atomic_write_ept_entry(ept_entry, new_entry);
       }
-
+
       /* Track the highest gfn for which we have ever had a valid

mapping */
      if ( mfn_valid(mfn_x(mfn))&&
           (gfn + (1UL<<   order) - 1>   p2m->max_mapped_pfn) ) diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/p2m.c

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +0 -0
@@ -184,11 +184,15 @@
   {
       /* End if the entry is a leaf entry. */

      if ( page_order == 0

-         || !(l1e_get_flags(*p2m_entry)&   _PAGE_PRESENT)
+         || !(l1e_get_flags(*p2m_entry)&   _PAGE_PRESENT)

           || (l1e_get_flags(*p2m_entry)&   _PAGE_PSE) )
+    {
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--; return;

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +3 -2
-
-    if ( page_order>   9 )
+    }
+
+    if ( page_order )

      {
          l1_pgentry_t *l3_table = map_domain_page(l1e_get_pfn(*p2m_entry));
          for ( int i = 0; i<   L3_PAGETABLE_ENTRIES; i++ )

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +1 -0
@@ -242,6 +246,7 @@
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                    __PAGE_HYPERVISOR | _PAGE_USER);
 
+        /* Stats: Empty entry, no mods needed */
           switch ( type ) {

          case PGT_l3_page_table:
              p2m_add_iommu_flags(&new_entry, 3,
IOMMUF_readable|IOMMUF_writable);

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +2 -0
@@ -285,10 +290,12 @@
           {
               new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES),
 flags);
               p2m_add_iommu_flags(&new_entry, 1,
 IOMMUF_readable|IOMMUF_writable);
+            p2m->stats.entries[1]++;
               p2m->write_p2m_entry(p2m, gfn,
                   l1_entry+i, *table_mfn, new_entry, 2);
           }
           unmap_domain_page(l1_entry);
+        p2m->stats.entries[2]--;
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),

                                   __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
          p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +2 -0
@@ -320,6 +327,7 @@
           {
               new_entry = l1e_from_pfn(pfn + i, flags);
               p2m_add_iommu_flags(&new_entry, 0, 0);
+            p2m->stats.entries[0]++;
               p2m->write_p2m_entry(p2m, gfn,
                   l1_entry+i, *table_mfn, new_entry, 1);
           }
@@ -328,6 +336,7 @@
           new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                    __PAGE_HYPERVISOR|_PAGE_USER);
           p2m_add_iommu_flags(&new_entry, 1,
 IOMMUF_readable|IOMMUF_writable);
+        p2m->stats.entries[1]--;
           p2m->write_p2m_entry(p2m, gfn,
               p2m_entry, *table_mfn, new_entry, 2);

      }

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +0 -0
@@ -908,6 +917,15 @@

  void
  p2m_pod_dump_data(struct p2m_domain *p2m)
  {
+    int i;
+    long entries;
+    printk("    P2M entry stats:\n");
+    for ( i=0; i<3; i++)
+        if ( (entries=p2m->stats.entries[i]) )
+            printk("     L%d: %8ld entries, %ld bytes\n",
+                   i+1,
+                   entries,
+                   entries<<(i*9+12));
      printk("    PoD entries=%d cachesize=%d\n", p2m->pod.entry_count, p2m->pod.count); }

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +6 -0
@@ -1475,6 +1493,12 @@
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn,
 entry_content, 3);
           /* NB: paging_write_p2m_entry() handles tlb flushes properly

*/

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +7 -0
@@ -1519,6 +1543,13 @@
               p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
+
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           /* level 1 entry */
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn,
 entry_content, 1);

          /* NB: paging_write_p2m_entry() handles tlb flushes properly */

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +6 -0
@@ -1556,6 +1587,12 @@
               old_mfn = l1e_get_pfn(*p2m_entry);
           }
 
+        /* Adjust count for present/not-present entries added */
+        if ( l1e_get_flags(*p2m_entry) )
+            p2m->stats.entries[page_order/9]--;
+        if ( l1e_get_flags(entry_content) )
+            p2m->stats.entries[page_order/9]++;
+
           p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn,
 entry_content, 2);
           /* NB: paging_write_p2m_entry() handles tlb flushes properly

*/

xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100 renamed from xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100 +1 -0
@@ -2750,6 +2787,8 @@
                   continue;
               }
 
+            /* STATS: Should change only type; no stats should need

adjustment */
+
              l2mfn = _mfn(l3e_get_pfn(l3e[i3])); l2e = map_domain_page(l3e_get_pfn(l3e[i3])); for ( i2 = 0; i2<   L2_PAGETABLE_ENTRIES; i2++ ) diff -r 4b0692880dfa -r be5d93d38f28 xen/include/asm-x86/p2m.h

xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100 renamed from xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100 +0 -0
@@ -278,6 +278,10 @@

          unsigned         reclaim_single; /* Last gpfn of a scan */ unsigned         max_guest;    /* gpfn of max guest demand-populate */
      } pod;
+
+    struct {
+        long entries[3];
+    } stats;
  };

Quoted 1 line
Quoted 1 line
Quoted 1 line

  /* get host p2m table */

--
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85689 Dornach b. Muenchen
Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen Registergericht Muenchen, HRB Nr. 43632

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#8 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

Quoted 4 lines · George Dunlap

This patch is actually not necessary for the series -- just for the verification that it worked. I could drop this patch so we can discuss it, and send the other three by themselves (since they seem pretty uncontroversial).

I think that's best. I'll be looking at reference-counting p2m entries soon, I hope, and I'll add some bookkeeping when I do. I suspect I can isolate it into a single place then.

Cheers,

Tim.

Signature · 3 lines
Tim Deegan <[email protected]>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd.  (Company #02937203, SL9 0BG)
#9 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

Quoted 9 lines · Tim Deegan
Quoted 4 lines · George Dunlap

This patch is actually not necessary for the series -- just for the verification that it worked.  I could drop this patch so we can discuss it, and send the other three by themselves (since they seem pretty uncontroversial).

I think that's best.  I'll be looking at reference-counting p2m entries soon, I hope, and I'll add some bookkeeping when I do.  I suspect I can isolate it into a single place then.\

Tim, I realize this is over a year ago now, but did you ever end up adding this bookkeeping? I'm trying to port this patch again...

-George

#10 lore raw

Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

Quoted 7 lines · George Dunlap
Quoted 6 lines · Tim Deegan
Quoted 4 lines · George Dunlap

This patch is actually not necessary for the series -- just for the verification that it worked.  I could drop this patch so we can discuss it, and send the other three by themselves (since they seem pretty uncontroversial).

Quoted 6 lines
Quoted 3 lines

I think that's best.  I'll be looking at reference-counting p2m entries soon, I hope, and I'll add some bookkeeping when I do.  I suspect I can isolate it into a single place then.\

Tim, I realize this is over a year ago now, but did you ever end up adding this bookkeeping? I'm trying to port this patch again...

No, I never did. :(

Tim.