[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [v3 09/10] log-dirty: refine common code to support PML
Using PML, it's possible there are dirty GPAs logged in vcpus' PML buffers when userspace peek/clear dirty pages, therefore we need to flush them befor reporting dirty pages to userspace. This applies to both video ram tracking and paging_log_dirty_op. This patch adds new p2m layer functions to enable/disable PML and flush PML buffers. The new functions are named to be generic to cover potential futher PML-like features for other platforms. Signed-off-by: Kai Huang <kai.huang@xxxxxxxxxxxxxxx> --- xen/arch/x86/mm/hap/hap.c | 29 +++++++++++++++++++++++++---- xen/arch/x86/mm/p2m.c | 36 ++++++++++++++++++++++++++++++++++++ xen/arch/x86/mm/paging.c | 10 ++++++++++ xen/include/asm-x86/p2m.h | 11 +++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index 4ecb2e2..1099670 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -121,7 +121,10 @@ int hap_track_dirty_vram(struct domain *d, p2m_change_type_range(d, ostart, oend, p2m_ram_logdirty, p2m_ram_rw); - /* set l1e entries of range within P2M table to be read-only. */ + /* + * switch vram to log dirty mode, either by setting l1e entries of + * P2M table to be read-only, or via hardware-assisted log-dirty. + */ p2m_change_type_range(d, begin_pfn, begin_pfn + nr, p2m_ram_rw, p2m_ram_logdirty); @@ -135,6 +138,9 @@ int hap_track_dirty_vram(struct domain *d, domain_pause(d); + /* flush dirty GFNs potentially cached by hardware */ + p2m_flush_hardware_cached_dirty(d); + /* get the bitmap */ paging_log_dirty_range(d, begin_pfn, nr, dirty_bitmap); @@ -190,9 +196,15 @@ static int hap_enable_log_dirty(struct domain *d, bool_t log_global) d->arch.paging.mode |= PG_log_dirty; paging_unlock(d); + /* enable hardware-assisted log-dirty if it is supported */ + p2m_enable_hardware_log_dirty(d); + if ( log_global ) { - /* set l1e entries of P2M table to be read-only. */ + /* + * switch to log dirty mode, either by setting l1e entries of P2M table + * to be read-only, or via hardware-assisted log-dirty. + */ p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty); flush_tlb_mask(d->domain_dirty_cpumask); } @@ -205,14 +217,23 @@ static int hap_disable_log_dirty(struct domain *d) d->arch.paging.mode &= ~PG_log_dirty; paging_unlock(d); - /* set l1e entries of P2M table with normal mode */ + /* disable hardware-assisted log-dirty if it is supported */ + p2m_disable_hardware_log_dirty(d); + + /* + * switch to normal mode, either by setting l1e entries of P2M table to + * normal mode, or via hardware-assisted log-dirty. + */ p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw); return 0; } static void hap_clean_dirty_bitmap(struct domain *d) { - /* set l1e entries of P2M table to be read-only. */ + /* + * switch to log-dirty mode, either by setting l1e entries of P2M table to + * be read-only, or via hardware-assisted log-dirty. + */ p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty); flush_tlb_mask(d->domain_dirty_cpumask); } diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index df4a485..67edf89 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -239,6 +239,42 @@ void p2m_memory_type_changed(struct domain *d) } } +void p2m_enable_hardware_log_dirty(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + + if ( p2m->enable_hardware_log_dirty ) + { + p2m_lock(p2m); + p2m->enable_hardware_log_dirty(p2m); + p2m_unlock(p2m); + } +} + +void p2m_disable_hardware_log_dirty(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + + if ( p2m->disable_hardware_log_dirty ) + { + p2m_lock(p2m); + p2m->disable_hardware_log_dirty(p2m); + p2m_unlock(p2m); + } +} + +void p2m_flush_hardware_cached_dirty(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + + if ( p2m->flush_hardware_cached_dirty ) + { + p2m_lock(p2m); + p2m->flush_hardware_cached_dirty(p2m); + p2m_unlock(p2m); + } +} + mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t, p2m_access_t *a, p2m_query_t q, unsigned int *page_order, bool_t locked) diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 77c929b..59d4720 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -422,7 +422,17 @@ static int paging_log_dirty_op(struct domain *d, int i4, i3, i2; if ( !resuming ) + { domain_pause(d); + + /* + * Flush dirty GFNs potentially cached by hardware. Only need to flush + * when not resuming, as domain was paused in resuming case therefore + * it's not possible to have any new dirty pages. + */ + p2m_flush_hardware_cached_dirty(d); + } + paging_lock(d); if ( !d->arch.paging.preempt.dom ) diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 91fc099..5b5785e 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -233,6 +233,9 @@ struct p2m_domain { p2m_access_t *p2ma, p2m_query_t q, unsigned int *page_order); + void (*enable_hardware_log_dirty)(struct p2m_domain *p2m); + void (*disable_hardware_log_dirty)(struct p2m_domain *p2m); + void (*flush_hardware_cached_dirty)(struct p2m_domain *p2m); void (*change_entry_type_global)(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t nt); @@ -507,6 +510,14 @@ void guest_physmap_remove_page(struct domain *d, /* Set a p2m range as populate-on-demand */ int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, unsigned int order); +/* Enable hardware-assisted log-dirty. */ +void p2m_enable_hardware_log_dirty(struct domain *d); + +/* Disable hardware-assisted log-dirty */ +void p2m_disable_hardware_log_dirty(struct domain *d); + +/* Flush hardware cached dirty GFNs */ +void p2m_flush_hardware_cached_dirty(struct domain *d); /* Change types across all p2m entries in a domain */ void p2m_change_entry_type_global(struct domain *d, -- 2.1.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |