aboutsummaryrefslogtreecommitdiffstats
path: root/main/xen/xsa97-hap-4_2-prereq.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/xen/xsa97-hap-4_2-prereq.patch')
-rw-r--r--main/xen/xsa97-hap-4_2-prereq.patch466
1 files changed, 0 insertions, 466 deletions
diff --git a/main/xen/xsa97-hap-4_2-prereq.patch b/main/xen/xsa97-hap-4_2-prereq.patch
deleted file mode 100644
index ce2240aec8..0000000000
--- a/main/xen/xsa97-hap-4_2-prereq.patch
+++ /dev/null
@@ -1,466 +0,0 @@
-x86/mm/hap: Adjust vram tracking to play nicely with log-dirty.
-
-The previous code assumed the guest would be in one of three mutually exclusive
-modes for bookkeeping dirty pages: (1) shadow, (2) hap utilizing the log dirty
-bitmap to support functionality such as live migrate, (3) hap utilizing the
-log dirty bitmap to track dirty vram pages.
-Races arose when a guest attempted to track dirty vram while performing live
-migrate. (The dispatch table managed by paging_log_dirty_init() might change
-in the middle of a log dirty or a vram tracking function.)
-
-This change allows hap log dirty and hap vram tracking to be concurrent.
-Vram tracking no longer uses the log dirty bitmap. Instead it detects
-dirty vram pages by examining their p2m type. The log dirty bitmap is only
-used by the log dirty code. Because the two operations use different
-mechanisms, they are no longer mutually exclusive.
-
-Signed-Off-By: Robert Phillips <robert.phillips@citrix.com>
-Acked-by: Tim Deegan <tim@xen.org>
-
-Minor whitespace changes to conform with coding style
-Signed-off-by: Tim Deegan <tim@xen.org>
-
-Committed-by: Tim Deegan <tim@xen.org>
-master commit: fd91a2a662bc59677e0f217423a7a155d5465886
-master date: 2012-12-13 12:10:14 +0000
-
---- a/xen/arch/x86/mm/hap/hap.c
-+++ b/xen/arch/x86/mm/hap/hap.c
-@@ -56,132 +56,110 @@
- /* HAP VRAM TRACKING SUPPORT */
- /************************************************/
-
--static int hap_enable_vram_tracking(struct domain *d)
--{
-- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
--
-- if ( !dirty_vram )
-- return -EINVAL;
--
-- /* turn on PG_log_dirty bit in paging mode */
-- paging_lock(d);
-- d->arch.paging.mode |= PG_log_dirty;
-- paging_unlock(d);
--
-- /* set l1e entries of P2M table to be read-only. */
-- p2m_change_type_range(d, dirty_vram->begin_pfn, dirty_vram->end_pfn,
-- p2m_ram_rw, p2m_ram_logdirty);
--
-- flush_tlb_mask(d->domain_dirty_cpumask);
-- return 0;
--}
--
--static int hap_disable_vram_tracking(struct domain *d)
--{
-- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
--
-- if ( !dirty_vram )
-- return -EINVAL;
--
-- paging_lock(d);
-- d->arch.paging.mode &= ~PG_log_dirty;
-- paging_unlock(d);
--
-- /* set l1e entries of P2M table with normal mode */
-- p2m_change_type_range(d, dirty_vram->begin_pfn, dirty_vram->end_pfn,
-- p2m_ram_logdirty, p2m_ram_rw);
--
-- flush_tlb_mask(d->domain_dirty_cpumask);
-- return 0;
--}
--
--static void hap_clean_vram_tracking(struct domain *d)
--{
-- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
--
-- if ( !dirty_vram )
-- return;
--
-- /* set l1e entries of P2M table to be read-only. */
-- p2m_change_type_range(d, dirty_vram->begin_pfn, dirty_vram->end_pfn,
-- p2m_ram_rw, p2m_ram_logdirty);
--
-- flush_tlb_mask(d->domain_dirty_cpumask);
--}
--
--static void hap_vram_tracking_init(struct domain *d)
--{
-- paging_log_dirty_init(d, hap_enable_vram_tracking,
-- hap_disable_vram_tracking,
-- hap_clean_vram_tracking);
--}
-+/*
-+ * hap_track_dirty_vram()
-+ * Create the domain's dv_dirty_vram struct on demand.
-+ * Create a dirty vram range on demand when some [begin_pfn:begin_pfn+nr] is
-+ * first encountered.
-+ * Collect the guest_dirty bitmask, a bit mask of the dirty vram pages, by
-+ * calling paging_log_dirty_range(), which interrogates each vram
-+ * page's p2m type looking for pages that have been made writable.
-+ */
-
- int hap_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)
- {
- long rc = 0;
-- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
-+ struct sh_dirty_vram *dirty_vram;
-+ uint8_t *dirty_bitmap = NULL;
-
- if ( nr )
- {
-- if ( paging_mode_log_dirty(d) && dirty_vram )
-+ int size = (nr + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
-+
-+ if ( !paging_mode_log_dirty(d) )
- {
-- if ( begin_pfn != dirty_vram->begin_pfn ||
-- begin_pfn + nr != dirty_vram->end_pfn )
-- {
-- paging_log_dirty_disable(d);
-- dirty_vram->begin_pfn = begin_pfn;
-- dirty_vram->end_pfn = begin_pfn + nr;
-- rc = paging_log_dirty_enable(d);
-- if (rc != 0)
-- goto param_fail;
-- }
-+ hap_logdirty_init(d);
-+ rc = paging_log_dirty_enable(d);
-+ if ( rc )
-+ goto out;
- }
-- else if ( !paging_mode_log_dirty(d) && !dirty_vram )
-+
-+ rc = -ENOMEM;
-+ dirty_bitmap = xzalloc_bytes(size);
-+ if ( !dirty_bitmap )
-+ goto out;
-+
-+ paging_lock(d);
-+
-+ dirty_vram = d->arch.hvm_domain.dirty_vram;
-+ if ( !dirty_vram )
- {
- rc = -ENOMEM;
-- if ( (dirty_vram = xmalloc(struct sh_dirty_vram)) == NULL )
-- goto param_fail;
-+ if ( (dirty_vram = xzalloc(struct sh_dirty_vram)) == NULL )
-+ {
-+ paging_unlock(d);
-+ goto out;
-+ }
-
-+ d->arch.hvm_domain.dirty_vram = dirty_vram;
-+ }
-+
-+ if ( begin_pfn != dirty_vram->begin_pfn ||
-+ begin_pfn + nr != dirty_vram->end_pfn )
-+ {
- dirty_vram->begin_pfn = begin_pfn;
- dirty_vram->end_pfn = begin_pfn + nr;
-- d->arch.hvm_domain.dirty_vram = dirty_vram;
-- hap_vram_tracking_init(d);
-- rc = paging_log_dirty_enable(d);
-- if (rc != 0)
-- goto param_fail;
-+
-+ paging_unlock(d);
-+
-+ /* set l1e entries of range within P2M table to be read-only. */
-+ p2m_change_type_range(d, begin_pfn, begin_pfn + nr,
-+ p2m_ram_rw, p2m_ram_logdirty);
-+
-+ flush_tlb_mask(d->domain_dirty_cpumask);
-+
-+ memset(dirty_bitmap, 0xff, size); /* consider all pages dirty */
- }
- else
- {
-- if ( !paging_mode_log_dirty(d) && dirty_vram )
-- rc = -EINVAL;
-- else
-- rc = -ENODATA;
-- goto param_fail;
-+ paging_unlock(d);
-+
-+ domain_pause(d);
-+
-+ /* get the bitmap */
-+ paging_log_dirty_range(d, begin_pfn, nr, dirty_bitmap);
-+
-+ domain_unpause(d);
- }
-- /* get the bitmap */
-- rc = paging_log_dirty_range(d, begin_pfn, nr, dirty_bitmap);
-+
-+ rc = -EFAULT;
-+ if ( copy_to_guest(guest_dirty_bitmap, dirty_bitmap, size) == 0 )
-+ rc = 0;
- }
- else
- {
-- if ( paging_mode_log_dirty(d) && dirty_vram ) {
-- rc = paging_log_dirty_disable(d);
-- xfree(dirty_vram);
-- dirty_vram = d->arch.hvm_domain.dirty_vram = NULL;
-- } else
-- rc = 0;
-- }
-+ paging_lock(d);
-
-- return rc;
-+ dirty_vram = d->arch.hvm_domain.dirty_vram;
-+ if ( dirty_vram )
-+ {
-+ /*
-+ * If zero pages specified while tracking dirty vram
-+ * then stop tracking
-+ */
-+ xfree(dirty_vram);
-+ d->arch.hvm_domain.dirty_vram = NULL;
-+ }
-
--param_fail:
-- if ( dirty_vram )
-- {
-- xfree(dirty_vram);
-- dirty_vram = d->arch.hvm_domain.dirty_vram = NULL;
-+ paging_unlock(d);
- }
-+out:
-+ if ( dirty_bitmap )
-+ xfree(dirty_bitmap);
-+
- return rc;
- }
-
-@@ -223,13 +201,6 @@ static void hap_clean_dirty_bitmap(struc
-
- void hap_logdirty_init(struct domain *d)
- {
-- struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
-- if ( paging_mode_log_dirty(d) && dirty_vram )
-- {
-- paging_log_dirty_disable(d);
-- xfree(dirty_vram);
-- dirty_vram = d->arch.hvm_domain.dirty_vram = NULL;
-- }
-
- /* Reinitialize logdirty mechanism */
- paging_log_dirty_init(d, hap_enable_log_dirty,
---- a/xen/arch/x86/mm/paging.c
-+++ b/xen/arch/x86/mm/paging.c
-@@ -447,157 +447,38 @@ int paging_log_dirty_op(struct domain *d
- return rv;
- }
-
--int paging_log_dirty_range(struct domain *d,
-- unsigned long begin_pfn,
-- unsigned long nr,
-- XEN_GUEST_HANDLE_64(uint8) dirty_bitmap)
--{
-- int rv = 0;
-- unsigned long pages = 0;
-- mfn_t *l4, *l3, *l2;
-- unsigned long *l1;
-- int b1, b2, b3, b4;
-- int i2, i3, i4;
--
-- d->arch.paging.log_dirty.clean_dirty_bitmap(d);
-- paging_lock(d);
--
-- PAGING_DEBUG(LOGDIRTY, "log-dirty-range: dom %u faults=%u dirty=%u\n",
-- d->domain_id,
-- d->arch.paging.log_dirty.fault_count,
-- d->arch.paging.log_dirty.dirty_count);
--
-- if ( unlikely(d->arch.paging.log_dirty.failed_allocs) ) {
-- printk("%s: %d failed page allocs while logging dirty pages\n",
-- __FUNCTION__, d->arch.paging.log_dirty.failed_allocs);
-- rv = -ENOMEM;
-- goto out;
-- }
-+void paging_log_dirty_range(struct domain *d,
-+ unsigned long begin_pfn,
-+ unsigned long nr,
-+ uint8_t *dirty_bitmap)
-+{
-+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
-+ int i;
-+ unsigned long pfn;
-+
-+ /*
-+ * Set l1e entries of P2M table to be read-only.
-+ *
-+ * On first write, it page faults, its entry is changed to read-write,
-+ * and on retry the write succeeds.
-+ *
-+ * We populate dirty_bitmap by looking for entries that have been
-+ * switched to read-write.
-+ */
-
-- if ( !d->arch.paging.log_dirty.fault_count &&
-- !d->arch.paging.log_dirty.dirty_count ) {
-- unsigned int size = BITS_TO_LONGS(nr);
--
-- if ( clear_guest(dirty_bitmap, size * BYTES_PER_LONG) != 0 )
-- rv = -EFAULT;
-- goto out;
-- }
-- d->arch.paging.log_dirty.fault_count = 0;
-- d->arch.paging.log_dirty.dirty_count = 0;
-+ p2m_lock(p2m);
-
-- b1 = L1_LOGDIRTY_IDX(begin_pfn);
-- b2 = L2_LOGDIRTY_IDX(begin_pfn);
-- b3 = L3_LOGDIRTY_IDX(begin_pfn);
-- b4 = L4_LOGDIRTY_IDX(begin_pfn);
-- l4 = paging_map_log_dirty_bitmap(d);
--
-- for ( i4 = b4;
-- (pages < nr) && (i4 < LOGDIRTY_NODE_ENTRIES);
-- i4++ )
-+ for ( i = 0, pfn = begin_pfn; pfn < begin_pfn + nr; i++, pfn++ )
- {
-- l3 = (l4 && mfn_valid(l4[i4])) ? map_domain_page(mfn_x(l4[i4])) : NULL;
-- for ( i3 = b3;
-- (pages < nr) && (i3 < LOGDIRTY_NODE_ENTRIES);
-- i3++ )
-- {
-- l2 = ((l3 && mfn_valid(l3[i3])) ?
-- map_domain_page(mfn_x(l3[i3])) : NULL);
-- for ( i2 = b2;
-- (pages < nr) && (i2 < LOGDIRTY_NODE_ENTRIES);
-- i2++ )
-- {
-- unsigned int bytes = PAGE_SIZE;
-- uint8_t *s;
-- l1 = ((l2 && mfn_valid(l2[i2])) ?
-- map_domain_page(mfn_x(l2[i2])) : NULL);
--
-- s = ((uint8_t*)l1) + (b1 >> 3);
-- bytes -= b1 >> 3;
--
-- if ( likely(((nr - pages + 7) >> 3) < bytes) )
-- bytes = (unsigned int)((nr - pages + 7) >> 3);
--
-- if ( !l1 )
-- {
-- if ( clear_guest_offset(dirty_bitmap, pages >> 3,
-- bytes) != 0 )
-- {
-- rv = -EFAULT;
-- goto out;
-- }
-- }
-- /* begin_pfn is not 32K aligned, hence we have to bit
-- * shift the bitmap */
-- else if ( b1 & 0x7 )
-- {
-- int i, j;
-- uint32_t *l = (uint32_t*) s;
-- int bits = b1 & 0x7;
-- int bitmask = (1 << bits) - 1;
-- int size = (bytes + BYTES_PER_LONG - 1) / BYTES_PER_LONG;
-- unsigned long bitmap[size];
-- static unsigned long printed = 0;
--
-- if ( printed != begin_pfn )
-- {
-- dprintk(XENLOG_DEBUG, "%s: begin_pfn %lx is not 32K aligned!\n",
-- __FUNCTION__, begin_pfn);
-- printed = begin_pfn;
-- }
--
-- for ( i = 0; i < size - 1; i++, l++ ) {
-- bitmap[i] = ((*l) >> bits) |
-- (((*((uint8_t*)(l + 1))) & bitmask) << (sizeof(*l) * 8 - bits));
-- }
-- s = (uint8_t*) l;
-- size = BYTES_PER_LONG - ((b1 >> 3) & 0x3);
-- bitmap[i] = 0;
-- for ( j = 0; j < size; j++, s++ )
-- bitmap[i] |= (*s) << (j * 8);
-- bitmap[i] = (bitmap[i] >> bits) | (bitmask << (size * 8 - bits));
-- if ( copy_to_guest_offset(dirty_bitmap, (pages >> 3),
-- (uint8_t*) bitmap, bytes) != 0 )
-- {
-- rv = -EFAULT;
-- goto out;
-- }
-- }
-- else
-- {
-- if ( copy_to_guest_offset(dirty_bitmap, pages >> 3,
-- s, bytes) != 0 )
-- {
-- rv = -EFAULT;
-- goto out;
-- }
-- }
--
-- pages += bytes << 3;
-- if ( l1 )
-- {
-- clear_page(l1);
-- unmap_domain_page(l1);
-- }
-- b1 = b1 & 0x7;
-- }
-- b2 = 0;
-- if ( l2 )
-- unmap_domain_page(l2);
-- }
-- b3 = 0;
-- if ( l3 )
-- unmap_domain_page(l3);
-+ p2m_type_t pt;
-+ pt = p2m_change_type(d, pfn, p2m_ram_rw, p2m_ram_logdirty);
-+ if ( pt == p2m_ram_rw )
-+ dirty_bitmap[i >> 3] |= (1 << (i & 7));
- }
-- if ( l4 )
-- unmap_domain_page(l4);
--
-- paging_unlock(d);
-
-- return rv;
-+ p2m_unlock(p2m);
-
-- out:
-- paging_unlock(d);
-- return rv;
-+ flush_tlb_mask(d->domain_dirty_cpumask);
- }
-
- /* Note that this function takes three function pointers. Callers must supply
---- a/xen/include/asm-x86/config.h
-+++ b/xen/include/asm-x86/config.h
-@@ -17,6 +17,7 @@
-
- #define BYTES_PER_LONG (1 << LONG_BYTEORDER)
- #define BITS_PER_LONG (BYTES_PER_LONG << 3)
-+#define BITS_PER_BYTE 8
-
- #define CONFIG_X86 1
- #define CONFIG_X86_HT 1
---- a/xen/include/asm-x86/paging.h
-+++ b/xen/include/asm-x86/paging.h
-@@ -145,10 +145,10 @@ struct paging_mode {
- void paging_free_log_dirty_bitmap(struct domain *d);
-
- /* get the dirty bitmap for a specific range of pfns */
--int paging_log_dirty_range(struct domain *d,
-- unsigned long begin_pfn,
-- unsigned long nr,
-- XEN_GUEST_HANDLE_64(uint8) dirty_bitmap);
-+void paging_log_dirty_range(struct domain *d,
-+ unsigned long begin_pfn,
-+ unsigned long nr,
-+ uint8_t *dirty_bitmap);
-
- /* enable log dirty */
- int paging_log_dirty_enable(struct domain *d);