Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Xen: Devel

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

 

 

Xen devel RSS feed   Index | Next | Previous | View Threaded


george.dunlap at eu

May 6, 2011, 7:01 AM

Post #1 of 11 (146 views)
Permalink
[PATCH 1 of 4] p2m: Keep statistics on order of p2m entries

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

Signed-off-by: George Dunlap <george.dunlap [at] eu>

diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100
@@ -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
--- a/xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100
+++ b/xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100
@@ -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
--- a/xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100
+++ b/xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100
@@ -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
Xen-devel [at] lists
http://lists.xensource.com/xen-devel


Tim.Deegan at citrix

May 6, 2011, 7:23 AM

Post #2 of 11 (143 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

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:

> @@ -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 )
> {

and similarly:

> @@ -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 )

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

Cheers,

Tim.

--
Tim Deegan <Tim.Deegan [at] citrix>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd. (Company #02937203, SL9 0BG)

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


Christoph.Egger at amd

May 6, 2011, 7:40 AM

Post #3 of 11 (141 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

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


On 05/06/11 16:01, George Dunlap wrote:
> Count the number of 4kiB, 2MiB, and 1GiB p2m entries.
>
> Signed-off-by: George Dunlap<george.dunlap [at] eu>
>
> diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
> --- a/xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100
> +++ b/xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100
> @@ -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
> --- a/xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100
> +++ b/xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100
> @@ -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
> --- a/xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100
> +++ b/xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100
> @@ -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
> Xen-devel [at] lists
> 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
Xen-devel [at] lists
http://lists.xensource.com/xen-devel


Christoph.Egger at amd

May 6, 2011, 7:53 AM

Post #4 of 11 (143 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

On 05/06/11 17:00, Tim Deegan wrote:
> Hello,
>
> At 15:40 +0100 on 06 May (1304696401), Christoph Egger wrote:
>> 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

>
> On the other hand, maybe the array itself could have a more descriptive
> name than "stats.entries".
>
> Tim.
>
>> On 05/06/11 16:01, George Dunlap wrote:
>>> Count the number of 4kiB, 2MiB, and 1GiB p2m entries.
>>>
>>> Signed-off-by: George Dunlap<george.dunlap [at] eu>
>>>
>>> diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
>>> --- a/xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100
>>> +++ b/xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100
>>> @@ -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
>>> --- a/xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100
>>> +++ b/xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100
>>> @@ -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
>>> --- a/xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100
>>> +++ b/xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100
>>> @@ -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 */


--
---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
Xen-devel [at] lists
http://lists.xensource.com/xen-devel


Tim.Deegan at citrix

May 6, 2011, 8:00 AM

Post #5 of 11 (142 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

Hello,

At 15:40 +0100 on 06 May (1304696401), Christoph Egger wrote:
> 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.

> On 05/06/11 16:01, George Dunlap wrote:
> > Count the number of 4kiB, 2MiB, and 1GiB p2m entries.
> >
> > Signed-off-by: George Dunlap<george.dunlap [at] eu>
> >
> > diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
> > --- a/xen/arch/x86/mm/hap/p2m-ept.c Thu May 05 17:40:34 2011 +0100
> > +++ b/xen/arch/x86/mm/hap/p2m-ept.c Fri May 06 15:01:08 2011 +0100
> > @@ -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
> > --- a/xen/arch/x86/mm/p2m.c Thu May 05 17:40:34 2011 +0100
> > +++ b/xen/arch/x86/mm/p2m.c Fri May 06 15:01:08 2011 +0100
> > @@ -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
> > --- a/xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100
> > +++ b/xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100
> > @@ -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
> > Xen-devel [at] lists
> > 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
> Xen-devel [at] lists
> http://lists.xensource.com/xen-devel

--
Tim Deegan <Tim.Deegan [at] citrix>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd. (Company #02937203, SL9 0BG)

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


george.dunlap at citrix

May 6, 2011, 8:07 AM

Post #6 of 11 (146 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

On Fri, 2011-05-06 at 15:23 +0100, Tim Deegan wrote:
> Hi,
>
> Can you please add this:
>
> [diff]
> showfunc = True

Ah, very helpful.

> 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

>
> > @@ -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 )
> > {
>
> and similarly:
>
> > @@ -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 )
>
> here. Can you explain those in a bit more detail?
>
> Cheers,
>
> Tim.
>



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


dunlapg at umich

May 6, 2011, 8:14 AM

Post #7 of 11 (144 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

On Fri, May 6, 2011 at 4:00 PM, Tim Deegan <Tim.Deegan [at] citrix> wrote:
> 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

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


dunlapg at umich

May 6, 2011, 8:34 AM

Post #8 of 11 (143 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

On Fri, May 6, 2011 at 3:53 PM, Christoph Egger <Christoph.Egger [at] amd> wrote:
> 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

>
>>
>> On the other hand, maybe the array itself could have a more descriptive
>> name than "stats.entries".
>>
>> Tim.
>>
>>> On 05/06/11 16:01, George Dunlap wrote:
>>>>
>>>> Count the number of 4kiB, 2MiB, and 1GiB p2m entries.
>>>>
>>>> Signed-off-by: George Dunlap<george.dunlap [at] eu>
>>>>
>>>> diff -r 4b0692880dfa -r be5d93d38f28 xen/arch/x86/mm/hap/p2m-ept.c
>>>> --- a/xen/arch/x86/mm/hap/p2m-ept.c     Thu May 05 17:40:34 2011 +0100
>>>> +++ b/xen/arch/x86/mm/hap/p2m-ept.c     Fri May 06 15:01:08 2011 +0100
>>>> @@ -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
>>>> --- a/xen/arch/x86/mm/p2m.c     Thu May 05 17:40:34 2011 +0100
>>>> +++ b/xen/arch/x86/mm/p2m.c     Fri May 06 15:01:08 2011 +0100
>>>> @@ -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
>>>> --- a/xen/include/asm-x86/p2m.h Thu May 05 17:40:34 2011 +0100
>>>> +++ b/xen/include/asm-x86/p2m.h Fri May 06 15:01:08 2011 +0100
>>>> @@ -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 */
>
>
> --
> ---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
> Xen-devel [at] lists
> http://lists.xensource.com/xen-devel
>

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


Tim.Deegan at citrix

May 9, 2011, 1:27 AM

Post #9 of 11 (140 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

At 16:34 +0100 on 06 May (1304699686), George Dunlap wrote:
> 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.

--
Tim Deegan <Tim.Deegan [at] citrix>
Principal Software Engineer, Xen Platform Team
Citrix Systems UK Ltd. (Company #02937203, SL9 0BG)

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


dunlapg at umich

Jun 8, 2012, 3:52 AM

Post #10 of 11 (95 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

On Mon, May 9, 2011 at 9:27 AM, Tim Deegan <Tim.Deegan [at] citrix> wrote:
> At 16:34 +0100 on 06 May (1304699686), George Dunlap wrote:
>> 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

_______________________________________________
Xen-devel mailing list
Xen-devel [at] lists
http://lists.xen.org/xen-devel


tim at xen

Jun 14, 2012, 1:52 AM

Post #11 of 11 (90 views)
Permalink
Re: [PATCH 1 of 4] p2m: Keep statistics on order of p2m entries [In reply to]

At 11:52 +0100 on 08 Jun (1339156322), George Dunlap wrote:
> On Mon, May 9, 2011 at 9:27 AM, Tim Deegan <Tim.Deegan [at] citrix> wrote:
> > At 16:34 +0100 on 06 May (1304699686), George Dunlap wrote:
> >> 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...

No, I never did. :(

Tim.

_______________________________________________
Xen-devel mailing list
Xen-devel [at] lists
http://lists.xen.org/xen-devel

Xen devel RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.