mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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@linux.intel.com> Acked-by: Tim Deegan <tim@xen.org>
This commit is contained in:
1 parent
e18d427477
commit
3a7a0ae0cc
4 files changed
+82
-4
No files matched your search
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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,
|
||||
|
||||