[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Allow batched mmu updates which preserve accessed/dirty pte bits.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1200407535 0 # Node ID fba4e7357744e96797916689e3274344b82a8e5f # Parent 58dfcad8d56d3ebad2e8553c43db499ce727cb36 x86: Allow batched mmu updates which preserve accessed/dirty pte bits. Signed-off-by: Bruce Rogers <brogers@xxxxxxxxxx> Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/mm.c | 110 +++++++++++++++++++++++++++++------------------ xen/include/public/xen.h | 11 +++- 2 files changed, 78 insertions(+), 43 deletions(-) diff -r 58dfcad8d56d -r fba4e7357744 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Jan 15 14:27:15 2008 +0000 +++ b/xen/arch/x86/mm.c Tue Jan 15 14:32:15 2008 +0000 @@ -1342,21 +1342,30 @@ static inline int update_intpte(intpte_t intpte_t old, intpte_t new, unsigned long mfn, - struct vcpu *v) + struct vcpu *v, + int preserve_ad) { int rv = 1; #ifndef PTE_UPDATE_WITH_CMPXCHG - rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); -#else + if ( !preserve_ad ) + { + rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); + } + else +#endif { intpte_t t = old; for ( ; ; ) { - rv = paging_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); + intpte_t _new = new; + if ( preserve_ad ) + _new |= old & (_PAGE_ACCESSED | _PAGE_DIRTY); + + rv = paging_cmpxchg_guest_entry(v, p, &t, _new, _mfn(mfn)); if ( unlikely(rv == 0) ) { MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte - ": saw %" PRIpte, old, new, t); + ": saw %" PRIpte, old, _new, t); break; } @@ -1369,20 +1378,19 @@ static inline int update_intpte(intpte_t old = t; } } -#endif return rv; } /* Macro that wraps the appropriate type-changes around update_intpte(). * Arguments are: type, ptr, old, new, mfn, vcpu */ -#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v) \ +#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v,_ad) \ update_intpte(&_t ## e_get_intpte(*(_p)), \ _t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \ - (_m), (_v)) + (_m), (_v), (_ad)) /* Update the L1 entry at pl1e to new value nl1e. */ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, - unsigned long gl1mfn) + unsigned long gl1mfn, int preserve_ad) { l1_pgentry_t ol1e; struct vcpu *curr = current; @@ -1393,7 +1401,7 @@ static int mod_l1_entry(l1_pgentry_t *pl return 0; if ( unlikely(paging_mode_refcounts(d)) ) - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, preserve_ad); if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) { @@ -1415,12 +1423,14 @@ static int mod_l1_entry(l1_pgentry_t *pl /* Fast path for identical mapping, r/w and presence. */ if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) ) - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad); if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad)) ) { put_page_from_l1e(nl1e, d); return 0; @@ -1428,7 +1438,8 @@ static int mod_l1_entry(l1_pgentry_t *pl } else { - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad)) ) return 0; } @@ -1441,7 +1452,8 @@ static int mod_l2_entry(l2_pgentry_t *pl static int mod_l2_entry(l2_pgentry_t *pl2e, l2_pgentry_t nl2e, unsigned long pfn, - unsigned long type) + unsigned long type, + int preserve_ad) { l2_pgentry_t ol2e; struct vcpu *curr = current; @@ -1469,18 +1481,20 @@ static int mod_l2_entry(l2_pgentry_t *pl /* Fast path for identical mapping and presence. */ if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr); + return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, + preserve_ad)) ) { put_page_from_l2e(nl2e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1494,7 +1508,8 @@ static int mod_l2_entry(l2_pgentry_t *pl /* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */ static int mod_l3_entry(l3_pgentry_t *pl3e, l3_pgentry_t nl3e, - unsigned long pfn) + unsigned long pfn, + int preserve_ad) { l3_pgentry_t ol3e; struct vcpu *curr = current; @@ -1532,18 +1547,20 @@ static int mod_l3_entry(l3_pgentry_t *pl /* Fast path for identical mapping and presence. */ if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr); + return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, + preserve_ad)) ) { put_page_from_l3e(nl3e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1564,7 +1581,8 @@ static int mod_l3_entry(l3_pgentry_t *pl /* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */ static int mod_l4_entry(l4_pgentry_t *pl4e, l4_pgentry_t nl4e, - unsigned long pfn) + unsigned long pfn, + int preserve_ad) { struct vcpu *curr = current; struct domain *d = curr->domain; @@ -1592,18 +1610,20 @@ static int mod_l4_entry(l4_pgentry_t *pl /* Fast path for identical mapping and presence. */ if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr); + return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l4e(nl4e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, + preserve_ad)) ) { put_page_from_l4e(nl4e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1946,7 +1966,7 @@ int new_guest_cr3(unsigned long mfn) l4e_from_pfn( mfn, (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)), - pagetable_get_pfn(v->arch.guest_table)); + pagetable_get_pfn(v->arch.guest_table), 0); if ( unlikely(!okay) ) { MEM_LOG("Error while installing new compat baseptr %lx", mfn); @@ -2458,13 +2478,16 @@ int do_mmu_update( { /* * MMU_NORMAL_PT_UPDATE: Normal update to any level of page table. + * MMU_UPDATE_PT_PRESERVE_AD: As above but also preserve (OR) + * current A/D bits. */ case MMU_NORMAL_PT_UPDATE: - + case MMU_PT_UPDATE_PRESERVE_AD: rc = xsm_mmu_normal_update(d, req.val); if ( rc ) break; + req.ptr -= cmd; gmfn = req.ptr >> PAGE_SHIFT; mfn = gmfn_to_mfn(d, gmfn); @@ -2501,20 +2524,23 @@ int do_mmu_update( case PGT_l1_page_table: { l1_pgentry_t l1e = l1e_from_intpte(req.val); - okay = mod_l1_entry(va, l1e, mfn); + okay = mod_l1_entry(va, l1e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; case PGT_l2_page_table: { l2_pgentry_t l2e = l2e_from_intpte(req.val); - okay = mod_l2_entry(va, l2e, mfn, type_info); + okay = mod_l2_entry(va, l2e, mfn, type_info, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #if CONFIG_PAGING_LEVELS >= 3 case PGT_l3_page_table: { l3_pgentry_t l3e = l3e_from_intpte(req.val); - okay = mod_l3_entry(va, l3e, mfn); + okay = mod_l3_entry(va, l3e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #endif @@ -2522,7 +2548,8 @@ int do_mmu_update( case PGT_l4_page_table: { l4_pgentry_t l4e = l4e_from_intpte(req.val); - okay = mod_l4_entry(va, l4e, mfn); + okay = mod_l4_entry(va, l4e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #endif @@ -2652,7 +2679,7 @@ static int create_grant_pte_mapping( } ol1e = *(l1_pgentry_t *)va; - if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v) ) + if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v, 0) ) { put_page_type(page); rc = GNTST_general_error; @@ -2720,9 +2747,11 @@ static int destroy_grant_pte_mapping( } /* Delete pagetable entry. */ - if ( unlikely(!UPDATE_ENTRY(l1, - (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, - d->vcpu[0] /* Change if we go to per-vcpu shadows. */)) ) + if ( unlikely(!UPDATE_ENTRY + (l1, + (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, + d->vcpu[0] /* Change if we go to per-vcpu shadows. */, + 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", va); put_page_type(page); @@ -2758,7 +2787,7 @@ static int create_grant_va_mapping( return GNTST_general_error; } ol1e = *pl1e; - okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v); + okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0); guest_unmap_l1e(v, pl1e); pl1e = NULL; @@ -2796,7 +2825,7 @@ static int replace_grant_va_mapping( } /* Delete pagetable entry. */ - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); rc = GNTST_general_error; @@ -2860,7 +2889,8 @@ int replace_grant_host_mapping( } ol1e = *pl1e; - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), + gl1mfn, curr, 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); guest_unmap_l1e(curr, pl1e); @@ -2948,7 +2978,7 @@ int do_update_va_mapping(unsigned long v pl1e = guest_map_l1e(v, va, &gl1mfn); - if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn)) ) + if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn, 0)) ) rc = -EINVAL; if ( pl1e ) @@ -3517,7 +3547,7 @@ static int ptwr_emulated_update( else { ol1e = *pl1e; - if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) ) + if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v, 0) ) BUG(); } diff -r 58dfcad8d56d -r fba4e7357744 xen/include/public/xen.h --- a/xen/include/public/xen.h Tue Jan 15 14:27:15 2008 +0000 +++ b/xen/include/public/xen.h Tue Jan 15 14:32:15 2008 +0000 @@ -168,9 +168,14 @@ * ptr[:2] -- Machine address within the frame whose mapping to modify. * The frame must belong to the FD, if one is specified. * val -- Value to write into the mapping entry. - */ -#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ -#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ + * + * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD: + * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed + * with those in @val. + */ +#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ +#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ +#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ /* * MMU EXTENDED OPERATIONS _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |