Differential D3854 Diff 9274 emulators/xen-kernel/files/0003-x86-shadow-fix-shadow_track_dirty_vram-to-work-on-hv.patch
Changeset View
Changeset View
Standalone View
Standalone View
emulators/xen-kernel/files/0003-x86-shadow-fix-shadow_track_dirty_vram-to-work-on-hv.patch
- This file was added.
From 055ee44e3cc7c40dc3a3319370d287591771a7f3 Mon Sep 17 00:00:00 2001 | |||||
From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com> | |||||
Date: Fri, 9 Oct 2015 12:57:32 +0200 | |||||
Subject: [PATCH 3/8] x86/shadow: fix shadow_track_dirty_vram to work on hvm | |||||
guests | |||||
MIME-Version: 1.0 | |||||
Content-Type: text/plain; charset=UTF-8 | |||||
Content-Transfer-Encoding: 8bit | |||||
Modify shadow_track_dirty_vram to use a local buffer and then flush to the | |||||
guest without the paging_lock held. This is modeled after | |||||
hap_track_dirty_vram. | |||||
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> | |||||
Reviewed-by: Tim Deegan <tim@xen.org> | |||||
--- | |||||
xen/arch/x86/mm/shadow/common.c | 49 +++++++++++++++++++++++++---------------- | |||||
1 file changed, 30 insertions(+), 19 deletions(-) | |||||
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c | |||||
index a5eed28..6b91b8c 100644 | |||||
--- a/xen/arch/x86/mm/shadow/common.c | |||||
+++ b/xen/arch/x86/mm/shadow/common.c | |||||
@@ -3478,7 +3478,7 @@ void shadow_clean_dirty_bitmap(struct domain *d) | |||||
int shadow_track_dirty_vram(struct domain *d, | |||||
unsigned long begin_pfn, | |||||
unsigned long nr, | |||||
- XEN_GUEST_HANDLE_64(uint8) dirty_bitmap) | |||||
+ XEN_GUEST_HANDLE_64(uint8) guest_dirty_bitmap) | |||||
{ | |||||
int rc; | |||||
unsigned long end_pfn = begin_pfn + nr; | |||||
@@ -3488,6 +3488,7 @@ int shadow_track_dirty_vram(struct domain *d, | |||||
p2m_type_t t; | |||||
struct sh_dirty_vram *dirty_vram; | |||||
struct p2m_domain *p2m = p2m_get_hostp2m(d); | |||||
+ uint8_t *dirty_bitmap = NULL; | |||||
if ( end_pfn < begin_pfn || end_pfn > p2m->max_mapped_pfn + 1 ) | |||||
return -EINVAL; | |||||
@@ -3516,6 +3517,12 @@ int shadow_track_dirty_vram(struct domain *d, | |||||
goto out; | |||||
} | |||||
+ dirty_bitmap = vzalloc(dirty_size); | |||||
+ if ( dirty_bitmap == NULL ) | |||||
+ { | |||||
+ rc = -ENOMEM; | |||||
+ goto out; | |||||
+ } | |||||
/* This should happen seldomly (Video mode change), | |||||
* no need to be careful. */ | |||||
if ( !dirty_vram ) | |||||
@@ -3546,12 +3553,8 @@ int shadow_track_dirty_vram(struct domain *d, | |||||
rc = -ENODATA; | |||||
} | |||||
else if (dirty_vram->last_dirty == -1) | |||||
- { | |||||
/* still completely clean, just copy our empty bitmap */ | |||||
- rc = -EFAULT; | |||||
- if ( copy_to_guest(dirty_bitmap, dirty_vram->dirty_bitmap, dirty_size) == 0 ) | |||||
- rc = 0; | |||||
- } | |||||
+ memcpy(dirty_bitmap, dirty_vram->dirty_bitmap, dirty_size); | |||||
else | |||||
{ | |||||
unsigned long map_mfn = INVALID_MFN; | |||||
@@ -3630,21 +3633,19 @@ int shadow_track_dirty_vram(struct domain *d, | |||||
if ( map_sl1p ) | |||||
sh_unmap_domain_page(map_sl1p); | |||||
- rc = -EFAULT; | |||||
- if ( copy_to_guest(dirty_bitmap, dirty_vram->dirty_bitmap, dirty_size) == 0 ) { | |||||
- memset(dirty_vram->dirty_bitmap, 0, dirty_size); | |||||
- if (dirty_vram->last_dirty + SECONDS(2) < NOW()) | |||||
+ memcpy(dirty_bitmap, dirty_vram->dirty_bitmap, dirty_size); | |||||
+ memset(dirty_vram->dirty_bitmap, 0, dirty_size); | |||||
+ if ( dirty_vram->last_dirty + SECONDS(2) < NOW() ) | |||||
+ { | |||||
+ /* was clean for more than two seconds, try to disable guest | |||||
+ * write access */ | |||||
+ for ( i = begin_pfn; i < end_pfn; i++ ) | |||||
{ | |||||
- /* was clean for more than two seconds, try to disable guest | |||||
- * write access */ | |||||
- for ( i = begin_pfn; i < end_pfn; i++ ) { | |||||
- mfn_t mfn = get_gfn_query_unlocked(d, i, &t); | |||||
- if (mfn_x(mfn) != INVALID_MFN) | |||||
- flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn, 1, 0); | |||||
- } | |||||
- dirty_vram->last_dirty = -1; | |||||
+ mfn_t mfn = get_gfn_query_unlocked(d, i, &t); | |||||
+ if ( mfn_x(mfn) != INVALID_MFN ) | |||||
+ flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn, 1, 0); | |||||
} | |||||
- rc = 0; | |||||
+ dirty_vram->last_dirty = -1; | |||||
} | |||||
} | |||||
if ( flush_tlb ) | |||||
@@ -3659,6 +3660,16 @@ out_dirty_vram: | |||||
out: | |||||
paging_unlock(d); | |||||
+ if ( rc == 0 && dirty_bitmap != NULL && | |||||
+ copy_to_guest(guest_dirty_bitmap, dirty_bitmap, dirty_size) ) | |||||
+ { | |||||
+ paging_lock(d); | |||||
+ for ( i = 0; i < dirty_size; i++ ) | |||||
+ dirty_vram->dirty_bitmap[i] |= dirty_bitmap[i]; | |||||
+ paging_unlock(d); | |||||
+ rc = -EFAULT; | |||||
+ } | |||||
+ vfree(dirty_bitmap); | |||||
p2m_unlock(p2m_get_hostp2m(d)); | |||||
return rc; | |||||
} | |||||
-- | |||||
1.9.5 (Apple Git-50.3) | |||||