Segment dirty log for performance
PATCH 1/1 Segment dirty log for performance
Represent dirty log as an array of bitmaps.
Also, when bookkeeping the valid HVM pfn ranges, breaks the PFNs into two ranges -- RAM and VGA. This allows the dirty page bitmaps to conform to these ranges and to skip the (sometimes large) empty PFN range between them.
xen/arch/x86/mm/p2m.c +6 -3
@@ -241,9 +241,12 @@ set_p2m_entry(struct domain *d, unsigned 0, L1_PAGETABLE_ENTRIES);ASSERT (p2m_entry); -/* Track the highest gfn for which we have ever had a valid mapping */ -if (mfn_valid (mfn) && (gfn > d->arch.p2m.max_mapped_pfn) ) - d->arch.p2m.max_mapped_pfn = gfn; +if (mfn_valid (mfn) ) { +paging_pfn_range_append (d, gfn); +/* Track the highest gfn for which we have ever had a valid mapping */ +if (gfn > d->arch.p2m.max_mapped_pfn ) + d->arch.p2m.max_mapped_pfn = gfn; + }if (mfn_valid (mfn) || (p2mt == p2m_mmio_direct) ) entry_content =l1e_from_pfn (mfn_x (mfn),p2m_type_to_flags (p2mt));
xen/arch/x86/mm/paging.c +177 -69
299 lines not on this page · raw message
xen/arch/x86/mm/shadow/private.h +12 -7
@@ -491,17 +491,22 @@ sh_mfn_is_dirty(struct domain *d, mfn_t/* Is this guest page dirty? Call only in log-dirty mode. */ {unsigned long pfn; +struct pfn_range *pr, *pr0 = d->arch.paging.log_dirty.pfn_range; +ASSERT (shadow_mode_log_dirty (d)); -ASSERT (d->arch.paging.log_dirty.bitmap !=NULL );/* We /really/ mean PFN here, even for non-translated guests. */ pfn =get_gpfn_from_mfn (mfn_x (gmfn)); -if (likely (VALID_M2P (pfn)) - &&likely (pfn < d->arch.paging.log_dirty.bitmap_size) - &&test_bit (pfn, d->arch.paging.log_dirty.bitmap) ) -return 1 ; - -return 0 ; +if (unlikely (!VALID_M2P (pfn)) ) +return 0 ; + +for (pr = pr0;likely (pr - pr0 !=PFN_RANGE_NR && pr->len >0 ); pr++) + { +ASSERT (pr->dirty_bitmap !=NULL ); +if (likely (pr->start <= pfn && pfn < pr->start + pr->len) ) +return test_bit (pfn - pr->start, pr->dirty_bitmap); + } +return 0 ;/* shouldn't get here */ }
xen/include/asm-x86/domain.h +9 -4
@@ -158,13 +158,18 @@ struct log_dirty_domain {int locker;/* processor that holds the lock */ const char *locker_function;/* func that took it */ -/* log-dirty bitmap to record dirty pages */ -unsigned long *bitmap; -unsigned int bitmap_size;/* in pages, bit per page */ -/* log-dirty mode stats */ unsigned int fault_count;unsigned int dirty_count; + +/* segmented log-dirty bitmap to record dirty pages */ +#define PFN_RANGE_NR 4 +struct pfn_range { +unsigned long start; +unsigned long len; +uint8_t *dirty_bitmap; +unsigned int dirty_bitmap_size;/* in pages, bit per page */ + } pfn_range[PFN_RANGE_NR ];/* functions which are paging mode specific */ int (*enable_log_dirty )(struct domain *d);
xen/include/asm-x86/paging.h +2 -0
@@ -258,6 +258,8 @@ static inline int paging_cmpxchg_guest_ereturn (!cmpxchg_user (p, *old, new)); } +void paging_pfn_range_append (struct domain *d,unsigned long gfn); +/* Helper function that writes a pte in such a way that a concurrent read * never sees a half-written entry that has _PAGE_PRESENT set */ static inline void safe_write_pte (l1_pgentry_t *p,l1_pgentry_t new)
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Quoted 8 lines · Ben Guthro
Represent dirty log as an array of bitmaps.
Also, when bookkeeping the valid HVM pfn ranges, breaks the PFNs into two ranges -- RAM and VGA. This allows the dirty page bitmaps to conform to these ranges and to skip the (sometimes large) empty PFN range between them.Signed-off-by Ben Guthro <[email protected]>Signed-off-by Dave Lively <[email protected]>
In terms of tracking active ranges of pseudophysical space, we already have a data structure that can give that info (the p2m radix tree). And the better way of subdividing the dirty bitmap would be to make that a radix tree too, where the leaves are PAGE_SIZE'd bitmaps each handling 128MB of pseudophys address space. This would mean we only need order-0 allocations in the dirty bitmap logic, greatly reducing the chance of domain-migration failure with ENOMEM.
Apart from the obvious benefit of allocating a smaller dirty bitmap, which is hence more likely to succeed, how much does this improve migration performance for a small-ish memory guest? Is it significant?
-- Keir
Quoted 21 lines · Keir Fraser
Quoted 9 lines · Ben Guthro
Represent dirty log as an array of bitmaps.
Also, when bookkeeping the valid HVM pfn ranges, breaks the PFNs into two ranges -- RAM and VGA. This allows the dirty page bitmaps to conform to these ranges and to skip the (sometimes large) empty PFN range between them.Signed-off-by Ben Guthro <[email protected]>Signed-off-by Dave Lively <[email protected]>In terms of tracking active ranges of pseudophysical space, we already have a data structure that can give that info (the p2m radix tree). And the better way of subdividing the dirty bitmap would be to make that a radix tree too, where the leaves are PAGE_SIZE'd bitmaps each handling 128MB of pseudophys address space. This would mean we only need order-0 allocations in the dirty bitmap logic, greatly reducing the chance of domain-migration failure with ENOMEM.
Quoted 6 lines
Apart from the obvious benefit of allocating a smaller dirty bitmap, which is hence more likely to succeed, how much does this improve migration performance for a small-ish memory guest? Is it significant?
-- Keir
No, the performance benefit is not noticeable. We (Robert Phillips, actually) did it to make migrate more reliable. But relying only on order-0 allocations is obviously even better. I'll take a look at using the radix tree as you suggest.
Thanks,
Dave
Quoted 4 lines · David Lively
No, the performance benefit is not noticeable. We (Robert Phillips, actually) did it to make migrate more reliable. But relying only on order-0 allocations is obviously even better. I'll take a look at using the radix tree as you suggest.
Okay, I see. A patch to use only order-0 allocations would be excellent!
-- Keir