From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: George Dunlap <george.dunlap@eu.citrix.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
Tim Deegan <tim@xen.org>, Jan Beulich <JBeulich@suse.com>
Subject: [PATCH v2 8/9] x86/pagewalk: Improve the logic behind setting access and dirty bits
Date: Thu, 16 Mar 2017 16:31:42 +0000 [thread overview]
Message-ID: <1489681903-28119-9-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1489681903-28119-1-git-send-email-andrew.cooper3@citrix.com>
The boolean pse2M is misnamed, because it might refer to a 4M superpage.
Switch the logic to be in terms of the level of the leaf entry, and rearrange
the calls to set_ad_bits() to be a fallthrough switch statement, to make it
easier to follow.
Alter set_ad_bits() to use properly use bool rather than integers. Introduce
properly typed pointers rather than repeatedly casting away from void. Use
ACCESS_ONCE() to ensure that *walk_p is only read once.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Tim Deegan <tim@xen.org>
CC: George Dunlap <george.dunlap@eu.citrix.com>
v2:
* New
---
xen/arch/x86/mm/guest_walk.c | 81 +++++++++++++++++++++++++-------------------
1 file changed, 47 insertions(+), 34 deletions(-)
diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c
index bdb52d9..4ba7602 100644
--- a/xen/arch/x86/mm/guest_walk.c
+++ b/xen/arch/x86/mm/guest_walk.c
@@ -32,24 +32,28 @@ asm(".file \"" __OBJECT_FILE__ "\"");
#include <asm/page.h>
#include <asm/guest_pt.h>
-/* Modify a guest pagetable entry to set the Accessed and Dirty bits.
- * Returns non-zero if it actually writes to guest memory. */
-static uint32_t set_ad_bits(void *guest_p, void *walk_p, int set_dirty)
+/*
+ * Modify a guest pagetable entry to set the Accessed and Dirty bits.
+ * Returns non-zero if it actually writes to guest memory.
+ */
+static bool set_ad_bits(void *_guest_p, void *_walk_p, bool set_dirty)
{
- guest_intpte_t old, new;
+ guest_intpte_t *guest_p = _guest_p, *walk_p = _walk_p;
+ guest_intpte_t new, old = ACCESS_ONCE(*walk_p);
- old = *(guest_intpte_t *)walk_p;
new = old | _PAGE_ACCESSED | (set_dirty ? _PAGE_DIRTY : 0);
- if ( old != new )
+ if ( old != new )
{
- /* Write the new entry into the walk, and try to write it back
+ /*
+ * Write the new entry into the walk, and try to write it back
* into the guest table as well. If the guest table has changed
- * under out feet then leave it alone. */
- *(guest_intpte_t *)walk_p = new;
- if ( cmpxchg(((guest_intpte_t *)guest_p), old, new) == old )
- return 1;
+ * under out feet then leave it alone.
+ */
+ *walk_p = new;
+ if ( cmpxchg(guest_p, old, new) == old )
+ return true;
}
- return 0;
+ return false;
}
/*
@@ -89,7 +93,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
guest_l4e_t *l4p;
#endif
uint32_t gflags, rc;
- bool_t pse1G = 0, pse2M = 0;
+ unsigned int leaf_level;
p2m_query_t qt = P2M_ALLOC | P2M_UNSHARE;
#define AR_ACCUM_AND (_PAGE_USER | _PAGE_RW)
@@ -179,9 +183,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
ar_and &= gflags;
ar_or |= gflags;
- pse1G = !!(gflags & _PAGE_PSE);
-
- if ( pse1G )
+ if ( gflags & _PAGE_PSE )
{
/* Generate a fake l1 table entry so callers don't all
* have to understand superpages. */
@@ -204,6 +206,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
((va >> PAGE_SHIFT) & GUEST_L3_GFN_MASK));
gw->l1e = guest_l1e_from_gfn(start, flags);
gw->l2mfn = gw->l1mfn = INVALID_MFN;
+ leaf_level = 3;
goto leaf;
}
@@ -273,9 +276,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
ar_and &= gflags;
ar_or |= gflags;
- pse2M = !!(gflags & _PAGE_PSE);
-
- if ( pse2M )
+ if ( gflags & _PAGE_PSE )
{
/* Special case: this guest VA is in a PSE superpage, so there's
* no guest l1e. We make one up so that the propagation code
@@ -309,6 +310,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
gw->l1e = guest_l1e_from_gfn(start, flags);
#endif
gw->l1mfn = INVALID_MFN;
+ leaf_level = 2;
goto leaf;
}
@@ -340,6 +342,8 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
ar_and &= gflags;
ar_or |= gflags;
+ leaf_level = 1;
+
leaf:
gw->pfec |= PFEC_page_present;
@@ -413,24 +417,33 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
* success. Although the PRMs say higher-level _PAGE_ACCESSED bits
* get set whenever a lower-level PT is used, at least some hardware
* walkers behave this way. */
-#if GUEST_PAGING_LEVELS == 4 /* 64-bit only... */
- if ( set_ad_bits(l4p + guest_l4_table_offset(va), &gw->l4e, 0) )
- paging_mark_dirty(d, gw->l4mfn);
- if ( set_ad_bits(l3p + guest_l3_table_offset(va), &gw->l3e,
- (pse1G && (walk & PFEC_write_access))) )
- paging_mark_dirty(d, gw->l3mfn);
-#endif
- if ( !pse1G )
+ switch ( leaf_level )
{
+ default:
+ ASSERT_UNREACHABLE();
+ break;
+
+ case 1:
+ if ( set_ad_bits(l1p + guest_l1_table_offset(va), &gw->l1e,
+ (walk & PFEC_write_access) && leaf_level == 1) )
+ paging_mark_dirty(d, gw->l1mfn);
+ /* Fallthrough */
+
+ case 2:
if ( set_ad_bits(l2p + guest_l2_table_offset(va), &gw->l2e,
- (pse2M && (walk & PFEC_write_access))) )
+ (walk & PFEC_write_access) && leaf_level == 2) )
paging_mark_dirty(d, gw->l2mfn);
- if ( !pse2M )
- {
- if ( set_ad_bits(l1p + guest_l1_table_offset(va), &gw->l1e,
- (walk & PFEC_write_access)) )
- paging_mark_dirty(d, gw->l1mfn);
- }
+ /* Fallthrough */
+
+#if GUEST_PAGING_LEVELS == 4 /* 64-bit only... */
+ case 3:
+ if ( set_ad_bits(l3p + guest_l3_table_offset(va), &gw->l3e,
+ (walk & PFEC_write_access) && leaf_level == 3) )
+ paging_mark_dirty(d, gw->l3mfn);
+
+ if ( set_ad_bits(l4p + guest_l4_table_offset(va), &gw->l4e, 0) )
+ paging_mark_dirty(d, gw->l4mfn);
+#endif
}
out:
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2017-03-16 16:31 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-16 16:31 [PATCH v2 0/9] Fixes to pagetable handling Andrew Cooper
2017-03-16 16:31 ` [PATCH v2 1/9] x86/cpuid: Sort cpu_has_* predicates by feature number Andrew Cooper
2017-03-17 16:08 ` Jan Beulich
2017-03-16 16:31 ` [PATCH v2 2/9] x86/pagewalk: Use pointer syntax for pfec parameter Andrew Cooper
2017-03-17 16:09 ` Jan Beulich
2017-03-20 11:29 ` George Dunlap
2017-03-23 16:28 ` Tim Deegan
2017-03-16 16:31 ` [PATCH v2 3/9] x86/shadow: Drop VALID_GFN() Andrew Cooper
2017-03-23 16:30 ` Tim Deegan
2017-03-16 16:31 ` [PATCH v2 4/9] x86/pagewalk: Clean up guest_supports_* predicates Andrew Cooper
2017-03-20 8:45 ` Jan Beulich
2017-03-20 13:36 ` Andrew Cooper
2017-03-20 13:59 ` Jan Beulich
2017-03-23 17:32 ` Andrew Cooper
2017-03-24 7:19 ` Jan Beulich
2017-03-23 16:34 ` Tim Deegan
2017-03-16 16:31 ` [PATCH v2 5/9] x86/pagewalk: Helpers for reserved bit handling Andrew Cooper
2017-03-20 8:48 ` Jan Beulich
2017-03-23 16:55 ` Tim Deegan
2017-03-23 17:02 ` Andrew Cooper
2017-03-23 17:12 ` Tim Deegan
2017-03-23 17:35 ` Andrew Cooper
2017-03-24 5:45 ` Juergen Gross
2017-03-24 7:51 ` Jan Beulich
[not found] ` <58D4DDFF0200007800147138@suse.com>
2017-03-24 7:58 ` Juergen Gross
2017-03-24 8:25 ` Jan Beulich
2017-03-24 9:06 ` Andrew Cooper
2017-03-24 7:47 ` Jan Beulich
2017-03-24 8:36 ` Andrew Cooper
2017-03-16 16:31 ` [PATCH v2 6/9] x86/pagewalk: Re-implement the pagetable walker Andrew Cooper
2017-03-16 16:31 ` [PATCH v2 7/9] x86/shadow: Use the pagewalk reserved bits helpers Andrew Cooper
2017-03-16 17:25 ` Andrew Cooper
2017-03-20 8:53 ` Jan Beulich
2017-03-23 16:57 ` Tim Deegan
2017-03-16 16:31 ` Andrew Cooper [this message]
2017-03-20 9:03 ` [PATCH v2 8/9] x86/pagewalk: Improve the logic behind setting access and dirty bits Jan Beulich
2017-03-23 17:09 ` Tim Deegan
2017-03-23 17:40 ` Andrew Cooper
2017-03-16 16:31 ` [PATCH v2 9/9] x86/pagewalk: non-functional cleanup Andrew Cooper
2017-03-20 9:04 ` Jan Beulich
2017-03-23 17:10 ` Tim Deegan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1489681903-28119-9-git-send-email-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=george.dunlap@eu.citrix.com \
--cc=tim@xen.org \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).