|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 3/6] x86: extend mod_l*_entry() to optionally return the old PTE value
Calling mod_l*_entry() with a valid ol*e_out pointer will do atomic
CMPXCHG to set the new pte value and return the old pte value through
the ol*e_out pointer. If the ol*e_out pointer is NULL then old behavior
is preserved.
Signed-off-by: Kevin Lampis <kevin.lampis@xxxxxxxxxx>
---
Changes in v5:
- Refactoring the mod_l*_entry() functions was split out
into a patch before this one
Changes in v4:
- Refactor how UPDATE_ENTRY is used
- Update commit message to specify CMPXCHG instead of xchg
Changes in v3:
- Add swap to mod_l{2,3,4}_entry()
Changes in v2:
- UPDATE_ENTRY now returns the old pte value instead of using an out
pointer
---
xen/arch/x86/mm.c | 77 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 18 deletions(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index dc0e0d451c02..316a435b9b71 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2193,7 +2193,8 @@ static void l3t_unlock(struct page_info *page)
/* Update the L1 entry at pl1e to new value nl1e. */
static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
mfn_t gl1mfn, unsigned int update_flags,
- struct vcpu *pt_vcpu, struct domain *pg_dom)
+ struct vcpu *pt_vcpu, struct domain *pg_dom,
+ l1_pgentry_t *ol1e_out)
{
l1_pgentry_t ol1e = l1e_read(pl1e);
struct domain *pt_dom = pt_vcpu->domain;
@@ -2254,7 +2255,11 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t
nl1e,
/* Fast path for sufficiently-similar mappings. */
if ( !l1e_has_changed(ol1e, nl1e, ~FASTPATH_FLAG_WHITELIST) )
{
- UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu, update_flags);
+ intpte_t old = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
+ update_flags);
+ if ( ol1e_out )
+ *ol1e_out = l1e_from_intpte(old);
+
if ( page )
put_page(page);
return 0;
@@ -2280,7 +2285,12 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t
nl1e,
else if ( pv_l1tf_check_l1e(pt_dom, nl1e) )
return -ERESTART;
- UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu, update_flags);
+ {
+ intpte_t old = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
+ update_flags);
+ if ( ol1e_out )
+ *ol1e_out = l1e_from_intpte(old);
+ }
put_page_from_l1e(ol1e, pt_dom);
return 0;
@@ -2292,7 +2302,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
l2_pgentry_t nl2e,
mfn_t mfn,
unsigned int update_flags,
- struct vcpu *vcpu)
+ struct vcpu *vcpu,
+ l2_pgentry_t *ol2e_out)
{
l2_pgentry_t ol2e;
struct domain *d = vcpu->domain;
@@ -2324,7 +2335,11 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
/* Fast path for sufficiently-similar mappings. */
if ( !l2e_has_changed(ol2e, nl2e, ~FASTPATH_PDE_FLAG_WHITELIST) )
{
- UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, mfn, vcpu, update_flags);
+ intpte_t old = UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, mfn, vcpu,
+ update_flags);
+ if ( ol2e_out )
+ *ol2e_out = l2e_from_intpte(old);
+
return 0;
}
@@ -2334,7 +2349,12 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
else if ( pv_l1tf_check_l2e(d, nl2e) )
return -ERESTART;
- UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, mfn, vcpu, update_flags);
+ {
+ intpte_t old = UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, mfn, vcpu,
+ update_flags);
+ if ( ol2e_out )
+ *ol2e_out = l2e_from_intpte(old);
+ }
put_page_from_l2e(ol2e, mfn, PTF_defer);
@@ -2346,7 +2366,8 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
l3_pgentry_t nl3e,
mfn_t mfn,
unsigned int update_flags,
- struct vcpu *vcpu)
+ struct vcpu *vcpu,
+ l3_pgentry_t *ol3e_out)
{
l3_pgentry_t ol3e;
struct domain *d = vcpu->domain;
@@ -2376,7 +2397,11 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
/* Fast path for sufficiently-similar mappings. */
if ( !l3e_has_changed(ol3e, nl3e, ~FASTPATH_PDE_FLAG_WHITELIST) )
{
- UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, mfn, vcpu, update_flags);
+ intpte_t old = UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, mfn, vcpu,
+ update_flags);
+ if ( ol3e_out )
+ *ol3e_out = l3e_from_intpte(old);
+
return 0;
}
@@ -2387,7 +2412,12 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
else if ( pv_l1tf_check_l3e(d, nl3e) )
return -ERESTART;
- UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, mfn, vcpu, update_flags);
+ {
+ intpte_t old = UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, mfn, vcpu,
+ update_flags);
+ if ( ol3e_out )
+ *ol3e_out = l3e_from_intpte(old);
+ }
put_page_from_l3e(ol3e, mfn, PTF_defer);
return 0;
@@ -2398,7 +2428,8 @@ static int mod_l4_entry(l4_pgentry_t *pl4e,
l4_pgentry_t nl4e,
mfn_t mfn,
unsigned int update_flags,
- struct vcpu *vcpu)
+ struct vcpu *vcpu,
+ l4_pgentry_t *ol4e_out)
{
struct domain *d = vcpu->domain;
l4_pgentry_t ol4e;
@@ -2428,7 +2459,11 @@ static int mod_l4_entry(l4_pgentry_t *pl4e,
/* Fast path for sufficiently-similar mappings. */
if ( !l4e_has_changed(ol4e, nl4e, ~FASTPATH_PDE_FLAG_WHITELIST) )
{
- UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, mfn, vcpu, update_flags);
+ intpte_t old = UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, mfn, vcpu,
+ update_flags);
+ if ( ol4e_out )
+ *ol4e_out = l4e_from_intpte(old);
+
return 0;
}
@@ -2439,7 +2474,12 @@ static int mod_l4_entry(l4_pgentry_t *pl4e,
else if ( pv_l1tf_check_l4e(d, nl4e) )
return -ERESTART;
- UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, mfn, vcpu, update_flags);
+ {
+ intpte_t old = UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, mfn, vcpu,
+ update_flags);
+ if ( ol4e_out )
+ *ol4e_out = l4e_from_intpte(old);
+ }
put_page_from_l4e(ol4e, mfn, PTF_defer);
return 0;
@@ -3311,7 +3351,7 @@ int new_guest_cr3(mfn_t mfn)
l4e_from_mfn(mfn,
(_PAGE_PRESENT | _PAGE_RW |
_PAGE_USER | _PAGE_ACCESSED)),
- gt_mfn, 0, curr);
+ gt_mfn, 0, curr, NULL);
unmap_domain_page(pl4e);
switch ( rc )
{
@@ -4149,14 +4189,14 @@ long do_mmu_update(
{
case PGT_l1_page_table:
rc = mod_l1_entry(va, l1e_from_intpte(req.val), mfn,
- update_flags, v, pg_owner);
+ update_flags, v, pg_owner, NULL);
break;
case PGT_l2_page_table:
if ( unlikely(pg_owner != pt_owner) )
break;
rc = mod_l2_entry(va, l2e_from_intpte(req.val), mfn,
- update_flags, v);
+ update_flags, v, NULL);
if ( !rc )
flush_linear_pt = true;
break;
@@ -4165,7 +4205,7 @@ long do_mmu_update(
if ( unlikely(pg_owner != pt_owner) )
break;
rc = mod_l3_entry(va, l3e_from_intpte(req.val), mfn,
- update_flags, v);
+ update_flags, v, NULL);
if ( !rc )
flush_linear_pt = true;
break;
@@ -4174,7 +4214,7 @@ long do_mmu_update(
if ( unlikely(pg_owner != pt_owner) )
break;
rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
- update_flags, v);
+ update_flags, v, NULL);
if ( !rc )
flush_linear_pt = true;
if ( !rc && pt_owner->arch.pv.xpti )
@@ -4514,7 +4554,8 @@ static int __do_update_va_mapping(
goto out;
}
- rc = mod_l1_entry(pl1e, val, gl1mfn, MMU_NORMAL_PT_UPDATE, v, pg_owner);
+ rc = mod_l1_entry(pl1e, val, gl1mfn, MMU_NORMAL_PT_UPDATE, v, pg_owner,
+ NULL);
page_unlock(gl1pg);
put_page(gl1pg);
--
2.52.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |