Page MenuHomeFreeBSD

D16416.diff
No OneTemporary

D16416.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: head/MOVED
===================================================================
--- head/MOVED
+++ head/MOVED
@@ -10354,3 +10354,6 @@
graphics/projectm-libvisual|graphics/libprojectm|2018-07-17|Code of projectm-libvisual was merged into graphics/libprojectm
graphics/yafray|graphics/yafaray|2018-07-20|Project renamed
lang/spec.alpha||2018-07-21|Unused in the ports tree
+sysutils/xen-tools|sysutils/xen-tools47|2018-07-23|Renamed to support multiple versions
+emulators/xen-kernel|emulators/xen-kernel47|2018-07-23|Renamed to support multiple versions
+emulators/xen||2018-07-23|Removed to support multiple versions
Index: head/emulators/xen-kernel/Makefile
===================================================================
--- head/emulators/xen-kernel/Makefile
+++ head/emulators/xen-kernel/Makefile
@@ -1,124 +0,0 @@
-# $FreeBSD$
-
-PORTNAME= xen
-PORTVERSION= 4.7.2
-PORTREVISION= 9
-CATEGORIES= emulators
-MASTER_SITES= http://downloads.xenproject.org/release/xen/${PORTVERSION}/
-PKGNAMESUFFIX= -kernel
-
-MAINTAINER= royger@FreeBSD.org
-COMMENT= Hypervisor using a microkernel design
-
-LICENSE= GPLv2
-
-ONLY_FOR_ARCHS= amd64
-
-USES= cpe gmake python:2.7,build
-
-# We need to use ld from ports because the version in base doesn't
-# support the '--build-id' switch that's needed for live hypervisor
-# hot-patching. Once the ld version in base supports this option the
-# dependency can be removed.
-#
-# GNU objcopy is used instead of elftc objcopy because of bug #533:
-# https://sourceforge.net/p/elftoolchain/tickets/533/
-# Once this is solved we should be able to switch to elfcopy.
-#
-# And finally we also need to use nm from binutils because the one
-# from base cannot deal with i386pep binary files which is the format
-# of the Xen EFI image (note that FreeBSD cannot yet boot as Dom0 from EFI,
-# but the image is built anyway). This is reported to elftc as bug #534:
-# https://sourceforge.net/p/elftoolchain/tickets/534/
-MAKE_ARGS= clang=y PYTHON=${PYTHON_CMD} LD="${LD}" OBJCOPY="${OBJCOPY}" \
- NM="${NM}"
-USE_BINUTILS= yes
-NO_MTREE= yes
-STRIP= #
-PLIST_FILES= /boot/xen \
- /boot/xen.4th
-EXTRA_PATCHES= ${FILESDIR}/0001-xen-logdirty-prevent-preemption-if-finished.patch:-p1 \
- ${FILESDIR}/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch:-p1 \
- ${FILESDIR}/kconf_arch.patch:-p1 \
- ${FILESDIR}/0001-x86-drop-unneeded-__packed-attributes.patch:-p1 \
- ${FILESDIR}/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch:-p1 \
- ${FILESDIR}/xsa212.patch:-p1 \
- ${FILESDIR}/xsa213-4.7.patch:-p1 \
- ${FILESDIR}/xsa214.patch:-p1 \
- ${FILESDIR}/xsa215.patch:-p1 \
- ${FILESDIR}/xsa217.patch:-p1 \
- ${FILESDIR}/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch:-p1 \
- ${FILESDIR}/0002-gnttab-fix-unmap-pin-accounting-race.patch:-p1 \
- ${FILESDIR}/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch:-p1 \
- ${FILESDIR}/0004-gnttab-correct-maptrack-table-accesses.patch:-p1 \
- ${FILESDIR}/xsa219-4.8.patch:-p1 \
- ${FILESDIR}/xsa220-4.7.patch:-p1 \
- ${FILESDIR}/xsa221.patch:-p1 \
- ${FILESDIR}/xsa222-1-4.7.patch:-p1 \
- ${FILESDIR}/xsa222-2-4.7.patch:-p1 \
- ${FILESDIR}/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch:-p1 \
- ${FILESDIR}/0002-gnttab-never-create-host-mapping-unless-asked-to.patch:-p1 \
- ${FILESDIR}/0003-gnttab-correct-logic-to-get-page-references-during-m.patch:-p1 \
- ${FILESDIR}/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch:-p1 \
- ${FILESDIR}/xsa226-4.7.patch:-p1 \
- ${FILESDIR}/xsa227.patch:-p1 \
- ${FILESDIR}/xsa228-4.8.patch:-p1 \
- ${FILESDIR}/xsa230.patch:-p1 \
- ${FILESDIR}/xsa231-4.7.patch:-p1 \
- ${FILESDIR}/xsa232.patch:-p1 \
- ${FILESDIR}/xsa233.patch:-p1 \
- ${FILESDIR}/xsa234-4.8.patch:-p1 \
- ${FILESDIR}/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch:-p1 \
- ${FILESDIR}/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch:-p1 \
- ${FILESDIR}/0003-x86-MSI-disallow-redundant-enabling.patch:-p1 \
- ${FILESDIR}/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch:-p1 \
- ${FILESDIR}/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch:-p1 \
- ${FILESDIR}/xsa238.patch:-p1 \
- ${FILESDIR}/xsa239.patch:-p1 \
- ${FILESDIR}/0001-x86-limit-linear-page-table-use-to-a-single-level.patch:-p1 \
- ${FILESDIR}/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch:-p1 \
- ${FILESDIR}/xsa241-4.8.patch:-p1 \
- ${FILESDIR}/xsa242-4.9.patch:-p1 \
- ${FILESDIR}/xsa243-4.7.patch:-p1 \
- ${FILESDIR}/xsa244-4.7.patch:-p1 \
- ${FILESDIR}/xsa236-4.9.patch:-p1 \
- ${FILESDIR}/0001-x86-compat-fix-compilation-errors-with-clang-6.patch:-p1 \
- ${FILESDIR}/xsa246-4.7.patch:-p1 \
- ${FILESDIR}/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch:-p1 \
- ${FILESDIR}/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch:-p1 \
- ${FILESDIR}/xsa248-4.8.patch:-p1 \
- ${FILESDIR}/xsa249.patch:-p1 \
- ${FILESDIR}/xsa250.patch:-p1 \
- ${FILESDIR}/xsa251-4.8.patch:-p1 \
- ${FILESDIR}/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch:-p1 \
- ${FILESDIR}/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch:-p1 \
- ${FILESDIR}/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch:-p1 \
- ${FILESDIR}/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch:-p1
-
-.include <bsd.port.options.mk>
-
-.if ${OPSYS} != FreeBSD
-IGNORE= only supported on FreeBSD
-.endif
-
-.if ${OSVERSION} < 1100055
-IGNORE= only supported on recent FreeBSD 11
-.endif
-
-pre-build:
- ${MAKE_CMD} -C ${WRKSRC}/xen defconfig ${MAKE_ARGS}
- # Enable hypervisor hot-patching.
- echo 'CONFIG_XSPLICE=y' >> ${WRKSRC}/xen/.config
- echo 'CONFIG_FAST_SYMBOL_LOOKUP=y' >> ${WRKSRC}/xen/.config
-
-# The ports native 'build' target cannot be used because it sets
-# CFLAGS, and that breaks the Xen build system.
-do-build:
- ${MAKE_CMD} -j${MAKE_JOBS_NUMBER} -C ${WRKSRC}/xen build ${MAKE_ARGS}
-
-do-install:
- ${MKDIR} ${STAGEDIR}/boot
- ${INSTALL_PROGRAM} ${WRKSRC}/xen/xen ${STAGEDIR}/boot
- ${INSTALL_DATA} ${FILESDIR}/xen.4th ${STAGEDIR}/boot
-
-.include <bsd.port.mk>
Index: head/emulators/xen-kernel/distinfo
===================================================================
--- head/emulators/xen-kernel/distinfo
+++ head/emulators/xen-kernel/distinfo
@@ -1,3 +0,0 @@
-TIMESTAMP = 1489059095
-SHA256 (xen-4.7.2.tar.gz) = 61494a56d9251e2108080f95b0dc8e3d175f1ba4da34603fc07b91cfebf358d5
-SIZE (xen-4.7.2.tar.gz) = 20714281
Index: head/emulators/xen-kernel/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
+++ head/emulators/xen-kernel/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
@@ -1,78 +0,0 @@
-From 03f872b98f24e25cafb478b5d7c34e1eb18e1e4c Mon Sep 17 00:00:00 2001
-From: Quan Xu <quan.xu@intel.com>
-Date: Fri, 2 Jun 2017 12:30:34 +0100
-Subject: [PATCH 1/4] IOMMU: handle IOMMU mapping and unmapping failures
-
-Treat IOMMU mapping and unmapping failures as a fatal to the DomU
-If IOMMU mapping and unmapping failed, crash the DomU and propagate
-the error up to the call trees.
-
-No spamming of the log can occur. For DomU, we avoid logging any
-message for already dying domains. For Dom0, that'll still be more
-verbose than we'd really like, but it at least wouldn't outright
-flood the console.
-
-Signed-off-by: Quan Xu <quan.xu@intel.com>
-Reviewed-by: Kevin Tian <kevin.tian@intel.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
----
- xen/drivers/passthrough/iommu.c | 30 ++++++++++++++++++++++++++++--
- 1 file changed, 28 insertions(+), 2 deletions(-)
-
-diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
-index 1a315ee..927966f 100644
---- a/xen/drivers/passthrough/iommu.c
-+++ b/xen/drivers/passthrough/iommu.c
-@@ -239,21 +239,47 @@ int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
- unsigned int flags)
- {
- const struct domain_iommu *hd = dom_iommu(d);
-+ int rc;
-
- if ( !iommu_enabled || !hd->platform_ops )
- return 0;
-
-- return hd->platform_ops->map_page(d, gfn, mfn, flags);
-+ rc = hd->platform_ops->map_page(d, gfn, mfn, flags);
-+ if ( unlikely(rc) )
-+ {
-+ if ( !d->is_shutting_down && printk_ratelimit() )
-+ printk(XENLOG_ERR
-+ "d%d: IOMMU mapping gfn %#lx to mfn %#lx failed: %d\n",
-+ d->domain_id, gfn, mfn, rc);
-+
-+ if ( !is_hardware_domain(d) )
-+ domain_crash(d);
-+ }
-+
-+ return rc;
- }
-
- int iommu_unmap_page(struct domain *d, unsigned long gfn)
- {
- const struct domain_iommu *hd = dom_iommu(d);
-+ int rc;
-
- if ( !iommu_enabled || !hd->platform_ops )
- return 0;
-
-- return hd->platform_ops->unmap_page(d, gfn);
-+ rc = hd->platform_ops->unmap_page(d, gfn);
-+ if ( unlikely(rc) )
-+ {
-+ if ( !d->is_shutting_down && printk_ratelimit() )
-+ printk(XENLOG_ERR
-+ "d%d: IOMMU unmapping gfn %#lx failed: %d\n",
-+ d->domain_id, gfn, rc);
-+
-+ if ( !is_hardware_domain(d) )
-+ domain_crash(d);
-+ }
-+
-+ return rc;
- }
-
- static void iommu_free_pagetables(unsigned long unused)
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
+++ head/emulators/xen-kernel/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
@@ -1,111 +0,0 @@
-From fd97f5f5ba9375163c8d8771fe551bb4a6423b36 Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Thu, 15 Jun 2017 16:24:02 +0100
-Subject: [PATCH 1/4] gnttab: Fix handling of dev_bus_addr during unmap
-
-If a grant has been mapped with the GNTTAB_device_map flag, calling
-grant_unmap_ref() with dev_bus_addr set to zero should cause the
-GNTTAB_device_map part of the mapping to be left alone.
-
-Unfortunately, at the moment, op->dev_bus_addr is implicitly checked
-before clearing the map and adjusting the pin count, but only the bits
-above 12; and it is not checked at all before dropping page
-references. This means a guest can repeatedly make such a call to
-cause the reference count to drop to zero, causing the page to be
-freed and re-used, even though it's still mapped in its pagetables.
-
-To fix this, always check op->dev_bus_addr explicitly for being
-non-zero, as well as op->flag & GNTMAP_device_map, before doing
-operations on the device_map.
-
-While we're here, make the logic a bit cleaner:
-
-* Always initialize op->frame to zero and set it from act->frame, to reduce the
-chance of untrusted input being used
-
-* Explicitly check the full dev_bus_addr against act->frame <<
- PAGE_SHIFT, rather than ignoring the lower 12 bits
-
-This is part of XSA-224.
-
-Reported-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 23 +++++++++++------------
- 1 file changed, 11 insertions(+), 12 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index c4d73af..69cbdb6 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -1089,8 +1089,6 @@ __gnttab_unmap_common(
- ld = current->domain;
- lgt = ld->grant_table;
-
-- op->frame = (unsigned long)(op->dev_bus_addr >> PAGE_SHIFT);
--
- if ( unlikely(op->handle >= lgt->maptrack_limit) )
- {
- gdprintk(XENLOG_INFO, "Bad handle (%d).\n", op->handle);
-@@ -1174,16 +1172,14 @@ __gnttab_unmap_common(
- goto act_release_out;
- }
-
-- if ( op->frame == 0 )
-- {
-- op->frame = act->frame;
-- }
-- else
-+ op->frame = act->frame;
-+
-+ if ( op->dev_bus_addr )
- {
-- if ( unlikely(op->frame != act->frame) )
-+ if ( unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
- PIN_FAIL(act_release_out, GNTST_general_error,
-- "Bad frame number doesn't match gntref. (%lx != %lx)\n",
-- op->frame, act->frame);
-+ "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
-+ op->dev_bus_addr, pfn_to_paddr(act->frame));
-
- map->flags &= ~GNTMAP_device_map;
- }
-@@ -1276,7 +1272,8 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- else
- status = &status_entry(rgt, op->ref);
-
-- if ( unlikely(op->frame != act->frame) )
-+ if ( op->dev_bus_addr &&
-+ unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
- {
- /*
- * Suggests that __gntab_unmap_common failed early and so
-@@ -1287,7 +1284,7 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
-
- pg = mfn_to_page(op->frame);
-
-- if ( op->flags & GNTMAP_device_map )
-+ if ( op->dev_bus_addr && (op->flags & GNTMAP_device_map) )
- {
- if ( !is_iomem_page(act->frame) )
- {
-@@ -1358,6 +1355,7 @@ __gnttab_unmap_grant_ref(
- /* Intialise these in case common contains old state */
- common->new_addr = 0;
- common->rd = NULL;
-+ common->frame = 0;
-
- __gnttab_unmap_common(common);
- op->status = common->status;
-@@ -1422,6 +1420,7 @@ __gnttab_unmap_and_replace(
- /* Intialise these in case common contains old state */
- common->dev_bus_addr = 0;
- common->rd = NULL;
-+ common->frame = 0;
-
- __gnttab_unmap_common(common);
- op->status = common->status;
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
+++ head/emulators/xen-kernel/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
@@ -1,176 +0,0 @@
-From f345ca185e0c042ed12bf929a9e93efaf33397bb Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Fri, 10 Nov 2017 16:53:54 +0000
-Subject: [PATCH 1/2] p2m: Always check to see if removing a p2m entry actually
- worked
-
-The PoD zero-check functions speculatively remove memory from the p2m,
-then check to see if it's completely zeroed, before putting it in the
-cache.
-
-Unfortunately, the p2m_set_entry() calls may fail if the underlying
-pagetable structure needs to change and the domain has exhausted its
-p2m memory pool: for instance, if we're removing a 2MiB region out of
-a 1GiB entry (in the p2m_pod_zero_check_superpage() case), or a 4k
-region out of a 2MiB or larger entry (in the p2m_pod_zero_check()
-case); and the return value is not checked.
-
-The underlying mfn will then be added into the PoD cache, and at some
-point mapped into another location in the p2m. If the guest
-afterwards ballons out this memory, it will be freed to the hypervisor
-and potentially reused by another domain, in spite of the fact that
-the original domain still has writable mappings to it.
-
-There are several places where p2m_set_entry() shouldn't be able to
-fail, as it is guaranteed to write an entry of the same order that
-succeeded before. Add a backstop of crashing the domain just in case,
-and an ASSERT_UNREACHABLE() to flag up the broken assumption on debug
-builds.
-
-While we're here, use PAGE_ORDER_2M rather than a magic constant.
-
-This is part of XSA-247.
-
-Reported-by: George Dunlap <george.dunlap.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
----
-v4:
-- Removed some training whitespace
-v3:
-- Reformat reset clause to be more compact
-- Make sure to set map[i] = NULL when unmapping in case we need to bail
-v2:
-- Crash a domain if a p2m_set_entry we think cannot fail fails anyway.
----
- xen/arch/x86/mm/p2m-pod.c | 77 +++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 61 insertions(+), 16 deletions(-)
-
-diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
-index 87082cf65f..5ec8a37949 100644
---- a/xen/arch/x86/mm/p2m-pod.c
-+++ b/xen/arch/x86/mm/p2m-pod.c
-@@ -754,8 +754,10 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
- }
-
- /* Try to remove the page, restoring old mapping if it fails. */
-- p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_2M,
-- p2m_populate_on_demand, p2m->default_access);
-+ if ( p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_2M,
-+ p2m_populate_on_demand, p2m->default_access) )
-+ goto out;
-+
- p2m_tlb_flush_sync(p2m);
-
- /* Make none of the MFNs are used elsewhere... for example, mapped
-@@ -812,9 +814,18 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
- ret = SUPERPAGE_PAGES;
-
- out_reset:
-- if ( reset )
-- p2m_set_entry(p2m, gfn, mfn0, 9, type0, p2m->default_access);
--
-+ /*
-+ * This p2m_set_entry() call shouldn't be able to fail, since the same order
-+ * on the same gfn succeeded above. If that turns out to be false, crashing
-+ * the domain should be the safest way of making sure we don't leak memory.
-+ */
-+ if ( reset && p2m_set_entry(p2m, gfn, mfn0, PAGE_ORDER_2M,
-+ type0, p2m->default_access) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ domain_crash(d);
-+ }
-+
- out:
- gfn_unlock(p2m, gfn, SUPERPAGE_ORDER);
- return ret;
-@@ -871,19 +882,30 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
- }
-
- /* Try to remove the page, restoring old mapping if it fails. */
-- p2m_set_entry(p2m, gfns[i], _mfn(INVALID_MFN), PAGE_ORDER_4K,
-- p2m_populate_on_demand, p2m->default_access);
-+ if ( p2m_set_entry(p2m, gfns[i], _mfn(INVALID_MFN), PAGE_ORDER_4K,
-+ p2m_populate_on_demand, p2m->default_access) )
-+ goto skip;
-
- /* See if the page was successfully unmapped. (Allow one refcount
- * for being allocated to a domain.) */
- if ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) > 1 )
- {
-+ /*
-+ * If the previous p2m_set_entry call succeeded, this one shouldn't
-+ * be able to fail. If it does, crashing the domain should be safe.
-+ */
-+ if ( p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
-+ types[i], p2m->default_access) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ domain_crash(d);
-+ goto out_unmap;
-+ }
-+
-+ skip:
- unmap_domain_page(map[i]);
- map[i] = NULL;
-
-- p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
-- types[i], p2m->default_access);
--
- continue;
- }
- }
-@@ -902,12 +924,25 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
-
- unmap_domain_page(map[i]);
-
-- /* See comment in p2m_pod_zero_check_superpage() re gnttab
-- * check timing. */
-- if ( j < PAGE_SIZE/sizeof(*map[i]) )
-+ map[i] = NULL;
-+
-+ /*
-+ * See comment in p2m_pod_zero_check_superpage() re gnttab
-+ * check timing.
-+ */
-+ if ( j < (PAGE_SIZE / sizeof(*map[i])) )
- {
-- p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
-- types[i], p2m->default_access);
-+ /*
-+ * If the previous p2m_set_entry call succeeded, this one shouldn't
-+ * be able to fail. If it does, crashing the domain should be safe.
-+ */
-+ if ( p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
-+ types[i], p2m->default_access) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ domain_crash(d);
-+ goto out_unmap;
-+ }
- }
- else
- {
-@@ -931,7 +966,17 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
- p2m->pod.entry_count++;
- }
- }
--
-+
-+ return;
-+
-+out_unmap:
-+ /*
-+ * Something went wrong, probably crashing the domain. Unmap
-+ * everything and return.
-+ */
-+ for ( i = 0; i < count; i++ )
-+ if ( map[i] )
-+ unmap_domain_page(map[i]);
- }
-
- #define POD_SWEEP_LIMIT 1024
---
-2.15.0
-
Index: head/emulators/xen-kernel/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
+++ head/emulators/xen-kernel/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
@@ -1,756 +0,0 @@
-From e19517a3355acaaa2ff83018bc41e7fd044161e5 Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Wed, 17 Jan 2018 17:24:12 +0100
-Subject: [PATCH 1/2] x86: Meltdown band-aid against malicious 64-bit PV guests
-
-This is a very simplistic change limiting the amount of memory a running
-64-bit PV guest has mapped (and hence available for attacking): Only the
-mappings of stack, IDT, and TSS are being cloned from the direct map
-into per-CPU page tables. Guest controlled parts of the page tables are
-being copied into those per-CPU page tables upon entry into the guest.
-Cross-vCPU synchronization of top level page table entry changes is
-being effected by forcing other active vCPU-s of the guest into the
-hypervisor.
-
-The change to context_switch() isn't strictly necessary, but there's no
-reason to keep switching page tables once a PV guest is being scheduled
-out.
-
-This isn't providing full isolation yet, but it should be covering all
-pieces of information exposure of which would otherwise require an XSA.
-
-There is certainly much room for improvement, especially of performance,
-here - first and foremost suppressing all the negative effects on AMD
-systems. But in the interest of backportability (including to really old
-hypervisors, which may not even have alternative patching) any such is
-being left out here.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-master commit: 5784de3e2067ed73efc2fe42e62831e8ae7f46c4
-master date: 2018-01-16 17:49:03 +0100
----
- xen/arch/x86/domain.c | 5 +
- xen/arch/x86/mm.c | 17 ++++
- xen/arch/x86/smpboot.c | 198 +++++++++++++++++++++++++++++++++++++
- xen/arch/x86/x86_64/asm-offsets.c | 2 +
- xen/arch/x86/x86_64/compat/entry.S | 11 +++
- xen/arch/x86/x86_64/entry.S | 149 +++++++++++++++++++++++++++-
- xen/include/asm-x86/asm_defns.h | 30 ++++++
- xen/include/asm-x86/current.h | 12 +++
- xen/include/asm-x86/processor.h | 1 +
- xen/include/asm-x86/x86_64/page.h | 5 +-
- 10 files changed, 424 insertions(+), 6 deletions(-)
-
-diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
-index 6539b75fa7..3cf18f95b7 100644
---- a/xen/arch/x86/domain.c
-+++ b/xen/arch/x86/domain.c
-@@ -1949,6 +1949,9 @@ static void paravirt_ctxt_switch_to(struct vcpu *v)
-
- switch_kernel_stack(v);
-
-+ this_cpu(root_pgt)[root_table_offset(PERDOMAIN_VIRT_START)] =
-+ l4e_from_page(v->domain->arch.perdomain_l3_pg, __PAGE_HYPERVISOR_RW);
-+
- cr4 = pv_guest_cr4_to_real_cr4(v);
- if ( unlikely(cr4 != read_cr4()) )
- write_cr4(cr4);
-@@ -2096,6 +2099,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
-
- ASSERT(local_irq_is_enabled());
-
-+ get_cpu_info()->xen_cr3 = 0;
-+
- cpumask_copy(&dirty_mask, next->vcpu_dirty_cpumask);
- /* Allow at most one CPU at a time to be dirty. */
- ASSERT(cpumask_weight(&dirty_mask) <= 1);
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index 50f500c940..c9e4003989 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -3857,6 +3857,7 @@ long do_mmu_update(
- struct vcpu *curr = current, *v = curr;
- struct domain *d = v->domain, *pt_owner = d, *pg_owner;
- struct domain_mmap_cache mapcache;
-+ bool_t sync_guest = 0;
- uint32_t xsm_needed = 0;
- uint32_t xsm_checked = 0;
- int rc = put_old_guest_table(curr);
-@@ -4005,6 +4006,8 @@ long do_mmu_update(
- case PGT_l4_page_table:
- rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
- cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
-+ if ( !rc )
-+ sync_guest = 1;
- break;
- case PGT_writable_page:
- perfc_incr(writable_mmu_updates);
-@@ -4107,6 +4110,20 @@ long do_mmu_update(
-
- domain_mmap_cache_destroy(&mapcache);
-
-+ if ( sync_guest )
-+ {
-+ /*
-+ * Force other vCPU-s of the affected guest to pick up L4 entry
-+ * changes (if any). Issue a flush IPI with empty operation mask to
-+ * facilitate this (including ourselves waiting for the IPI to
-+ * actually have arrived). Utilize the fact that FLUSH_VA_VALID is
-+ * meaningless without FLUSH_CACHE, but will allow to pass the no-op
-+ * check in flush_area_mask().
-+ */
-+ flush_area_mask(pt_owner->domain_dirty_cpumask,
-+ ZERO_BLOCK_PTR, FLUSH_VA_VALID);
-+ }
-+
- perfc_add(num_page_updates, i);
-
- out:
-diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
-index f9e4ee85ff..eaeec5acf0 100644
---- a/xen/arch/x86/smpboot.c
-+++ b/xen/arch/x86/smpboot.c
-@@ -319,6 +319,9 @@ void start_secondary(void *unused)
- */
- spin_debug_disable();
-
-+ get_cpu_info()->xen_cr3 = 0;
-+ get_cpu_info()->pv_cr3 = __pa(this_cpu(root_pgt));
-+
- load_system_tables();
-
- /* Full exception support from here on in. */
-@@ -628,6 +631,187 @@ void cpu_exit_clear(unsigned int cpu)
- set_cpu_state(CPU_STATE_DEAD);
- }
-
-+static int clone_mapping(const void *ptr, root_pgentry_t *rpt)
-+{
-+ unsigned long linear = (unsigned long)ptr, pfn;
-+ unsigned int flags;
-+ l3_pgentry_t *pl3e = l4e_to_l3e(idle_pg_table[root_table_offset(linear)]) +
-+ l3_table_offset(linear);
-+ l2_pgentry_t *pl2e;
-+ l1_pgentry_t *pl1e;
-+
-+ if ( linear < DIRECTMAP_VIRT_START )
-+ return 0;
-+
-+ flags = l3e_get_flags(*pl3e);
-+ ASSERT(flags & _PAGE_PRESENT);
-+ if ( flags & _PAGE_PSE )
-+ {
-+ pfn = (l3e_get_pfn(*pl3e) & ~((1UL << (2 * PAGETABLE_ORDER)) - 1)) |
-+ (PFN_DOWN(linear) & ((1UL << (2 * PAGETABLE_ORDER)) - 1));
-+ flags &= ~_PAGE_PSE;
-+ }
-+ else
-+ {
-+ pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(linear);
-+ flags = l2e_get_flags(*pl2e);
-+ ASSERT(flags & _PAGE_PRESENT);
-+ if ( flags & _PAGE_PSE )
-+ {
-+ pfn = (l2e_get_pfn(*pl2e) & ~((1UL << PAGETABLE_ORDER) - 1)) |
-+ (PFN_DOWN(linear) & ((1UL << PAGETABLE_ORDER) - 1));
-+ flags &= ~_PAGE_PSE;
-+ }
-+ else
-+ {
-+ pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(linear);
-+ flags = l1e_get_flags(*pl1e);
-+ if ( !(flags & _PAGE_PRESENT) )
-+ return 0;
-+ pfn = l1e_get_pfn(*pl1e);
-+ }
-+ }
-+
-+ if ( !(root_get_flags(rpt[root_table_offset(linear)]) & _PAGE_PRESENT) )
-+ {
-+ pl3e = alloc_xen_pagetable();
-+ if ( !pl3e )
-+ return -ENOMEM;
-+ clear_page(pl3e);
-+ l4e_write(&rpt[root_table_offset(linear)],
-+ l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR));
-+ }
-+ else
-+ pl3e = l4e_to_l3e(rpt[root_table_offset(linear)]);
-+
-+ pl3e += l3_table_offset(linear);
-+
-+ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
-+ {
-+ pl2e = alloc_xen_pagetable();
-+ if ( !pl2e )
-+ return -ENOMEM;
-+ clear_page(pl2e);
-+ l3e_write(pl3e, l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR));
-+ }
-+ else
-+ {
-+ ASSERT(!(l3e_get_flags(*pl3e) & _PAGE_PSE));
-+ pl2e = l3e_to_l2e(*pl3e);
-+ }
-+
-+ pl2e += l2_table_offset(linear);
-+
-+ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
-+ {
-+ pl1e = alloc_xen_pagetable();
-+ if ( !pl1e )
-+ return -ENOMEM;
-+ clear_page(pl1e);
-+ l2e_write(pl2e, l2e_from_paddr(__pa(pl1e), __PAGE_HYPERVISOR));
-+ }
-+ else
-+ {
-+ ASSERT(!(l2e_get_flags(*pl2e) & _PAGE_PSE));
-+ pl1e = l2e_to_l1e(*pl2e);
-+ }
-+
-+ pl1e += l1_table_offset(linear);
-+
-+ if ( l1e_get_flags(*pl1e) & _PAGE_PRESENT )
-+ {
-+ ASSERT(l1e_get_pfn(*pl1e) == pfn);
-+ ASSERT(l1e_get_flags(*pl1e) == flags);
-+ }
-+ else
-+ l1e_write(pl1e, l1e_from_pfn(pfn, flags));
-+
-+ return 0;
-+}
-+
-+DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
-+
-+static int setup_cpu_root_pgt(unsigned int cpu)
-+{
-+ root_pgentry_t *rpt = alloc_xen_pagetable();
-+ unsigned int off;
-+ int rc;
-+
-+ if ( !rpt )
-+ return -ENOMEM;
-+
-+ clear_page(rpt);
-+ per_cpu(root_pgt, cpu) = rpt;
-+
-+ rpt[root_table_offset(RO_MPT_VIRT_START)] =
-+ idle_pg_table[root_table_offset(RO_MPT_VIRT_START)];
-+ /* SH_LINEAR_PT inserted together with guest mappings. */
-+ /* PERDOMAIN inserted during context switch. */
-+ rpt[root_table_offset(XEN_VIRT_START)] =
-+ idle_pg_table[root_table_offset(XEN_VIRT_START)];
-+
-+ /* Install direct map page table entries for stack, IDT, and TSS. */
-+ for ( off = rc = 0; !rc && off < STACK_SIZE; off += PAGE_SIZE )
-+ rc = clone_mapping(__va(__pa(stack_base[cpu])) + off, rpt);
-+
-+ if ( !rc )
-+ rc = clone_mapping(idt_tables[cpu], rpt);
-+ if ( !rc )
-+ rc = clone_mapping(&per_cpu(init_tss, cpu), rpt);
-+
-+ return rc;
-+}
-+
-+static void cleanup_cpu_root_pgt(unsigned int cpu)
-+{
-+ root_pgentry_t *rpt = per_cpu(root_pgt, cpu);
-+ unsigned int r;
-+
-+ if ( !rpt )
-+ return;
-+
-+ per_cpu(root_pgt, cpu) = NULL;
-+
-+ for ( r = root_table_offset(DIRECTMAP_VIRT_START);
-+ r < root_table_offset(HYPERVISOR_VIRT_END); ++r )
-+ {
-+ l3_pgentry_t *l3t;
-+ unsigned int i3;
-+
-+ if ( !(root_get_flags(rpt[r]) & _PAGE_PRESENT) )
-+ continue;
-+
-+ l3t = l4e_to_l3e(rpt[r]);
-+
-+ for ( i3 = 0; i3 < L3_PAGETABLE_ENTRIES; ++i3 )
-+ {
-+ l2_pgentry_t *l2t;
-+ unsigned int i2;
-+
-+ if ( !(l3e_get_flags(l3t[i3]) & _PAGE_PRESENT) )
-+ continue;
-+
-+ ASSERT(!(l3e_get_flags(l3t[i3]) & _PAGE_PSE));
-+ l2t = l3e_to_l2e(l3t[i3]);
-+
-+ for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; ++i2 )
-+ {
-+ if ( !(l2e_get_flags(l2t[i2]) & _PAGE_PRESENT) )
-+ continue;
-+
-+ ASSERT(!(l2e_get_flags(l2t[i2]) & _PAGE_PSE));
-+ free_xen_pagetable(l2e_to_l1e(l2t[i2]));
-+ }
-+
-+ free_xen_pagetable(l2t);
-+ }
-+
-+ free_xen_pagetable(l3t);
-+ }
-+
-+ free_xen_pagetable(rpt);
-+}
-+
- static void cpu_smpboot_free(unsigned int cpu)
- {
- unsigned int order, socket = cpu_to_socket(cpu);
-@@ -664,6 +848,8 @@ static void cpu_smpboot_free(unsigned int cpu)
- free_domheap_page(mfn_to_page(mfn));
- }
-
-+ cleanup_cpu_root_pgt(cpu);
-+
- order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
- free_xenheap_pages(per_cpu(gdt_table, cpu), order);
-
-@@ -719,6 +905,9 @@ static int cpu_smpboot_alloc(unsigned int cpu)
- set_ist(&idt_tables[cpu][TRAP_nmi], IST_NONE);
- set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
-
-+ if ( setup_cpu_root_pgt(cpu) )
-+ goto oom;
-+
- for ( stub_page = 0, i = cpu & ~(STUBS_PER_PAGE - 1);
- i < nr_cpu_ids && i <= (cpu | (STUBS_PER_PAGE - 1)); ++i )
- if ( cpu_online(i) && cpu_to_node(i) == node )
-@@ -773,6 +962,8 @@ static struct notifier_block cpu_smpboot_nfb = {
-
- void __init smp_prepare_cpus(unsigned int max_cpus)
- {
-+ int rc;
-+
- register_cpu_notifier(&cpu_smpboot_nfb);
-
- mtrr_aps_sync_begin();
-@@ -786,6 +977,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
-
- stack_base[0] = stack_start;
-
-+ rc = setup_cpu_root_pgt(0);
-+ if ( rc )
-+ panic("Error %d setting up PV root page table\n", rc);
-+ get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
-+
- set_nr_sockets();
-
- socket_cpumask = xzalloc_array(cpumask_t *, nr_sockets);
-@@ -850,6 +1046,8 @@ void __init smp_prepare_boot_cpu(void)
- {
- cpumask_set_cpu(smp_processor_id(), &cpu_online_map);
- cpumask_set_cpu(smp_processor_id(), &cpu_present_map);
-+
-+ get_cpu_info()->xen_cr3 = 0;
- }
-
- static void
-diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
-index a3ae7a475f..4f2ba28520 100644
---- a/xen/arch/x86/x86_64/asm-offsets.c
-+++ b/xen/arch/x86/x86_64/asm-offsets.c
-@@ -137,6 +137,8 @@ void __dummy__(void)
- OFFSET(CPUINFO_processor_id, struct cpu_info, processor_id);
- OFFSET(CPUINFO_current_vcpu, struct cpu_info, current_vcpu);
- OFFSET(CPUINFO_cr4, struct cpu_info, cr4);
-+ OFFSET(CPUINFO_xen_cr3, struct cpu_info, xen_cr3);
-+ OFFSET(CPUINFO_pv_cr3, struct cpu_info, pv_cr3);
- DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
- BLANK();
-
-diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
-index 7ee01597a3..f7e53fb3cb 100644
---- a/xen/arch/x86/x86_64/compat/entry.S
-+++ b/xen/arch/x86/x86_64/compat/entry.S
-@@ -270,6 +270,17 @@ ENTRY(cstar_enter)
- pushq $0
- movl $TRAP_syscall, 4(%rsp)
- SAVE_ALL
-+
-+ GET_STACK_END(bx)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
-+ neg %rcx
-+ jz .Lcstar_cr3_okay
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+ neg %rcx
-+ write_cr3 rcx, rdi, rsi
-+ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+.Lcstar_cr3_okay:
-+
- GET_CURRENT(bx)
- movq VCPU_domain(%rbx),%rcx
- cmpb $0,DOMAIN_is_32bit_pv(%rcx)
-diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
-index cebb1e4f4f..d63e734bb3 100644
---- a/xen/arch/x86/x86_64/entry.S
-+++ b/xen/arch/x86/x86_64/entry.S
-@@ -36,6 +36,32 @@ ENTRY(switch_to_kernel)
- /* %rbx: struct vcpu, interrupts disabled */
- restore_all_guest:
- ASSERT_INTERRUPTS_DISABLED
-+
-+ /* Copy guest mappings and switch to per-CPU root page table. */
-+ mov %cr3, %r9
-+ GET_STACK_END(dx)
-+ mov STACK_CPUINFO_FIELD(pv_cr3)(%rdx), %rdi
-+ movabs $PADDR_MASK & PAGE_MASK, %rsi
-+ movabs $DIRECTMAP_VIRT_START, %rcx
-+ mov %rdi, %rax
-+ and %rsi, %rdi
-+ and %r9, %rsi
-+ add %rcx, %rdi
-+ add %rcx, %rsi
-+ mov $ROOT_PAGETABLE_FIRST_XEN_SLOT, %ecx
-+ mov root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rsi), %r8
-+ mov %r8, root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rdi)
-+ rep movsq
-+ mov $ROOT_PAGETABLE_ENTRIES - \
-+ ROOT_PAGETABLE_LAST_XEN_SLOT - 1, %ecx
-+ sub $(ROOT_PAGETABLE_FIRST_XEN_SLOT - \
-+ ROOT_PAGETABLE_LAST_XEN_SLOT - 1) * 8, %rsi
-+ sub $(ROOT_PAGETABLE_FIRST_XEN_SLOT - \
-+ ROOT_PAGETABLE_LAST_XEN_SLOT - 1) * 8, %rdi
-+ rep movsq
-+ mov %r9, STACK_CPUINFO_FIELD(xen_cr3)(%rdx)
-+ write_cr3 rax, rdi, rsi
-+
- RESTORE_ALL
- testw $TRAP_syscall,4(%rsp)
- jz iret_exit_to_guest
-@@ -70,6 +96,22 @@ iret_exit_to_guest:
- ALIGN
- /* No special register assumptions. */
- restore_all_xen:
-+ /*
-+ * Check whether we need to switch to the per-CPU page tables, in
-+ * case we return to late PV exit code (from an NMI or #MC).
-+ */
-+ GET_STACK_END(ax)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rax), %rdx
-+ mov STACK_CPUINFO_FIELD(pv_cr3)(%rax), %rax
-+ test %rdx, %rdx
-+ /*
-+ * Ideally the condition would be "nsz", but such doesn't exist,
-+ * so "g" will have to do.
-+ */
-+UNLIKELY_START(g, exit_cr3)
-+ write_cr3 rax, rdi, rsi
-+UNLIKELY_END(exit_cr3)
-+
- RESTORE_ALL adj=8
- iretq
-
-@@ -99,7 +141,18 @@ ENTRY(lstar_enter)
- pushq $0
- movl $TRAP_syscall, 4(%rsp)
- SAVE_ALL
-- GET_CURRENT(bx)
-+
-+ GET_STACK_END(bx)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
-+ neg %rcx
-+ jz .Llstar_cr3_okay
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+ neg %rcx
-+ write_cr3 rcx, r11, r12
-+ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+.Llstar_cr3_okay:
-+
-+ __GET_CURRENT(bx)
- testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
- jz switch_to_kernel
-
-@@ -248,7 +301,18 @@ GLOBAL(sysenter_eflags_saved)
- pushq $0
- movl $TRAP_syscall, 4(%rsp)
- SAVE_ALL
-- GET_CURRENT(bx)
-+
-+ GET_STACK_END(bx)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
-+ neg %rcx
-+ jz .Lsyse_cr3_okay
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+ neg %rcx
-+ write_cr3 rcx, rdi, rsi
-+ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+.Lsyse_cr3_okay:
-+
-+ __GET_CURRENT(bx)
- cmpb $0,VCPU_sysenter_disables_events(%rbx)
- movq VCPU_sysenter_addr(%rbx),%rax
- setne %cl
-@@ -284,13 +348,23 @@ ENTRY(int80_direct_trap)
- movl $0x80, 4(%rsp)
- SAVE_ALL
-
-+ GET_STACK_END(bx)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
-+ neg %rcx
-+ jz .Lint80_cr3_okay
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+ neg %rcx
-+ write_cr3 rcx, rdi, rsi
-+ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
-+.Lint80_cr3_okay:
-+
- cmpb $0,untrusted_msi(%rip)
- UNLIKELY_START(ne, msi_check)
- movl $0x80,%edi
- call check_for_unexpected_msi
- UNLIKELY_END(msi_check)
-
-- GET_CURRENT(bx)
-+ __GET_CURRENT(bx)
-
- /* Check that the callback is non-null. */
- leaq VCPU_int80_bounce(%rbx),%rdx
-@@ -441,9 +515,27 @@ ENTRY(dom_crash_sync_extable)
-
- ENTRY(common_interrupt)
- SAVE_ALL CLAC
-+
-+ GET_STACK_END(14)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
-+ mov %rcx, %r15
-+ neg %rcx
-+ jz .Lintr_cr3_okay
-+ jns .Lintr_cr3_load
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+ neg %rcx
-+.Lintr_cr3_load:
-+ write_cr3 rcx, rdi, rsi
-+ xor %ecx, %ecx
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+ testb $3, UREGS_cs(%rsp)
-+ cmovnz %rcx, %r15
-+.Lintr_cr3_okay:
-+
- CR4_PV32_RESTORE
- movq %rsp,%rdi
- callq do_IRQ
-+ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
- jmp ret_from_intr
-
- /* No special register assumptions. */
-@@ -461,6 +553,23 @@ ENTRY(page_fault)
- /* No special register assumptions. */
- GLOBAL(handle_exception)
- SAVE_ALL CLAC
-+
-+ GET_STACK_END(14)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
-+ mov %rcx, %r15
-+ neg %rcx
-+ jz .Lxcpt_cr3_okay
-+ jns .Lxcpt_cr3_load
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+ neg %rcx
-+.Lxcpt_cr3_load:
-+ write_cr3 rcx, rdi, rsi
-+ xor %ecx, %ecx
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+ testb $3, UREGS_cs(%rsp)
-+ cmovnz %rcx, %r15
-+.Lxcpt_cr3_okay:
-+
- handle_exception_saved:
- GET_CURRENT(bx)
- testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
-@@ -525,6 +634,7 @@ handle_exception_saved:
- leaq exception_table(%rip),%rdx
- PERFC_INCR(exceptions, %rax, %rbx)
- callq *(%rdx,%rax,8)
-+ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
- testb $3,UREGS_cs(%rsp)
- jz restore_all_xen
- leaq VCPU_trap_bounce(%rbx),%rdx
-@@ -557,6 +667,7 @@ exception_with_ints_disabled:
- rep; movsq # make room for ec/ev
- 1: movq UREGS_error_code(%rsp),%rax # ec/ev
- movq %rax,UREGS_kernel_sizeof(%rsp)
-+ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
- jmp restore_all_xen # return to fixup code
-
- /* No special register assumptions. */
-@@ -634,6 +745,17 @@ ENTRY(double_fault)
- movl $TRAP_double_fault,4(%rsp)
- /* Set AC to reduce chance of further SMAP faults */
- SAVE_ALL STAC
-+
-+ GET_STACK_END(bx)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rbx
-+ test %rbx, %rbx
-+ jz .Ldblf_cr3_okay
-+ jns .Ldblf_cr3_load
-+ neg %rbx
-+.Ldblf_cr3_load:
-+ write_cr3 rbx, rdi, rsi
-+.Ldblf_cr3_okay:
-+
- movq %rsp,%rdi
- call do_double_fault
- BUG /* do_double_fault() shouldn't return. */
-@@ -652,10 +774,28 @@ ENTRY(nmi)
- movl $TRAP_nmi,4(%rsp)
- handle_ist_exception:
- SAVE_ALL CLAC
-+
-+ GET_STACK_END(14)
-+ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
-+ mov %rcx, %r15
-+ neg %rcx
-+ jz .List_cr3_okay
-+ jns .List_cr3_load
-+ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+ neg %rcx
-+.List_cr3_load:
-+ write_cr3 rcx, rdi, rsi
-+ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
-+.List_cr3_okay:
-+
- CR4_PV32_RESTORE
- testb $3,UREGS_cs(%rsp)
- jz 1f
-- /* Interrupted guest context. Copy the context to stack bottom. */
-+ /*
-+ * Interrupted guest context. Clear the restore value for xen_cr3
-+ * and copy the context to stack bottom.
-+ */
-+ xor %r15, %r15
- GET_CPUINFO_FIELD(guest_cpu_user_regs,di)
- movq %rsp,%rsi
- movl $UREGS_kernel_sizeof/8,%ecx
-@@ -665,6 +805,7 @@ handle_ist_exception:
- movzbl UREGS_entry_vector(%rsp),%eax
- leaq exception_table(%rip),%rdx
- callq *(%rdx,%rax,8)
-+ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
- cmpb $TRAP_nmi,UREGS_entry_vector(%rsp)
- jne ret_from_intr
-
-diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
-index 6e5c079ad8..6cfdaa1aa0 100644
---- a/xen/include/asm-x86/asm_defns.h
-+++ b/xen/include/asm-x86/asm_defns.h
-@@ -93,9 +93,30 @@ void ret_from_intr(void);
- UNLIKELY_DONE(mp, tag); \
- __UNLIKELY_END(tag)
-
-+ .equ .Lrax, 0
-+ .equ .Lrcx, 1
-+ .equ .Lrdx, 2
-+ .equ .Lrbx, 3
-+ .equ .Lrsp, 4
-+ .equ .Lrbp, 5
-+ .equ .Lrsi, 6
-+ .equ .Lrdi, 7
-+ .equ .Lr8, 8
-+ .equ .Lr9, 9
-+ .equ .Lr10, 10
-+ .equ .Lr11, 11
-+ .equ .Lr12, 12
-+ .equ .Lr13, 13
-+ .equ .Lr14, 14
-+ .equ .Lr15, 15
-+
- #define STACK_CPUINFO_FIELD(field) (1 - CPUINFO_sizeof + CPUINFO_##field)
- #define GET_STACK_END(reg) \
-+ .if .Lr##reg > 8; \
-+ movq $STACK_SIZE-1, %r##reg; \
-+ .else; \
- movl $STACK_SIZE-1, %e##reg; \
-+ .endif; \
- orq %rsp, %r##reg
-
- #define GET_CPUINFO_FIELD(field, reg) \
-@@ -177,6 +198,15 @@ void ret_from_intr(void);
- #define ASM_STAC ASM_AC(STAC)
- #define ASM_CLAC ASM_AC(CLAC)
-
-+.macro write_cr3 val:req, tmp1:req, tmp2:req
-+ mov %cr4, %\tmp1
-+ mov %\tmp1, %\tmp2
-+ and $~X86_CR4_PGE, %\tmp1
-+ mov %\tmp1, %cr4
-+ mov %\val, %cr3
-+ mov %\tmp2, %cr4
-+.endm
-+
- #define CR4_PV32_RESTORE \
- 667: ASM_NOP5; \
- .pushsection .altinstr_replacement, "ax"; \
-diff --git a/xen/include/asm-x86/current.h b/xen/include/asm-x86/current.h
-index e6587e684c..397fa4c38f 100644
---- a/xen/include/asm-x86/current.h
-+++ b/xen/include/asm-x86/current.h
-@@ -42,6 +42,18 @@ struct cpu_info {
- struct vcpu *current_vcpu;
- unsigned long per_cpu_offset;
- unsigned long cr4;
-+ /*
-+ * Of the two following fields the latter is being set to the CR3 value
-+ * to be used on the given pCPU for loading whenever 64-bit PV guest
-+ * context is being entered. The value never changes once set.
-+ * The former is the value to restore when re-entering Xen, if any. IOW
-+ * its value being zero means there's nothing to restore. However, its
-+ * value can also be negative, indicating to the exit-to-Xen code that
-+ * restoring is not necessary, but allowing any nested entry code paths
-+ * to still know the value to put back into CR3.
-+ */
-+ unsigned long xen_cr3;
-+ unsigned long pv_cr3;
- /* get_stack_bottom() must be 16-byte aligned */
- };
-
-diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
-index ccd406a3fe..9906f38f2d 100644
---- a/xen/include/asm-x86/processor.h
-+++ b/xen/include/asm-x86/processor.h
-@@ -517,6 +517,7 @@ extern idt_entry_t idt_table[];
- extern idt_entry_t *idt_tables[];
-
- DECLARE_PER_CPU(struct tss_struct, init_tss);
-+DECLARE_PER_CPU(root_pgentry_t *, root_pgt);
-
- extern void init_int80_direct_trap(struct vcpu *v);
-
-diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
-index 589f22552e..afc77c3237 100644
---- a/xen/include/asm-x86/x86_64/page.h
-+++ b/xen/include/asm-x86/x86_64/page.h
-@@ -25,8 +25,8 @@
- /* These are architectural limits. Current CPUs support only 40-bit phys. */
- #define PADDR_BITS 52
- #define VADDR_BITS 48
--#define PADDR_MASK ((1UL << PADDR_BITS)-1)
--#define VADDR_MASK ((1UL << VADDR_BITS)-1)
-+#define PADDR_MASK ((_AC(1,UL) << PADDR_BITS) - 1)
-+#define VADDR_MASK ((_AC(1,UL) << VADDR_BITS) - 1)
-
- #define is_canonical_address(x) (((long)(x) >> 47) == ((long)(x) >> 63))
-
-@@ -117,6 +117,7 @@ typedef l4_pgentry_t root_pgentry_t;
- : (((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT) || \
- ((_s) > ROOT_PAGETABLE_LAST_XEN_SLOT)))
-
-+#define root_table_offset l4_table_offset
- #define root_get_pfn l4e_get_pfn
- #define root_get_flags l4e_get_flags
- #define root_get_intpte l4e_get_intpte
---
-2.15.1
-
Index: head/emulators/xen-kernel/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
+++ head/emulators/xen-kernel/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
@@ -1,76 +0,0 @@
-From 58e028648e3bc831b1b60a39b7f1661538fa6a34 Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Tue, 23 Jan 2018 16:05:17 +0000
-Subject: [PATCH] x86/compat: fix compilation errors with clang 6
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The following errors are generated when compiling Xen with clang 6:
-
-In file included from x86_64/asm-offsets.c:9:
-In file included from /root/src/xen/xen/include/xen/sched.h:8:
-In file included from /root/src/xen/xen/include/xen/shared.h:6:
-In file included from /root/src/xen/xen/include/compat/arch-x86/../xen.h:9:
-/root/src/xen/xen/include/compat/arch-x86/xen.h:10:10: error: the current #pragma pack aligment
- value is modified in the included file [-Werror,-Wpragma-pack]
-#include "xen-x86_32.h"
- ^
-/root/src/xen/xen/include/compat/arch-x86/xen-x86_32.h:40:9: note: previous '#pragma pack'
- directive that modifies alignment is here
-#pragma pack()
- ^
-In file included from x86_64/asm-offsets.c:9:
-In file included from /root/src/xen/xen/include/xen/sched.h:8:
-In file included from /root/src/xen/xen/include/xen/shared.h:6:
-/root/src/xen/xen/include/compat/arch-x86/../xen.h:9:10: error: the current #pragma pack aligment
- value is modified in the included file [-Werror,-Wpragma-pack]
-#include "arch-x86/xen.h"
- ^
-/root/src/xen/xen/include/compat/arch-x86/xen.h:71:9: note: previous '#pragma pack' directive that
- modifies alignment is here
-#pragma pack()
- ^
-2 errors generated.
-
-Fix this by using pragma push/pop in order to store the current pragma
-value in the compiler stack and later restoring it when using clang.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
----
-Cc: Andrew Cooper <andrew.cooper3@citrix.com>
-Cc: George Dunlap <George.Dunlap@eu.citrix.com>
-Cc: Ian Jackson <ian.jackson@eu.citrix.com>
-Cc: Jan Beulich <jbeulich@suse.com>
-Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-Cc: Stefano Stabellini <sstabellini@kernel.org>
-Cc: Tim Deegan <tim@xen.org>
-Cc: Wei Liu <wei.liu2@citrix.com>
----
-Changes since v1:
- - Only use push/pop with clang.
----
- xen/include/Makefile | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/xen/include/Makefile b/xen/include/Makefile
-index 268bc9d6ba..eeae942903 100644
---- a/xen/include/Makefile
-+++ b/xen/include/Makefile
-@@ -34,8 +34,13 @@ cppflags-y := -include public/xen-compat.h
- cppflags-$(CONFIG_X86) += -m32
-
- # 8-byte types are 4-byte aligned on x86_32 ...
-+ifeq ($(clang),y)
-+prefix-$(CONFIG_X86) := \#pragma pack(push, 4)
-+suffix-$(CONFIG_X86) := \#pragma pack(pop)
-+else
- prefix-$(CONFIG_X86) := \#pragma pack(4)
- suffix-$(CONFIG_X86) := \#pragma pack()
-+endif
-
- endif
-
---
-2.15.1
-
Index: head/emulators/xen-kernel/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
+++ head/emulators/xen-kernel/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
@@ -1,27 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: don't allow MSI pIRQ mapping on unowned device
-
-MSI setup should be permitted only for existing devices owned by the
-respective guest (the operation may still be carried out by the domain
-controlling that guest).
-
-This is part of XSA-237.
-
-Reported-by: HW42 <hw42@ipsumj.de>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/irq.c
-+++ b/xen/arch/x86/irq.c
-@@ -1964,7 +1964,10 @@ int map_domain_pirq(
- if ( !cpu_has_apic )
- goto done;
-
-- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
-+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
-+ if ( !pdev )
-+ goto done;
-+
- ret = pci_enable_msi(msi, &msi_desc);
- if ( ret )
- {
Index: head/emulators/xen-kernel/files/0001-x86-drop-unneeded-__packed-attributes.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-drop-unneeded-__packed-attributes.patch
+++ head/emulators/xen-kernel/files/0001-x86-drop-unneeded-__packed-attributes.patch
@@ -1,122 +0,0 @@
-From 7de7d07d47cc389bc341f5524ea8415c3c78e378 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
-Date: Fri, 10 Mar 2017 01:05:51 +0900
-Subject: [PATCH 1/2] x86: drop unneeded __packed attributes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There where a couple of unneeded packed attributes in several x86-specific
-structures, that are obviously aligned. The only non-trivial one is
-vmcb_struct, which has been checked to have the same layout with and without
-the packed attribute using pahole. In that case add a build-time size check to
-be on the safe side.
-
-No functional change is expected as a result of this commit.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
----
- xen/arch/x86/hvm/svm/vmcb.c | 3 +++
- xen/arch/x86/x86_emulate/x86_emulate.h | 4 ++--
- xen/include/asm-x86/hvm/svm/vmcb.h | 12 ++++++------
- 3 files changed, 11 insertions(+), 8 deletions(-)
-
-diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
-index 9ea014f..f982fc9 100644
---- a/xen/arch/x86/hvm/svm/vmcb.c
-+++ b/xen/arch/x86/hvm/svm/vmcb.c
-@@ -72,6 +72,9 @@ static int construct_vmcb(struct vcpu *v)
- struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
- struct vmcb_struct *vmcb = arch_svm->vmcb;
-
-+ /* Build-time check of the size of VMCB AMD structure. */
-+ BUILD_BUG_ON(sizeof(*vmcb) != PAGE_SIZE);
-+
- vmcb->_general1_intercepts =
- GENERAL1_INTERCEPT_INTR | GENERAL1_INTERCEPT_NMI |
- GENERAL1_INTERCEPT_SMI | GENERAL1_INTERCEPT_INIT |
-diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
-index 17c86f3..bbdf16a 100644
---- a/xen/arch/x86/x86_emulate/x86_emulate.h
-+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
-@@ -71,7 +71,7 @@ enum x86_swint_emulation {
- * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
- * segment descriptor. It happens to match the format of an AMD SVM VMCB.
- */
--typedef union __packed segment_attributes {
-+typedef union segment_attributes {
- uint16_t bytes;
- struct
- {
-@@ -91,7 +91,7 @@ typedef union __packed segment_attributes {
- * Full state of a segment register (visible and hidden portions).
- * Again, this happens to match the format of an AMD SVM VMCB.
- */
--struct __packed segment_register {
-+struct segment_register {
- uint16_t sel;
- segment_attributes_t attr;
- uint32_t limit;
-diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
-index bad2382..a3cd1b1 100644
---- a/xen/include/asm-x86/hvm/svm/vmcb.h
-+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
-@@ -308,7 +308,7 @@ enum VMEXIT_EXITCODE
- /* Definition of segment state is borrowed by the generic HVM code. */
- typedef struct segment_register svm_segment_register_t;
-
--typedef union __packed
-+typedef union
- {
- u64 bytes;
- struct
-@@ -322,7 +322,7 @@ typedef union __packed
- } fields;
- } eventinj_t;
-
--typedef union __packed
-+typedef union
- {
- u64 bytes;
- struct
-@@ -340,7 +340,7 @@ typedef union __packed
- } fields;
- } vintr_t;
-
--typedef union __packed
-+typedef union
- {
- u64 bytes;
- struct
-@@ -357,7 +357,7 @@ typedef union __packed
- } fields;
- } ioio_info_t;
-
--typedef union __packed
-+typedef union
- {
- u64 bytes;
- struct
-@@ -366,7 +366,7 @@ typedef union __packed
- } fields;
- } lbrctrl_t;
-
--typedef union __packed
-+typedef union
- {
- uint32_t bytes;
- struct
-@@ -401,7 +401,7 @@ typedef union __packed
- #define IOPM_SIZE (12 * 1024)
- #define MSRPM_SIZE (8 * 1024)
-
--struct __packed vmcb_struct {
-+struct vmcb_struct {
- u32 _cr_intercepts; /* offset 0x00 - cleanbit 0 */
- u32 _dr_intercepts; /* offset 0x04 - cleanbit 0 */
- u32 _exception_intercepts; /* offset 0x08 - cleanbit 0 */
---
-2.10.1 (Apple Git-78)
-
Index: head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
+++ head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
@@ -1,399 +0,0 @@
-From 0e6c6fc449000d97f9fa87ed1fbe23f0cf21406b Mon Sep 17 00:00:00 2001
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Date: Wed, 17 Jan 2018 17:22:34 +0100
-Subject: [PATCH] x86/entry: Remove support for partial cpu_user_regs frames
-
-Save all GPRs on entry to Xen.
-
-The entry_int82() path is via a DPL1 gate, only usable by 32bit PV guests, so
-can get away with only saving the 32bit registers. All other entrypoints can
-be reached from 32 or 64bit contexts.
-
-This is part of XSA-254.
-
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Wei Liu <wei.liu2@citrix.com>
-Acked-by: Jan Beulich <jbeulich@suse.com>
-master commit: f9eb74789af77e985ae653193f3622263499f674
-master date: 2018-01-05 19:57:07 +0000
----
- tools/tests/x86_emulator/x86_emulate.c | 1 -
- xen/arch/x86/domain.c | 1 -
- xen/arch/x86/traps.c | 2 -
- xen/arch/x86/x86_64/compat/entry.S | 7 ++-
- xen/arch/x86/x86_64/entry.S | 12 ++--
- xen/arch/x86/x86_64/traps.c | 13 ++--
- xen/arch/x86/x86_emulate.c | 1 -
- xen/arch/x86/x86_emulate/x86_emulate.c | 8 +--
- xen/common/wait.c | 1 -
- xen/include/asm-x86/asm_defns.h | 107 +++------------------------------
- 10 files changed, 26 insertions(+), 127 deletions(-)
-
-diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
-index 10e3f61baa..c12527a50b 100644
---- a/tools/tests/x86_emulator/x86_emulate.c
-+++ b/tools/tests/x86_emulator/x86_emulate.c
-@@ -24,7 +24,6 @@ typedef bool bool_t;
- #endif
-
- #define cpu_has_amd_erratum(nr) 0
--#define mark_regs_dirty(r) ((void)(r))
-
- #define __packed __attribute__((packed))
-
-diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
-index ceeadabbfd..6539b75fa7 100644
---- a/xen/arch/x86/domain.c
-+++ b/xen/arch/x86/domain.c
-@@ -148,7 +148,6 @@ static void noreturn continue_idle_domain(struct vcpu *v)
- static void noreturn continue_nonidle_domain(struct vcpu *v)
- {
- check_wakeup_from_wait();
-- mark_regs_dirty(guest_cpu_user_regs());
- reset_stack_and_jump(ret_from_intr);
- }
-
-diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
-index 05b4b0811d..0928c9b235 100644
---- a/xen/arch/x86/traps.c
-+++ b/xen/arch/x86/traps.c
-@@ -2456,7 +2456,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
- goto fail;
- if ( admin_io_okay(port, op_bytes, currd) )
- {
-- mark_regs_dirty(regs);
- io_emul(regs);
- }
- else
-@@ -2486,7 +2485,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
- goto fail;
- if ( admin_io_okay(port, op_bytes, currd) )
- {
-- mark_regs_dirty(regs);
- io_emul(regs);
- if ( (op_bytes == 1) && pv_post_outb_hook )
- pv_post_outb_hook(port, regs->eax);
-diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
-index 794bb44266..7ee01597a3 100644
---- a/xen/arch/x86/x86_64/compat/entry.S
-+++ b/xen/arch/x86/x86_64/compat/entry.S
-@@ -15,7 +15,8 @@
- ENTRY(compat_hypercall)
- ASM_CLAC
- pushq $0
-- SAVE_VOLATILE type=TRAP_syscall compat=1
-+ movl $TRAP_syscall, 4(%rsp)
-+ SAVE_ALL compat=1 /* DPL1 gate, restricted to 32bit PV guests only. */
- CR4_PV32_RESTORE
-
- cmpb $0,untrusted_msi(%rip)
-@@ -127,7 +128,6 @@ compat_test_guest_events:
- /* %rbx: struct vcpu */
- compat_process_softirqs:
- sti
-- andl $~TRAP_regs_partial,UREGS_entry_vector(%rsp)
- call do_softirq
- jmp compat_test_all_events
-
-@@ -268,7 +268,8 @@ ENTRY(cstar_enter)
- pushq $FLAT_USER_CS32
- pushq %rcx
- pushq $0
-- SAVE_VOLATILE TRAP_syscall
-+ movl $TRAP_syscall, 4(%rsp)
-+ SAVE_ALL
- GET_CURRENT(bx)
- movq VCPU_domain(%rbx),%rcx
- cmpb $0,DOMAIN_is_32bit_pv(%rcx)
-diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
-index 708d9b9402..cebb1e4f4f 100644
---- a/xen/arch/x86/x86_64/entry.S
-+++ b/xen/arch/x86/x86_64/entry.S
-@@ -97,7 +97,8 @@ ENTRY(lstar_enter)
- pushq $FLAT_KERNEL_CS64
- pushq %rcx
- pushq $0
-- SAVE_VOLATILE TRAP_syscall
-+ movl $TRAP_syscall, 4(%rsp)
-+ SAVE_ALL
- GET_CURRENT(bx)
- testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
- jz switch_to_kernel
-@@ -192,7 +193,6 @@ test_guest_events:
- /* %rbx: struct vcpu */
- process_softirqs:
- sti
-- SAVE_PRESERVED
- call do_softirq
- jmp test_all_events
-
-@@ -246,7 +246,8 @@ GLOBAL(sysenter_eflags_saved)
- pushq $3 /* ring 3 null cs */
- pushq $0 /* null rip */
- pushq $0
-- SAVE_VOLATILE TRAP_syscall
-+ movl $TRAP_syscall, 4(%rsp)
-+ SAVE_ALL
- GET_CURRENT(bx)
- cmpb $0,VCPU_sysenter_disables_events(%rbx)
- movq VCPU_sysenter_addr(%rbx),%rax
-@@ -263,7 +264,6 @@ UNLIKELY_END(sysenter_nt_set)
- leal (,%rcx,TBF_INTERRUPT),%ecx
- UNLIKELY_START(z, sysenter_gpf)
- movq VCPU_trap_ctxt(%rbx),%rsi
-- SAVE_PRESERVED
- movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
- movl %eax,TRAPBOUNCE_error_code(%rdx)
- movq TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%rax
-@@ -281,7 +281,8 @@ UNLIKELY_END(sysenter_gpf)
- ENTRY(int80_direct_trap)
- ASM_CLAC
- pushq $0
-- SAVE_VOLATILE 0x80
-+ movl $0x80, 4(%rsp)
-+ SAVE_ALL
-
- cmpb $0,untrusted_msi(%rip)
- UNLIKELY_START(ne, msi_check)
-@@ -309,7 +310,6 @@ int80_slow_path:
- * IDT entry with DPL==0.
- */
- movl $((0x80 << 3) | X86_XEC_IDT),UREGS_error_code(%rsp)
-- SAVE_PRESERVED
- movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
- /* A GPF wouldn't have incremented the instruction pointer. */
- subq $2,UREGS_rip(%rsp)
-diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
-index 22816100fd..bf8dfcbdee 100644
---- a/xen/arch/x86/x86_64/traps.c
-+++ b/xen/arch/x86/x86_64/traps.c
-@@ -81,15 +81,10 @@ static void _show_registers(
- regs->rbp, regs->rsp, regs->r8);
- printk("r9: %016lx r10: %016lx r11: %016lx\n",
- regs->r9, regs->r10, regs->r11);
-- if ( !(regs->entry_vector & TRAP_regs_partial) )
-- {
-- printk("r12: %016lx r13: %016lx r14: %016lx\n",
-- regs->r12, regs->r13, regs->r14);
-- printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
-- regs->r15, crs[0], crs[4]);
-- }
-- else
-- printk("cr0: %016lx cr4: %016lx\n", crs[0], crs[4]);
-+ printk("r12: %016lx r13: %016lx r14: %016lx\n",
-+ regs->r12, regs->r13, regs->r14);
-+ printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
-+ regs->r15, crs[0], crs[4]);
- printk("cr3: %016lx cr2: %016lx\n", crs[3], crs[2]);
- printk("fsb: %016lx gsb: %016lx gss: %016lx\n",
- crs[5], crs[6], crs[7]);
-diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
-index 28132b5dbc..43730026c2 100644
---- a/xen/arch/x86/x86_emulate.c
-+++ b/xen/arch/x86/x86_emulate.c
-@@ -11,7 +11,6 @@
-
- #include <xen/domain_page.h>
- #include <asm/x86_emulate.h>
--#include <asm/asm_defns.h> /* mark_regs_dirty() */
- #include <asm/processor.h> /* current_cpu_info */
- #include <asm/amd.h> /* cpu_has_amd_erratum() */
-
-diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
-index 4ee3df9247..fcfe9f7de7 100644
---- a/xen/arch/x86/x86_emulate/x86_emulate.c
-+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
-@@ -1424,10 +1424,10 @@ decode_register(
- case 9: p = &regs->r9; break;
- case 10: p = &regs->r10; break;
- case 11: p = &regs->r11; break;
-- case 12: mark_regs_dirty(regs); p = &regs->r12; break;
-- case 13: mark_regs_dirty(regs); p = &regs->r13; break;
-- case 14: mark_regs_dirty(regs); p = &regs->r14; break;
-- case 15: mark_regs_dirty(regs); p = &regs->r15; break;
-+ case 12: p = &regs->r12; break;
-+ case 13: p = &regs->r13; break;
-+ case 14: p = &regs->r14; break;
-+ case 15: p = &regs->r15; break;
- #endif
- default: BUG(); p = NULL; break;
- }
-diff --git a/xen/common/wait.c b/xen/common/wait.c
-index 4ac98c07fe..398f653174 100644
---- a/xen/common/wait.c
-+++ b/xen/common/wait.c
-@@ -128,7 +128,6 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
- unsigned long dummy;
- u32 entry_vector = cpu_info->guest_cpu_user_regs.entry_vector;
-
-- cpu_info->guest_cpu_user_regs.entry_vector &= ~TRAP_regs_partial;
- ASSERT(wqv->esp == 0);
-
- /* Save current VCPU affinity; force wakeup on *this* CPU only. */
-diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
-index 279d70298f..6e5c079ad8 100644
---- a/xen/include/asm-x86/asm_defns.h
-+++ b/xen/include/asm-x86/asm_defns.h
-@@ -17,15 +17,6 @@
- void ret_from_intr(void);
- #endif
-
--#ifdef CONFIG_FRAME_POINTER
--/* Indicate special exception stack frame by inverting the frame pointer. */
--#define SETUP_EXCEPTION_FRAME_POINTER(offs) \
-- leaq offs(%rsp),%rbp; \
-- notq %rbp
--#else
--#define SETUP_EXCEPTION_FRAME_POINTER(offs)
--#endif
--
- #ifndef NDEBUG
- #define ASSERT_INTERRUPT_STATUS(x, msg) \
- pushf; \
-@@ -42,31 +33,6 @@ void ret_from_intr(void);
- #define ASSERT_INTERRUPTS_DISABLED \
- ASSERT_INTERRUPT_STATUS(z, "INTERRUPTS DISABLED")
-
--/*
-- * This flag is set in an exception frame when registers R12-R15 did not get
-- * saved.
-- */
--#define _TRAP_regs_partial 16
--#define TRAP_regs_partial (1 << _TRAP_regs_partial)
--/*
-- * This flag gets set in an exception frame when registers R12-R15 possibly
-- * get modified from their originally saved values and hence need to be
-- * restored even if the normal call flow would restore register values.
-- *
-- * The flag being set implies _TRAP_regs_partial to be unset. Restoring
-- * R12-R15 thus is
-- * - required when this flag is set,
-- * - safe when _TRAP_regs_partial is unset.
-- */
--#define _TRAP_regs_dirty 17
--#define TRAP_regs_dirty (1 << _TRAP_regs_dirty)
--
--#define mark_regs_dirty(r) ({ \
-- struct cpu_user_regs *r__ = (r); \
-- ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
-- r__->entry_vector |= TRAP_regs_dirty; \
--})
--
- #ifdef __ASSEMBLY__
- # define _ASM_EX(p) p-.
- #else
-@@ -236,7 +202,7 @@ static always_inline void stac(void)
- #endif
-
- #ifdef __ASSEMBLY__
--.macro SAVE_ALL op
-+.macro SAVE_ALL op, compat=0
- .ifeqs "\op", "CLAC"
- ASM_CLAC
- .else
-@@ -255,40 +221,6 @@ static always_inline void stac(void)
- movq %rdx,UREGS_rdx(%rsp)
- movq %rcx,UREGS_rcx(%rsp)
- movq %rax,UREGS_rax(%rsp)
-- movq %r8,UREGS_r8(%rsp)
-- movq %r9,UREGS_r9(%rsp)
-- movq %r10,UREGS_r10(%rsp)
-- movq %r11,UREGS_r11(%rsp)
-- movq %rbx,UREGS_rbx(%rsp)
-- movq %rbp,UREGS_rbp(%rsp)
-- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
-- movq %r12,UREGS_r12(%rsp)
-- movq %r13,UREGS_r13(%rsp)
-- movq %r14,UREGS_r14(%rsp)
-- movq %r15,UREGS_r15(%rsp)
--.endm
--
--/*
-- * Save all registers not preserved by C code or used in entry/exit code. Mark
-- * the frame as partial.
-- *
-- * @type: exception type
-- * @compat: R8-R15 don't need saving, and the frame nevertheless is complete
-- */
--.macro SAVE_VOLATILE type compat=0
--.if \compat
-- movl $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
--.else
-- movl $\type|TRAP_regs_partial,\
-- UREGS_entry_vector-UREGS_error_code(%rsp)
--.endif
-- addq $-(UREGS_error_code-UREGS_r15),%rsp
-- cld
-- movq %rdi,UREGS_rdi(%rsp)
-- movq %rsi,UREGS_rsi(%rsp)
-- movq %rdx,UREGS_rdx(%rsp)
-- movq %rcx,UREGS_rcx(%rsp)
-- movq %rax,UREGS_rax(%rsp)
- .if !\compat
- movq %r8,UREGS_r8(%rsp)
- movq %r9,UREGS_r9(%rsp)
-@@ -297,20 +229,17 @@ static always_inline void stac(void)
- .endif
- movq %rbx,UREGS_rbx(%rsp)
- movq %rbp,UREGS_rbp(%rsp)
-- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
--.endm
--
--/*
-- * Complete a frame potentially only partially saved.
-- */
--.macro SAVE_PRESERVED
-- btrl $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
-- jnc 987f
-+#ifdef CONFIG_FRAME_POINTER
-+/* Indicate special exception stack frame by inverting the frame pointer. */
-+ leaq UREGS_rbp(%rsp), %rbp
-+ notq %rbp
-+#endif
-+.if !\compat
- movq %r12,UREGS_r12(%rsp)
- movq %r13,UREGS_r13(%rsp)
- movq %r14,UREGS_r14(%rsp)
- movq %r15,UREGS_r15(%rsp)
--987:
-+.endif
- .endm
-
- #define LOAD_ONE_REG(reg, compat) \
-@@ -351,33 +280,13 @@ static always_inline void stac(void)
- * @compat: R8-R15 don't need reloading
- */
- .macro RESTORE_ALL adj=0 compat=0
--.if !\compat
-- testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
--.endif
- LOAD_C_CLOBBERED \compat
- .if !\compat
-- jz 987f
- movq UREGS_r15(%rsp),%r15
- movq UREGS_r14(%rsp),%r14
- movq UREGS_r13(%rsp),%r13
- movq UREGS_r12(%rsp),%r12
--#ifndef NDEBUG
-- .subsection 1
--987: testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
-- jnz 987f
-- cmpq UREGS_r15(%rsp),%r15
-- jne 789f
-- cmpq UREGS_r14(%rsp),%r14
-- jne 789f
-- cmpq UREGS_r13(%rsp),%r13
-- jne 789f
-- cmpq UREGS_r12(%rsp),%r12
-- je 987f
--789: BUG /* Corruption of partial register state. */
-- .subsection 0
--#endif
- .endif
--987:
- LOAD_ONE_REG(bp, \compat)
- LOAD_ONE_REG(bx, \compat)
- subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
---
-2.15.1
-
Index: head/emulators/xen-kernel/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
+++ head/emulators/xen-kernel/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
@@ -1,494 +0,0 @@
-From ea7513a3e3f28cfec59dda6e128b6b4968685762 Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Thu, 28 Sep 2017 15:17:27 +0100
-Subject: [PATCH 1/2] x86: limit linear page table use to a single level
-
-That's the only way that they're meant to be used. Without such a
-restriction arbitrarily long chains of same-level page tables can be
-built, tearing down of which may then cause arbitrarily deep recursion,
-causing a stack overflow. To facilitate this restriction, a counter is
-being introduced to track both the number of same-level entries in a
-page table as well as the number of uses of a page table in another
-same-level one (counting into positive and negative direction
-respectively, utilizing the fact that both counts can't be non-zero at
-the same time).
-
-Note that the added accounting introduces a restriction on the number
-of times a page can be used in other same-level page tables - more than
-32k of such uses are no longer possible.
-
-Note also that some put_page_and_type[_preemptible]() calls are
-replaced with open-coded equivalents. This seemed preferrable to
-adding "parent_table" to the matrix of functions.
-
-Note further that cross-domain same-level page table references are no
-longer permitted (they probably never should have been).
-
-This is XSA-240.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
----
- xen/arch/x86/domain.c | 1 +
- xen/arch/x86/mm.c | 171 ++++++++++++++++++++++++++++++++++++++-----
- xen/include/asm-x86/domain.h | 2 +
- xen/include/asm-x86/mm.h | 25 +++++--
- 4 files changed, 175 insertions(+), 24 deletions(-)
-
-diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
-index 452748dd5b..44ed2ccd0a 100644
---- a/xen/arch/x86/domain.c
-+++ b/xen/arch/x86/domain.c
-@@ -1237,6 +1237,7 @@ int arch_set_info_guest(
- case -EINTR:
- rc = -ERESTART;
- case -ERESTART:
-+ v->arch.old_guest_ptpg = NULL;
- v->arch.old_guest_table =
- pagetable_get_page(v->arch.guest_table);
- v->arch.guest_table = pagetable_null();
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index e97ecccd93..e81a461b91 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -732,6 +732,61 @@ static void put_data_page(
- put_page(page);
- }
-
-+static bool_t inc_linear_entries(struct page_info *pg)
-+{
-+ typeof(pg->linear_pt_count) nc = read_atomic(&pg->linear_pt_count), oc;
-+
-+ do {
-+ /*
-+ * The check below checks for the "linear use" count being non-zero
-+ * as well as overflow. Signed integer overflow is undefined behavior
-+ * according to the C spec. However, as long as linear_pt_count is
-+ * smaller in size than 'int', the arithmetic operation of the
-+ * increment below won't overflow; rather the result will be truncated
-+ * when stored. Ensure that this is always true.
-+ */
-+ BUILD_BUG_ON(sizeof(nc) >= sizeof(int));
-+ oc = nc++;
-+ if ( nc <= 0 )
-+ return 0;
-+ nc = cmpxchg(&pg->linear_pt_count, oc, nc);
-+ } while ( oc != nc );
-+
-+ return 1;
-+}
-+
-+static void dec_linear_entries(struct page_info *pg)
-+{
-+ typeof(pg->linear_pt_count) oc;
-+
-+ oc = arch_fetch_and_add(&pg->linear_pt_count, -1);
-+ ASSERT(oc > 0);
-+}
-+
-+static bool_t inc_linear_uses(struct page_info *pg)
-+{
-+ typeof(pg->linear_pt_count) nc = read_atomic(&pg->linear_pt_count), oc;
-+
-+ do {
-+ /* See the respective comment in inc_linear_entries(). */
-+ BUILD_BUG_ON(sizeof(nc) >= sizeof(int));
-+ oc = nc--;
-+ if ( nc >= 0 )
-+ return 0;
-+ nc = cmpxchg(&pg->linear_pt_count, oc, nc);
-+ } while ( oc != nc );
-+
-+ return 1;
-+}
-+
-+static void dec_linear_uses(struct page_info *pg)
-+{
-+ typeof(pg->linear_pt_count) oc;
-+
-+ oc = arch_fetch_and_add(&pg->linear_pt_count, 1);
-+ ASSERT(oc < 0);
-+}
-+
- /*
- * We allow root tables to map each other (a.k.a. linear page tables). It
- * needs some special care with reference counts and access permissions:
-@@ -761,15 +816,35 @@ get_##level##_linear_pagetable( \
- \
- if ( (pfn = level##e_get_pfn(pde)) != pde_pfn ) \
- { \
-+ struct page_info *ptpg = mfn_to_page(pde_pfn); \
-+ \
-+ /* Make sure the page table belongs to the correct domain. */ \
-+ if ( unlikely(page_get_owner(ptpg) != d) ) \
-+ return 0; \
-+ \
- /* Make sure the mapped frame belongs to the correct domain. */ \
- if ( unlikely(!get_page_from_pagenr(pfn, d)) ) \
- return 0; \
- \
- /* \
-- * Ensure that the mapped frame is an already-validated page table. \
-+ * Ensure that the mapped frame is an already-validated page table \
-+ * and is not itself having linear entries, as well as that the \
-+ * containing page table is not iself in use as a linear page table \
-+ * elsewhere. \
- * If so, atomically increment the count (checking for overflow). \
- */ \
- page = mfn_to_page(pfn); \
-+ if ( !inc_linear_entries(ptpg) ) \
-+ { \
-+ put_page(page); \
-+ return 0; \
-+ } \
-+ if ( !inc_linear_uses(page) ) \
-+ { \
-+ dec_linear_entries(ptpg); \
-+ put_page(page); \
-+ return 0; \
-+ } \
- y = page->u.inuse.type_info; \
- do { \
- x = y; \
-@@ -777,6 +852,8 @@ get_##level##_linear_pagetable( \
- unlikely((x & (PGT_type_mask|PGT_validated)) != \
- (PGT_##level##_page_table|PGT_validated)) ) \
- { \
-+ dec_linear_uses(page); \
-+ dec_linear_entries(ptpg); \
- put_page(page); \
- return 0; \
- } \
-@@ -1201,6 +1278,9 @@ get_page_from_l4e(
- l3e_remove_flags((pl3e), _PAGE_USER|_PAGE_RW|_PAGE_ACCESSED); \
- } while ( 0 )
-
-+static int _put_page_type(struct page_info *page, bool_t preemptible,
-+ struct page_info *ptpg);
-+
- void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
- {
- unsigned long pfn = l1e_get_pfn(l1e);
-@@ -1270,17 +1350,22 @@ static int put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
- if ( l2e_get_flags(l2e) & _PAGE_PSE )
- put_superpage(l2e_get_pfn(l2e));
- else
-- put_page_and_type(l2e_get_page(l2e));
-+ {
-+ struct page_info *pg = l2e_get_page(l2e);
-+ int rc = _put_page_type(pg, 0, mfn_to_page(pfn));
-+
-+ ASSERT(!rc);
-+ put_page(pg);
-+ }
-
- return 0;
- }
-
--static int __put_page_type(struct page_info *, int preemptible);
--
- static int put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn,
- int partial, bool_t defer)
- {
- struct page_info *pg;
-+ int rc;
-
- if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || (l3e_get_pfn(l3e) == pfn) )
- return 1;
-@@ -1303,21 +1388,28 @@ static int put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn,
- if ( unlikely(partial > 0) )
- {
- ASSERT(!defer);
-- return __put_page_type(pg, 1);
-+ return _put_page_type(pg, 1, mfn_to_page(pfn));
- }
-
- if ( defer )
- {
-+ current->arch.old_guest_ptpg = mfn_to_page(pfn);
- current->arch.old_guest_table = pg;
- return 0;
- }
-
-- return put_page_and_type_preemptible(pg);
-+ rc = _put_page_type(pg, 1, mfn_to_page(pfn));
-+ if ( likely(!rc) )
-+ put_page(pg);
-+
-+ return rc;
- }
-
- static int put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn,
- int partial, bool_t defer)
- {
-+ int rc = 1;
-+
- if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) &&
- (l4e_get_pfn(l4e) != pfn) )
- {
-@@ -1326,18 +1418,22 @@ static int put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn,
- if ( unlikely(partial > 0) )
- {
- ASSERT(!defer);
-- return __put_page_type(pg, 1);
-+ return _put_page_type(pg, 1, mfn_to_page(pfn));
- }
-
- if ( defer )
- {
-+ current->arch.old_guest_ptpg = mfn_to_page(pfn);
- current->arch.old_guest_table = pg;
- return 0;
- }
-
-- return put_page_and_type_preemptible(pg);
-+ rc = _put_page_type(pg, 1, mfn_to_page(pfn));
-+ if ( likely(!rc) )
-+ put_page(pg);
- }
-- return 1;
-+
-+ return rc;
- }
-
- static int alloc_l1_table(struct page_info *page)
-@@ -1535,6 +1631,7 @@ static int alloc_l3_table(struct page_info *page)
- {
- page->nr_validated_ptes = i;
- page->partial_pte = 0;
-+ current->arch.old_guest_ptpg = NULL;
- current->arch.old_guest_table = page;
- }
- while ( i-- > 0 )
-@@ -1627,6 +1724,7 @@ static int alloc_l4_table(struct page_info *page)
- {
- if ( current->arch.old_guest_table )
- page->nr_validated_ptes++;
-+ current->arch.old_guest_ptpg = NULL;
- current->arch.old_guest_table = page;
- }
- }
-@@ -2369,14 +2467,20 @@ int free_page_type(struct page_info *pag
- }
-
-
--static int __put_final_page_type(
-- struct page_info *page, unsigned long type, int preemptible)
-+static int _put_final_page_type(struct page_info *page, unsigned long type,
-+ bool_t preemptible, struct page_info *ptpg)
- {
- int rc = free_page_type(page, type, preemptible);
-
- /* No need for atomic update of type_info here: noone else updates it. */
- if ( rc == 0 )
- {
-+ if ( ptpg && PGT_type_equal(type, ptpg->u.inuse.type_info) )
-+ {
-+ dec_linear_uses(page);
-+ dec_linear_entries(ptpg);
-+ }
-+ ASSERT(!page->linear_pt_count || page_get_owner(page)->is_dying);
- /*
- * Record TLB information for flush later. We do not stamp page tables
- * when running in shadow mode:
-@@ -2412,8 +2516,8 @@ static int __put_final_page_type(
- }
-
-
--static int __put_page_type(struct page_info *page,
-- int preemptible)
-+static int _put_page_type(struct page_info *page, bool_t preemptible,
-+ struct page_info *ptpg)
- {
- unsigned long nx, x, y = page->u.inuse.type_info;
- int rc = 0;
-@@ -2440,12 +2544,28 @@ static int __put_page_type(struct page_info *page,
- x, nx)) != x) )
- continue;
- /* We cleared the 'valid bit' so we do the clean up. */
-- rc = __put_final_page_type(page, x, preemptible);
-+ rc = _put_final_page_type(page, x, preemptible, ptpg);
-+ ptpg = NULL;
- if ( x & PGT_partial )
- put_page(page);
- break;
- }
-
-+ if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
-+ {
-+ /*
-+ * page_set_tlbflush_timestamp() accesses the same union
-+ * linear_pt_count lives in. Unvalidated page table pages,
-+ * however, should occur during domain destruction only
-+ * anyway. Updating of linear_pt_count luckily is not
-+ * necessary anymore for a dying domain.
-+ */
-+ ASSERT(page_get_owner(page)->is_dying);
-+ ASSERT(page->linear_pt_count < 0);
-+ ASSERT(ptpg->linear_pt_count > 0);
-+ ptpg = NULL;
-+ }
-+
- /*
- * Record TLB information for flush later. We do not stamp page
- * tables when running in shadow mode:
-@@ -2465,6 +2585,13 @@ static int __put_page_type(struct page_info *page,
- return -EINTR;
- }
-
-+ if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
-+ {
-+ ASSERT(!rc);
-+ dec_linear_uses(page);
-+ dec_linear_entries(ptpg);
-+ }
-+
- return rc;
- }
-
-@@ -2599,6 +2726,7 @@ static int __get_page_type(struct page_info *page, unsigned long type,
- page->nr_validated_ptes = 0;
- page->partial_pte = 0;
- }
-+ page->linear_pt_count = 0;
- rc = alloc_page_type(page, type, preemptible);
- }
-
-@@ -2610,7 +2738,7 @@ static int __get_page_type(struct page_info *page, unsigned long type,
-
- void put_page_type(struct page_info *page)
- {
-- int rc = __put_page_type(page, 0);
-+ int rc = _put_page_type(page, 0, NULL);
- ASSERT(rc == 0);
- (void)rc;
- }
-@@ -2626,7 +2754,7 @@ int get_page_type(struct page_info *page, unsigned long type)
-
- int put_page_type_preemptible(struct page_info *page)
- {
-- return __put_page_type(page, 1);
-+ return _put_page_type(page, 1, NULL);
- }
-
- int get_page_type_preemptible(struct page_info *page, unsigned long type)
-@@ -2832,11 +2960,14 @@ int put_old_guest_table(struct vcpu *v)
- if ( !v->arch.old_guest_table )
- return 0;
-
-- switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table) )
-+ switch ( rc = _put_page_type(v->arch.old_guest_table, 1,
-+ v->arch.old_guest_ptpg) )
- {
- case -EINTR:
- case -ERESTART:
- return -ERESTART;
-+ case 0:
-+ put_page(v->arch.old_guest_table);
- }
-
- v->arch.old_guest_table = NULL;
-@@ -2993,6 +3124,7 @@ int new_guest_cr3(unsigned long mfn)
- rc = -ERESTART;
- /* fallthrough */
- case -ERESTART:
-+ curr->arch.old_guest_ptpg = NULL;
- curr->arch.old_guest_table = page;
- break;
- default:
-@@ -3260,7 +3392,10 @@ long do_mmuext_op(
- if ( type == PGT_l1_page_table )
- put_page_and_type(page);
- else
-+ {
-+ curr->arch.old_guest_ptpg = NULL;
- curr->arch.old_guest_table = page;
-+ }
- }
- }
-
-@@ -3293,6 +3428,7 @@ long do_mmuext_op(
- {
- case -EINTR:
- case -ERESTART:
-+ curr->arch.old_guest_ptpg = NULL;
- curr->arch.old_guest_table = page;
- rc = 0;
- break;
-@@ -3371,6 +3507,7 @@ long do_mmuext_op(
- rc = -ERESTART;
- /* fallthrough */
- case -ERESTART:
-+ curr->arch.old_guest_ptpg = NULL;
- curr->arch.old_guest_table = page;
- break;
- default:
-diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
-index 165e533ab3..5ef761be8b 100644
---- a/xen/include/asm-x86/domain.h
-+++ b/xen/include/asm-x86/domain.h
-@@ -529,6 +529,8 @@ struct arch_vcpu
- pagetable_t guest_table_user; /* (MFN) x86/64 user-space pagetable */
- pagetable_t guest_table; /* (MFN) guest notion of cr3 */
- struct page_info *old_guest_table; /* partially destructed pagetable */
-+ struct page_info *old_guest_ptpg; /* containing page table of the */
-+ /* former, if any */
- /* guest_table holds a ref to the page, and also a type-count unless
- * shadow refcounts are in use */
- pagetable_t shadow_table[4]; /* (MFN) shadow(s) of guest */
-diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
-index a30e76db1e..905c7971f2 100644
---- a/xen/include/asm-x86/mm.h
-+++ b/xen/include/asm-x86/mm.h
-@@ -125,11 +125,11 @@ struct page_info
- u32 tlbflush_timestamp;
-
- /*
-- * When PGT_partial is true then this field is valid and indicates
-- * that PTEs in the range [0, @nr_validated_ptes) have been validated.
-- * An extra page reference must be acquired (or not dropped) whenever
-- * PGT_partial gets set, and it must be dropped when the flag gets
-- * cleared. This is so that a get() leaving a page in partially
-+ * When PGT_partial is true then the first two fields are valid and
-+ * indicate that PTEs in the range [0, @nr_validated_ptes) have been
-+ * validated. An extra page reference must be acquired (or not dropped)
-+ * whenever PGT_partial gets set, and it must be dropped when the flag
-+ * gets cleared. This is so that a get() leaving a page in partially
- * validated state (where the caller would drop the reference acquired
- * due to the getting of the type [apparently] failing [-ERESTART])
- * would not accidentally result in a page left with zero general
-@@ -153,10 +153,18 @@ struct page_info
- * put_page_from_lNe() (due to the apparent failure), and hence it
- * must be dropped when the put operation is resumed (and completes),
- * but it must not be acquired if picking up the page for validation.
-+ *
-+ * The 3rd field, @linear_pt_count, indicates
-+ * - by a positive value, how many same-level page table entries a page
-+ * table has,
-+ * - by a negative value, in how many same-level page tables a page is
-+ * in use.
- */
- struct {
-- u16 nr_validated_ptes;
-- s8 partial_pte;
-+ u16 nr_validated_ptes:PAGETABLE_ORDER + 1;
-+ u16 :16 - PAGETABLE_ORDER - 1 - 2;
-+ s16 partial_pte:2;
-+ s16 linear_pt_count;
- };
-
- /*
-@@ -207,6 +215,9 @@ struct page_info
- #define PGT_count_width PG_shift(9)
- #define PGT_count_mask ((1UL<<PGT_count_width)-1)
-
-+/* Are the 'type mask' bits identical? */
-+#define PGT_type_equal(x, y) (!(((x) ^ (y)) & PGT_type_mask))
-+
- /* Cleared when the owning guest 'frees' this page. */
- #define _PGC_allocated PG_shift(1)
- #define PGC_allocated PG_mask(1, 1)
---
-2.14.1
-
Index: head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
+++ head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
@@ -1,45 +0,0 @@
-From 9b76908e6e074d7efbeafe6bad066ecc5f3c3c43 Mon Sep 17 00:00:00 2001
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Date: Wed, 17 Jan 2018 17:23:37 +0100
-Subject: [PATCH] x86/mm: Always set _PAGE_ACCESSED on L4e updates
-
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-master commit: bd61fe94bee0556bc2f64999a4a8315b93f90f21
-master date: 2018-01-15 13:53:16 +0000
----
- xen/arch/x86/mm.c | 14 +++++++++++++-
- 1 file changed, 13 insertions(+), 1 deletion(-)
-
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index ada12c05c5..50f500c940 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -1296,11 +1296,23 @@ get_page_from_l4e(
- _PAGE_USER|_PAGE_RW); \
- } while ( 0 )
-
-+/*
-+ * When shadowing an L4 behind the guests back (e.g. for per-pcpu
-+ * purposes), we cannot efficiently sync access bit updates from hardware
-+ * (on the shadow tables) back into the guest view.
-+ *
-+ * We therefore unconditionally set _PAGE_ACCESSED even in the guests
-+ * view. This will appear to the guest as a CPU which proactively pulls
-+ * all valid L4e's into its TLB, which is compatible with the x86 ABI.
-+ *
-+ * At the time of writing, all PV guests set the access bit anyway, so
-+ * this is no actual change in their behaviour.
-+ */
- #define adjust_guest_l4e(pl4e, d) \
- do { \
- if ( likely(l4e_get_flags((pl4e)) & _PAGE_PRESENT) && \
- likely(!is_pv_32bit_domain(d)) ) \
-- l4e_add_flags((pl4e), _PAGE_USER); \
-+ l4e_add_flags((pl4e), _PAGE_USER | _PAGE_ACCESSED); \
- } while ( 0 )
-
- #define unadjust_guest_l3e(pl3e, d) \
---
-2.15.1
-
Index: head/emulators/xen-kernel/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
===================================================================
--- head/emulators/xen-kernel/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
+++ head/emulators/xen-kernel/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
@@ -1,44 +0,0 @@
-From 7a0ed7f3c2dcb1f104b6f70223d48d8826aec7f2 Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Tue, 31 May 2016 16:07:26 +0200
-Subject: [PATCH 1/2] xen/logdirty: prevent preemption if finished
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-While working on PVH migration support I've realized that
-paging_log_dirty_op sometimes restarts with sc->pages == pages, which means
-there's no more work to do. Avoid this by adding a check in the preemption
-points of the function.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
----
- xen/arch/x86/mm/paging.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
-index 8219bb6..ed94ff7 100644
---- a/xen/arch/x86/mm/paging.c
-+++ b/xen/arch/x86/mm/paging.c
-@@ -519,7 +519,8 @@ static int paging_log_dirty_op(struct domain *d,
- if ( l2 )
- unmap_domain_page(l2);
-
-- if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() )
-+ if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() &&
-+ sc->pages != pages )
- {
- d->arch.paging.preempt.log_dirty.i4 = i4;
- d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
-@@ -531,7 +532,7 @@ static int paging_log_dirty_op(struct domain *d,
- unmap_domain_page(l3);
-
- if ( !rv && i4 < LOGDIRTY_NODE_ENTRIES - 1 &&
-- hypercall_preempt_check() )
-+ hypercall_preempt_check() && sc->pages != pages )
- {
- d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
- d->arch.paging.preempt.log_dirty.i3 = 0;
---
-2.7.4 (Apple Git-66)
-
Index: head/emulators/xen-kernel/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
===================================================================
--- head/emulators/xen-kernel/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
+++ head/emulators/xen-kernel/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
@@ -1,69 +0,0 @@
-From e5a1bf46187b0d39ec7e8c46e11c42027840747c Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Fri, 10 Mar 2017 01:08:26 +0900
-Subject: [PATCH 2/2] build/clang: fix XSM dummy policy when using clang 4.0
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There seems to be some weird bug in clang 4.0 that prevents xsm_pmu_op from
-working as expected, and vpmu.o ends up with a reference to
-__xsm_action_mismatch_detected which makes the build fail:
-
-[...]
-ld -melf_x86_64_fbsd -T xen.lds -N prelink.o \
- xen/common/symbols-dummy.o -o xen/.xen-syms.0
-prelink.o: In function `xsm_default_action':
-xen/include/xsm/dummy.h:80: undefined reference to `__xsm_action_mismatch_detected'
-xen/xen/include/xsm/dummy.h:80: relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__xsm_action_mismatch_detected'
-ld: xen/xen/.xen-syms.0: hidden symbol `__xsm_action_mismatch_detected' isn't defined
-
-Then doing a search in the objects files:
-
-# find xen/ -type f -name '*.o' -print0 | xargs -0 bash -c \
- 'for filename; do nm "$filename" | \
- grep -q __xsm_action_mismatch_detected && echo "$filename"; done' bash
-xen/arch/x86/prelink.o
-xen/arch/x86/cpu/vpmu.o
-xen/arch/x86/cpu/built_in.o
-xen/arch/x86/built_in.o
-
-The current patch is the only way I've found to fix this so far, by simply
-moving the XSM_PRIV check into the default case in xsm_pmu_op. This also fixes
-the behavior of do_xenpmu_op, which will now return -EINVAL for unknown
-XENPMU_* operations, instead of -EPERM when called by a privileged domain.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
----
-Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
----
- xen/include/xsm/dummy.h | 7 +------
- 1 file changed, 1 insertion(+), 6 deletions(-)
-
-diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
-index abbe282..0039c39 100644
---- a/xen/include/xsm/dummy.h
-+++ b/xen/include/xsm/dummy.h
-@@ -711,18 +711,13 @@ static XSM_INLINE int xsm_pmu_op (XSM_DEFAULT_ARG struct domain *d, unsigned int
- XSM_ASSERT_ACTION(XSM_OTHER);
- switch ( op )
- {
-- case XENPMU_mode_set:
-- case XENPMU_mode_get:
-- case XENPMU_feature_set:
-- case XENPMU_feature_get:
-- return xsm_default_action(XSM_PRIV, d, current->domain);
- case XENPMU_init:
- case XENPMU_finish:
- case XENPMU_lvtpc_set:
- case XENPMU_flush:
- return xsm_default_action(XSM_HOOK, d, current->domain);
- default:
-- return -EPERM;
-+ return xsm_default_action(XSM_PRIV, d, current->domain);
- }
- }
-
---
-2.10.1 (Apple Git-78)
-
Index: head/emulators/xen-kernel/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
+++ head/emulators/xen-kernel/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
@@ -1,102 +0,0 @@
-From 2c146b4f763f47180a0effb8d8045b0ebb93652c Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Fri, 2 Jun 2017 12:22:42 +0100
-Subject: [PATCH 2/4] gnttab: fix unmap pin accounting race
-
-Once all {writable} mappings of a grant entry have been unmapped, the
-hypervisor informs the guest that the grant entry has been released by
-clearing the _GTF_{reading,writing} usage flags in the guest's grant
-table as appropriate.
-
-Unfortunately, at the moment, the code that updates the accounting
-happens in a different critical section than the one which updates the
-usage flags; this means that under the right circumstances, there may be
-a window in time after the hypervisor reported the grant as being free
-during which the grant referee still had access to the page.
-
-Move the grant accounting code into the same critical section as the
-reporting code to make sure this kind of race can't happen.
-
-This is part of XSA-218.
-
-Reported-by: Jann Horn <jannh.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 32 +++++++++++++++++---------------
- 1 file changed, 17 insertions(+), 15 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index 8b22299..cfc483f 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -1150,15 +1150,8 @@ __gnttab_unmap_common(
- PIN_FAIL(act_release_out, GNTST_general_error,
- "Bad frame number doesn't match gntref. (%lx != %lx)\n",
- op->frame, act->frame);
-- if ( op->flags & GNTMAP_device_map )
-- {
-- ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
-- op->map->flags &= ~GNTMAP_device_map;
-- if ( op->flags & GNTMAP_readonly )
-- act->pin -= GNTPIN_devr_inc;
-- else
-- act->pin -= GNTPIN_devw_inc;
-- }
-+
-+ op->map->flags &= ~GNTMAP_device_map;
- }
-
- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
-@@ -1168,12 +1161,7 @@ __gnttab_unmap_common(
- op->flags)) < 0 )
- goto act_release_out;
-
-- ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
- op->map->flags &= ~GNTMAP_host_map;
-- if ( op->flags & GNTMAP_readonly )
-- act->pin -= GNTPIN_hstr_inc;
-- else
-- act->pin -= GNTPIN_hstw_inc;
- }
-
- act_release_out:
-@@ -1266,6 +1254,12 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- else
- put_page_and_type(pg);
- }
-+
-+ ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
-+ if ( op->flags & GNTMAP_readonly )
-+ act->pin -= GNTPIN_devr_inc;
-+ else
-+ act->pin -= GNTPIN_devw_inc;
- }
-
- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
-@@ -1274,7 +1268,9 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- {
- /*
- * Suggests that __gntab_unmap_common failed in
-- * replace_grant_host_mapping() so nothing further to do
-+ * replace_grant_host_mapping() or IOMMU handling, so nothing
-+ * further to do (short of re-establishing the mapping in the
-+ * latter case).
- */
- goto act_release_out;
- }
-@@ -1285,6 +1281,12 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- put_page_type(pg);
- put_page(pg);
- }
-+
-+ ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
-+ if ( op->flags & GNTMAP_readonly )
-+ act->pin -= GNTPIN_hstr_inc;
-+ else
-+ act->pin -= GNTPIN_hstw_inc;
- }
-
- if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
+++ head/emulators/xen-kernel/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
@@ -1,42 +0,0 @@
-From 8894a0c20d920aada305aade0591c1e77167b1db Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Fri, 2 Jun 2017 15:21:27 +0100
-Subject: [PATCH 2/4] gnttab: never create host mapping unless asked to
-
-We shouldn't create a host mapping unless asked to even in the case of
-mapping a granted MMIO page. In particular the mapping wouldn't be torn
-down when processing the matching unmap request.
-
-This is part of XSA-224.
-
-Reported-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index 69cbdb6..452538e 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -911,10 +911,13 @@ __gnttab_map_grant_ref(
- goto undo_out;
- }
-
-- rc = create_grant_host_mapping(
-- op->host_addr, frame, op->flags, cache_flags);
-- if ( rc != GNTST_okay )
-- goto undo_out;
-+ if ( op->flags & GNTMAP_host_map )
-+ {
-+ rc = create_grant_host_mapping(op->host_addr, frame, op->flags,
-+ cache_flags);
-+ if ( rc != GNTST_okay )
-+ goto undo_out;
-+ }
- }
- else if ( owner == rd || owner == dom_cow )
- {
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
+++ head/emulators/xen-kernel/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
@@ -1,109 +0,0 @@
-From 01feeda5363dd8d2fea8395c2c435203751c8ba5 Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Fri, 10 Nov 2017 16:53:55 +0000
-Subject: [PATCH 2/2] p2m: Check return value of p2m_set_entry() when
- decreasing reservation
-
-If the entire range specified to p2m_pod_decrease_reservation() is marked
-populate-on-demand, then it will make a single p2m_set_entry() call,
-reducing its PoD entry count.
-
-Unfortunately, in the right circumstances, this p2m_set_entry() call
-may fail. It that case, repeated calls to decrease_reservation() may
-cause p2m->pod.entry_count to fall below zero, potentially tripping
-over BUG_ON()s to the contrary.
-
-Instead, check to see if the entry succeeded, and return false if not.
-The caller will then call guest_remove_page() on the gfns, which will
-return -EINVAL upon finding no valid memory there to return.
-
-Unfortunately if the order > 0, the entry may have partially changed.
-A domain_crash() is probably the safest thing in that case.
-
-Other p2m_set_entry() calls in the same function should be fine,
-because they are writing the entry at its current order. Nonetheless,
-check the return value and crash if our assumption turns otu to be
-wrong.
-
-This is part of XSA-247.
-
-Reported-by: George Dunlap <george.dunlap.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
----
-v2: Crash the domain if we're not sure it's safe (or if we think it
-can't happen)
----
- xen/arch/x86/mm/p2m-pod.c | 42 +++++++++++++++++++++++++++++++++---------
- 1 file changed, 33 insertions(+), 9 deletions(-)
-
-diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
-index 5ec8a37949..91d309647e 100644
---- a/xen/arch/x86/mm/p2m-pod.c
-+++ b/xen/arch/x86/mm/p2m-pod.c
-@@ -557,11 +557,23 @@ p2m_pod_decrease_reservation(struct domain *d,
-
- if ( !nonpod )
- {
-- /* All PoD: Mark the whole region invalid and tell caller
-- * we're done. */
-- p2m_set_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid,
-- p2m->default_access);
-- p2m->pod.entry_count-=(1<<order);
-+ /*
-+ * All PoD: Mark the whole region invalid and tell caller
-+ * we're done.
-+ */
-+ if ( p2m_set_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid,
-+ p2m->default_access) )
-+ {
-+ /*
-+ * If this fails, we can't tell how much of the range was changed.
-+ * Best to crash the domain unless we're sure a partial change is
-+ * impossible.
-+ */
-+ if ( order != 0 )
-+ domain_crash(d);
-+ goto out_unlock;
-+ }
-+ p2m->pod.entry_count -= 1UL << order;
- BUG_ON(p2m->pod.entry_count < 0);
- ret = 1;
- goto out_entry_check;
-@@ -602,8 +614,14 @@ p2m_pod_decrease_reservation(struct domain *d,
- n = 1UL << cur_order;
- if ( t == p2m_populate_on_demand )
- {
-- p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
-- p2m_invalid, p2m->default_access);
-+ /* This shouldn't be able to fail */
-+ if ( p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
-+ p2m_invalid, p2m->default_access) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ domain_crash(d);
-+ goto out_unlock;
-+ }
- p2m->pod.entry_count -= n;
- BUG_ON(p2m->pod.entry_count < 0);
- pod -= n;
-@@ -624,8 +642,14 @@ p2m_pod_decrease_reservation(struct domain *d,
-
- page = mfn_to_page(mfn);
-
-- p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
-- p2m_invalid, p2m->default_access);
-+ /* This shouldn't be able to fail */
-+ if ( p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
-+ p2m_invalid, p2m->default_access) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ domain_crash(d);
-+ goto out_unlock;
-+ }
- p2m_tlb_flush_sync(p2m);
- for ( j = 0; j < n; ++j )
- set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
---
-2.15.0
-
Index: head/emulators/xen-kernel/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
+++ head/emulators/xen-kernel/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
@@ -1,163 +0,0 @@
-From e19d0af4ee2ae9e42a85db639fd6848e72f5658b Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Wed, 17 Jan 2018 17:24:59 +0100
-Subject: [PATCH 2/2] x86: allow Meltdown band-aid to be disabled
-
-First of all we don't need it on AMD systems. Additionally allow its use
-to be controlled by command line option. For best backportability, this
-intentionally doesn't use alternative instruction patching to achieve
-the intended effect - while we likely want it, this will be later
-follow-up.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-master commit: e871e80c38547d9faefc6604532ba3e985e65873
-master date: 2018-01-16 17:50:59 +0100
----
- docs/misc/xen-command-line.markdown | 12 ++++++++++++
- xen/arch/x86/domain.c | 7 +++++--
- xen/arch/x86/mm.c | 2 +-
- xen/arch/x86/smpboot.c | 17 ++++++++++++++---
- xen/arch/x86/x86_64/entry.S | 2 ++
- 5 files changed, 34 insertions(+), 6 deletions(-)
-
-diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
-index 2dacb5d073..aecf9fd49d 100644
---- a/docs/misc/xen-command-line.markdown
-+++ b/docs/misc/xen-command-line.markdown
-@@ -1621,6 +1621,18 @@ In the case that x2apic is in use, this option switches between physical and
- clustered mode. The default, given no hint from the **FADT**, is cluster
- mode.
-
-+### xpti
-+> `= <boolean>`
-+
-+> Default: `false` on AMD hardware
-+> Default: `true` everywhere else
-+
-+Override default selection of whether to isolate 64-bit PV guest page
-+tables.
-+
-+** WARNING: Not yet a complete isolation implementation, but better than
-+nothing. **
-+
- ### xsave
- > `= <boolean>`
-
-diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
-index 3cf18f95b7..a1bda5e12d 100644
---- a/xen/arch/x86/domain.c
-+++ b/xen/arch/x86/domain.c
-@@ -1945,12 +1945,15 @@ static void paravirt_ctxt_switch_from(struct vcpu *v)
-
- static void paravirt_ctxt_switch_to(struct vcpu *v)
- {
-+ root_pgentry_t *root_pgt = this_cpu(root_pgt);
- unsigned long cr4;
-
- switch_kernel_stack(v);
-
-- this_cpu(root_pgt)[root_table_offset(PERDOMAIN_VIRT_START)] =
-- l4e_from_page(v->domain->arch.perdomain_l3_pg, __PAGE_HYPERVISOR_RW);
-+ if ( root_pgt )
-+ root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
-+ l4e_from_page(v->domain->arch.perdomain_l3_pg,
-+ __PAGE_HYPERVISOR_RW);
-
- cr4 = pv_guest_cr4_to_real_cr4(v);
- if ( unlikely(cr4 != read_cr4()) )
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index c9e4003989..07015e3160 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -4007,7 +4007,7 @@ long do_mmu_update(
- rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
- cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
- if ( !rc )
-- sync_guest = 1;
-+ sync_guest = !!this_cpu(root_pgt);
- break;
- case PGT_writable_page:
- perfc_incr(writable_mmu_updates);
-diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
-index eaeec5acf0..f2f47f612a 100644
---- a/xen/arch/x86/smpboot.c
-+++ b/xen/arch/x86/smpboot.c
-@@ -320,7 +320,7 @@ void start_secondary(void *unused)
- spin_debug_disable();
-
- get_cpu_info()->xen_cr3 = 0;
-- get_cpu_info()->pv_cr3 = __pa(this_cpu(root_pgt));
-+ get_cpu_info()->pv_cr3 = this_cpu(root_pgt) ? __pa(this_cpu(root_pgt)) : 0;
-
- load_system_tables();
-
-@@ -729,14 +729,20 @@ static int clone_mapping(const void *ptr, root_pgentry_t *rpt)
- return 0;
- }
-
-+static __read_mostly int8_t opt_xpti = -1;
-+boolean_param("xpti", opt_xpti);
- DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
-
- static int setup_cpu_root_pgt(unsigned int cpu)
- {
-- root_pgentry_t *rpt = alloc_xen_pagetable();
-+ root_pgentry_t *rpt;
- unsigned int off;
- int rc;
-
-+ if ( !opt_xpti )
-+ return 0;
-+
-+ rpt = alloc_xen_pagetable();
- if ( !rpt )
- return -ENOMEM;
-
-@@ -977,10 +983,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
-
- stack_base[0] = stack_start;
-
-+ if ( opt_xpti < 0 )
-+ opt_xpti = boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
-+
- rc = setup_cpu_root_pgt(0);
- if ( rc )
- panic("Error %d setting up PV root page table\n", rc);
-- get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
-+ if ( per_cpu(root_pgt, 0) )
-+ get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
-
- set_nr_sockets();
-
-@@ -1048,6 +1058,7 @@ void __init smp_prepare_boot_cpu(void)
- cpumask_set_cpu(smp_processor_id(), &cpu_present_map);
-
- get_cpu_info()->xen_cr3 = 0;
-+ get_cpu_info()->pv_cr3 = 0;
- }
-
- static void
-diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
-index d63e734bb3..2a569952e3 100644
---- a/xen/arch/x86/x86_64/entry.S
-+++ b/xen/arch/x86/x86_64/entry.S
-@@ -45,6 +45,7 @@ restore_all_guest:
- movabs $DIRECTMAP_VIRT_START, %rcx
- mov %rdi, %rax
- and %rsi, %rdi
-+ jz .Lrag_keep_cr3
- and %r9, %rsi
- add %rcx, %rdi
- add %rcx, %rsi
-@@ -61,6 +62,7 @@ restore_all_guest:
- rep movsq
- mov %r9, STACK_CPUINFO_FIELD(xen_cr3)(%rdx)
- write_cr3 rax, rdi, rsi
-+.Lrag_keep_cr3:
-
- RESTORE_ALL
- testw $TRAP_syscall,4(%rsp)
---
-2.15.1
-
Index: head/emulators/xen-kernel/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
+++ head/emulators/xen-kernel/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
@@ -1,66 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
-
-(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
-actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
-This in turn requires bypassing the XSM check in physdev_unmap_pirq()
-for the HVM emuirq case just like is being done in physdev_map_pirq().
-The primary goal security wise, however, is to no longer allow HVM
-guests, by specifying their own domain ID instead of DOMID_SELF, to
-enter code paths intended for PV guest and the control domains of HVM
-guests only.
-
-This is part of XSA-237.
-
-Reported-by: HW42 <hw42@ipsumj.de>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/x86/physdev.c
-+++ b/xen/arch/x86/physdev.c
-@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
- if ( d == NULL )
- return -ESRCH;
-
-- ret = xsm_map_domain_pirq(XSM_TARGET, d);
-+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
- if ( ret )
- goto free_domain;
-
-@@ -255,13 +255,14 @@ int physdev_map_pirq(domid_t domid, int
- int physdev_unmap_pirq(domid_t domid, int pirq)
- {
- struct domain *d;
-- int ret;
-+ int ret = 0;
-
- d = rcu_lock_domain_by_any_id(domid);
- if ( d == NULL )
- return -ESRCH;
-
-- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
-+ if ( domid != DOMID_SELF || !is_hvm_domain(d) )
-+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
- if ( ret )
- goto free_domain;
-
---- a/xen/include/xsm/dummy.h
-+++ b/xen/include/xsm/dummy.h
-@@ -453,7 +453,7 @@ static XSM_INLINE char *xsm_show_irq_sid
-
- static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
- {
-- XSM_ASSERT_ACTION(XSM_TARGET);
-+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
- return xsm_default_action(action, current->domain, d);
- }
-
-@@ -465,7 +465,7 @@ static XSM_INLINE int xsm_map_domain_irq
-
- static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
- {
-- XSM_ASSERT_ACTION(XSM_TARGET);
-+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
- return xsm_default_action(action, current->domain, d);
- }
-
Index: head/emulators/xen-kernel/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
+++ head/emulators/xen-kernel/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
@@ -1,82 +0,0 @@
-From 9a4b34729f1bb92eea1e1efe52e6face9f0b17ae Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Fri, 22 Sep 2017 11:46:55 +0100
-Subject: [PATCH 2/2] x86/mm: Disable PV linear pagetables by default
-
-Allowing pagetables to point to other pagetables of the same level
-(often called 'linear pagetables') has been included in Xen since its
-inception. But it is not used by the most common PV guests (Linux,
-NetBSD, minios), and has been the source of a number of subtle
-reference-counting bugs.
-
-Add a command-line option to control whether PV linear pagetables are
-allowed (disabled by default).
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
----
-Changes since v2:
-- s/_/-/; in command-line option
-- Added __read_mostly
----
- docs/misc/xen-command-line.markdown | 15 +++++++++++++++
- xen/arch/x86/mm.c | 9 +++++++++
- 2 files changed, 24 insertions(+)
-
-diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
-index 73f5265fc6..061aff5edc 100644
---- a/docs/misc/xen-command-line.markdown
-+++ b/docs/misc/xen-command-line.markdown
-@@ -1280,6 +1280,21 @@ The following resources are available:
- CDP, one COS will corespond two CBMs other than one with CAT, due to the
- sum of CBMs is fixed, that means actual `cos_max` in use will automatically
- reduce to half when CDP is enabled.
-+
-+### pv-linear-pt
-+> `= <boolean>`
-+
-+> Default: `false`
-+
-+Allow PV guests to have pagetable entries pointing to other pagetables
-+of the same level (i.e., allowing L2 PTEs to point to other L2 pages).
-+This technique is often called "linear pagetables", and is sometimes
-+used to allow operating systems a simple way to consistently map the
-+current process's pagetables into its own virtual address space.
-+
-+None of the most common PV operating systems (Linux, NetBSD, MiniOS)
-+use this technique, but there may be custom operating systems which
-+do.
-
- ### reboot
- > `= t[riple] | k[bd] | a[cpi] | p[ci] | P[ower] | e[fi] | n[o] [, [w]arm | [c]old]`
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index e81a461b91..f748d4a221 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -799,6 +799,9 @@ static void dec_linear_uses(struct page_info *pg)
- * frame if it is mapped by a different root table. This is sufficient and
- * also necessary to allow validation of a root table mapping itself.
- */
-+static bool_t __read_mostly pv_linear_pt_enable = 0;
-+boolean_param("pv-linear-pt", pv_linear_pt_enable);
-+
- #define define_get_linear_pagetable(level) \
- static int \
- get_##level##_linear_pagetable( \
-@@ -808,6 +811,12 @@ get_##level##_linear_pagetable( \
- struct page_info *page; \
- unsigned long pfn; \
- \
-+ if ( !pv_linear_pt_enable ) \
-+ { \
-+ MEM_LOG("Attempt to create linear p.t. (feature disabled)"); \
-+ return 0; \
-+ } \
-+ \
- if ( (level##e_get_flags(pde) & _PAGE_RW) ) \
- { \
- MEM_LOG("Attempt to create linear p.t. with write perms"); \
---
-2.14.1
-
Index: head/emulators/xen-kernel/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
===================================================================
--- head/emulators/xen-kernel/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
+++ head/emulators/xen-kernel/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
@@ -1,244 +0,0 @@
-From e253a2e2fb45197273cee7a7fa2b77f7a87cb67f Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Tue, 31 May 2016 16:07:26 +0200
-Subject: [PATCH 2/2] xen: rework paging_log_dirty_op to work with hvm guests
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When the caller of paging_log_dirty_op is a hvm guest Xen would choke when
-trying to copy the dirty bitmap to the guest because the paging lock is
-already held.
-
-Fix this by independently mapping each page of the guest bitmap as needed
-without the paging lock held.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Cc: Tim Deegan <tim@xen.org>
-Cc: Jan Beulich <jbeulich@suse.com>
-Cc: Andrew Cooper <andrew.cooper3@citrix.com>
----
-Changes since v6:
- - Move the again label to the start of the function.
- - Set all the preempt fields if we need to map a new page (just like on the
- preempt case).
-
-Changes since v4:
- - Indent again label.
- - Replace bogus paddr_t cast with proper type.
- - Update preempt.log_dirty before dropping the paging lock.
-
-Changes since v3:
- - Drop last parameter from map_dirty_bitmap.
- - Drop pointless initializers in paging_log_dirty_op.
- - Add a new field to paging_domain in order to copy i2 position.
- - Move the again case up to make sure we don't hold cached values of the
- contents of log_dirty.
- - Replace the BUG_ON in paging_log_dirty_op with an ASSERT.
-
-Changes since v2:
- - Add checks for p2m_is_ram and p2m_is_discard_write when mapping a guest
- page.
- - Remove error checking from memset/memcpy, they unconditionally return
- dst.
----
- xen/arch/x86/mm/paging.c | 97 +++++++++++++++++++++++++++++++++++++++-----
- xen/include/asm-x86/domain.h | 1 +
- 2 files changed, 87 insertions(+), 11 deletions(-)
-
-diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
-index ed94ff7..595c9d6 100644
---- a/xen/arch/x86/mm/paging.c
-+++ b/xen/arch/x86/mm/paging.c
-@@ -406,6 +406,51 @@ int paging_mfn_is_dirty(struct domain *d, mfn_t gmfn)
- return rv;
- }
-
-+static inline void *map_dirty_bitmap(XEN_GUEST_HANDLE_64(uint8) dirty_bitmap,
-+ unsigned long pages,
-+ struct page_info **page)
-+{
-+ uint32_t pfec = PFEC_page_present | PFEC_write_access;
-+ unsigned long gfn;
-+ p2m_type_t p2mt;
-+
-+ gfn = paging_gva_to_gfn(current,
-+ (unsigned long)(dirty_bitmap.p + (pages >> 3)),
-+ &pfec);
-+ if ( gfn == INVALID_GFN )
-+ return NULL;
-+
-+ *page = get_page_from_gfn(current->domain, gfn, &p2mt, P2M_UNSHARE);
-+
-+ if ( !p2m_is_ram(p2mt) )
-+ {
-+ put_page(*page);
-+ return NULL;
-+ }
-+ if ( p2m_is_paging(p2mt) )
-+ {
-+ put_page(*page);
-+ p2m_mem_paging_populate(current->domain, gfn);
-+ return NULL;
-+ }
-+ if ( p2m_is_shared(p2mt) || p2m_is_discard_write(p2mt) )
-+ {
-+ put_page(*page);
-+ return NULL;
-+ }
-+
-+ return __map_domain_page(*page);
-+}
-+
-+static inline void unmap_dirty_bitmap(void *addr, struct page_info *page)
-+{
-+ if ( addr != NULL )
-+ {
-+ unmap_domain_page(addr);
-+ put_page(page);
-+ }
-+}
-+
-
- /* Read a domain's log-dirty bitmap and stats. If the operation is a CLEAN,
- * clear the bitmap and stats as well. */
-@@ -418,7 +463,11 @@ static int paging_log_dirty_op(struct domain *d,
- mfn_t *l4 = NULL, *l3 = NULL, *l2 = NULL;
- unsigned long *l1 = NULL;
- int i4, i3, i2;
-+ uint8_t *dirty_bitmap;
-+ struct page_info *page;
-+ unsigned long index_mapped;
-
-+ again:
- if ( !resuming )
- {
- /*
-@@ -439,6 +488,14 @@ static int paging_log_dirty_op(struct domain *d,
- p2m_flush_hardware_cached_dirty(d);
- }
-
-+ index_mapped = resuming ? d->arch.paging.preempt.log_dirty.done : 0;
-+ dirty_bitmap = map_dirty_bitmap(sc->dirty_bitmap, index_mapped, &page);
-+ if ( dirty_bitmap == NULL )
-+ {
-+ domain_unpause(d);
-+ return -EFAULT;
-+ }
-+
- paging_lock(d);
-
- if ( !d->arch.paging.preempt.dom )
-@@ -478,18 +535,18 @@ static int paging_log_dirty_op(struct domain *d,
- l4 = paging_map_log_dirty_bitmap(d);
- i4 = d->arch.paging.preempt.log_dirty.i4;
- i3 = d->arch.paging.preempt.log_dirty.i3;
-+ i2 = d->arch.paging.preempt.log_dirty.i2;
- pages = d->arch.paging.preempt.log_dirty.done;
-
- for ( ; (pages < sc->pages) && (i4 < LOGDIRTY_NODE_ENTRIES); i4++, i3 = 0 )
- {
- l3 = (l4 && mfn_valid(l4[i4])) ? map_domain_page(l4[i4]) : NULL;
-- for ( ; (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES); i3++ )
-+ for ( ; (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES);
-+ i3++, i2 = 0 )
- {
- l2 = ((l3 && mfn_valid(l3[i3])) ?
- map_domain_page(l3[i3]) : NULL);
-- for ( i2 = 0;
-- (pages < sc->pages) && (i2 < LOGDIRTY_NODE_ENTRIES);
-- i2++ )
-+ for ( ; (pages < sc->pages) && (i2 < LOGDIRTY_NODE_ENTRIES); i2++ )
- {
- unsigned int bytes = PAGE_SIZE;
- l1 = ((l2 && mfn_valid(l2[i2])) ?
-@@ -498,15 +555,28 @@ static int paging_log_dirty_op(struct domain *d,
- bytes = (unsigned int)((sc->pages - pages + 7) >> 3);
- if ( likely(peek) )
- {
-- if ( (l1 ? copy_to_guest_offset(sc->dirty_bitmap,
-- pages >> 3, (uint8_t *)l1,
-- bytes)
-- : clear_guest_offset(sc->dirty_bitmap,
-- pages >> 3, bytes)) != 0 )
-+ if ( pages >> (3 + PAGE_SHIFT) !=
-+ index_mapped >> (3 + PAGE_SHIFT) )
- {
-- rv = -EFAULT;
-- goto out;
-+ /* We need to map next page */
-+ d->arch.paging.preempt.log_dirty.i4 = i4;
-+ d->arch.paging.preempt.log_dirty.i3 = i3;
-+ d->arch.paging.preempt.log_dirty.i2 = i2;
-+ d->arch.paging.preempt.log_dirty.done = pages;
-+ d->arch.paging.preempt.dom = current->domain;
-+ d->arch.paging.preempt.op = sc->op;
-+ resuming = 1;
-+ paging_unlock(d);
-+ unmap_dirty_bitmap(dirty_bitmap, page);
-+ goto again;
- }
-+ ASSERT(((pages >> 3) % PAGE_SIZE) + bytes <= PAGE_SIZE);
-+ if ( l1 )
-+ memcpy(dirty_bitmap + ((pages >> 3) % PAGE_SIZE), l1,
-+ bytes);
-+ else
-+ memset(dirty_bitmap + ((pages >> 3) % PAGE_SIZE), 0,
-+ bytes);
- }
- pages += bytes << 3;
- if ( l1 )
-@@ -524,6 +594,7 @@ static int paging_log_dirty_op(struct domain *d,
- {
- d->arch.paging.preempt.log_dirty.i4 = i4;
- d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
-+ d->arch.paging.preempt.log_dirty.i2 = 0;
- rv = -ERESTART;
- break;
- }
-@@ -536,6 +607,7 @@ static int paging_log_dirty_op(struct domain *d,
- {
- d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
- d->arch.paging.preempt.log_dirty.i3 = 0;
-+ d->arch.paging.preempt.log_dirty.i2 = 0;
- rv = -ERESTART;
- }
- if ( rv )
-@@ -565,6 +637,7 @@ static int paging_log_dirty_op(struct domain *d,
- if ( rv )
- {
- /* Never leave the domain paused on real errors. */
-+ unmap_dirty_bitmap(dirty_bitmap, page);
- ASSERT(rv == -ERESTART);
- return rv;
- }
-@@ -577,12 +650,14 @@ static int paging_log_dirty_op(struct domain *d,
- * paging modes (shadow or hap). Safe because the domain is paused. */
- d->arch.paging.log_dirty.clean_dirty_bitmap(d);
- }
-+ unmap_dirty_bitmap(dirty_bitmap, page);
- domain_unpause(d);
- return rv;
-
- out:
- d->arch.paging.preempt.dom = NULL;
- paging_unlock(d);
-+ unmap_dirty_bitmap(dirty_bitmap, page);
- domain_unpause(d);
-
- if ( l1 )
-diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
-index 165e533..0dc1ed8 100644
---- a/xen/include/asm-x86/domain.h
-+++ b/xen/include/asm-x86/domain.h
-@@ -206,6 +206,7 @@ struct paging_domain {
- unsigned long done:PADDR_BITS - PAGE_SHIFT;
- unsigned long i4:PAGETABLE_ORDER;
- unsigned long i3:PAGETABLE_ORDER;
-+ unsigned long i2:PAGETABLE_ORDER;
- } log_dirty;
- };
- } preempt;
---
-2.7.4 (Apple Git-66)
-
Index: head/emulators/xen-kernel/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
===================================================================
--- head/emulators/xen-kernel/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
+++ head/emulators/xen-kernel/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
@@ -1,232 +0,0 @@
-From 39b704785a8d330c02e8e2d2368c80dbaf679bc0 Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Thu, 15 Jun 2017 12:05:14 +0100
-Subject: [PATCH 3/4] gnttab: Avoid potential double-put of maptrack entry
-
-Each grant mapping for a particular domain is tracked by an in-Xen
-"maptrack" entry. This entry is is referenced by a "handle", which is
-given to the guest when it calls gnttab_map_grant_ref().
-
-There are two types of mapping a particular handle can refer to:
-GNTMAP_host_map and GNTMAP_device_map. A given
-gnttab_unmap_grant_ref() call can remove either only one or both of
-these entries. When a particular handle has no entries left, it must
-be freed.
-
-gnttab_unmap_grant_ref() loops through its grant unmap request list
-twice. It first removes entries from any host pagetables and (if
-appropraite) iommus; then it does a single domain TLB flush; then it
-does the clean-up, including telling the granter that entries are no
-longer being used (if appropriate).
-
-At the moment, it's during the first pass that the maptrack flags are
-cleared, but the second pass that the maptrack entry is freed.
-
-Unfortunately this allows the following race, which results in a
-double-free:
-
- A: (pass 1) clear host_map
- B: (pass 1) clear device_map
- A: (pass 2) See that maptrack entry has no mappings, free it
- B: (pass 2) See that maptrack entry has no mappings, free it #
-
-Unfortunately, unlike the active entry pinning update, we can't simply
-move the maptrack flag changes to the second half, because the
-maptrack flags are used to determine if iommu entries need to be
-added: a domain's iommu must never have fewer permissions than the
-maptrack flags indicate, or a subsequent map_grant_ref() might fail to
-add the necessary iommu entries.
-
-Instead, free the maptrack entry in the first pass if there are no
-further mappings.
-
-This is part of XSA-218.
-
-Reported-by: Jan Beulich <jbeulich.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 79 +++++++++++++++++++++++++++++++++---------------
- 1 file changed, 54 insertions(+), 25 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index cfc483f..81a1a8b 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -98,8 +98,8 @@ struct gnttab_unmap_common {
- /* Shared state beteen *_unmap and *_unmap_complete */
- u16 flags;
- unsigned long frame;
-- struct grant_mapping *map;
- struct domain *rd;
-+ grant_ref_t ref;
- };
-
- /* Number of unmap operations that are done between each tlb flush */
-@@ -1079,6 +1079,8 @@ __gnttab_unmap_common(
- struct grant_table *lgt, *rgt;
- struct active_grant_entry *act;
- s16 rc = 0;
-+ struct grant_mapping *map;
-+ bool_t put_handle = 0;
-
- ld = current->domain;
- lgt = ld->grant_table;
-@@ -1092,11 +1094,11 @@ __gnttab_unmap_common(
- return;
- }
-
-- op->map = &maptrack_entry(lgt, op->handle);
-+ map = &maptrack_entry(lgt, op->handle);
-
- grant_read_lock(lgt);
-
-- if ( unlikely(!read_atomic(&op->map->flags)) )
-+ if ( unlikely(!read_atomic(&map->flags)) )
- {
- grant_read_unlock(lgt);
- gdprintk(XENLOG_INFO, "Zero flags for handle (%d).\n", op->handle);
-@@ -1104,7 +1106,7 @@ __gnttab_unmap_common(
- return;
- }
-
-- dom = op->map->domid;
-+ dom = map->domid;
- grant_read_unlock(lgt);
-
- if ( unlikely((rd = rcu_lock_domain_by_id(dom)) == NULL) )
-@@ -1129,16 +1131,43 @@ __gnttab_unmap_common(
-
- grant_read_lock(rgt);
-
-- op->flags = read_atomic(&op->map->flags);
-- if ( unlikely(!op->flags) || unlikely(op->map->domid != dom) )
-+ op->rd = rd;
-+ op->ref = map->ref;
-+
-+ /*
-+ * We can't assume there was no racing unmap for this maptrack entry,
-+ * and hence we can't assume map->ref is valid for rd. While the checks
-+ * below (with the active entry lock held) will reject any such racing
-+ * requests, we still need to make sure we don't attempt to acquire an
-+ * invalid lock.
-+ */
-+ smp_rmb();
-+ if ( unlikely(op->ref >= nr_grant_entries(rgt)) )
- {
-- gdprintk(XENLOG_WARNING, "Unstable handle %u\n", op->handle);
-+ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
- rc = GNTST_bad_handle;
-- goto unmap_out;
-+ goto unlock_out;
- }
-
-- op->rd = rd;
-- act = active_entry_acquire(rgt, op->map->ref);
-+ act = active_entry_acquire(rgt, op->ref);
-+
-+ /*
-+ * Note that we (ab)use the active entry lock here to protect against
-+ * multiple unmaps of the same mapping here. We don't want to hold lgt's
-+ * lock, and we only hold rgt's lock for reading (but the latter wouldn't
-+ * be the right one anyway). Hence the easiest is to rely on a lock we
-+ * hold anyway; see docs/misc/grant-tables.txt's "Locking" section.
-+ */
-+
-+ op->flags = read_atomic(&map->flags);
-+ smp_rmb();
-+ if ( unlikely(!op->flags) || unlikely(map->domid != dom) ||
-+ unlikely(map->ref != op->ref) )
-+ {
-+ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
-+ rc = GNTST_bad_handle;
-+ goto act_release_out;
-+ }
-
- if ( op->frame == 0 )
- {
-@@ -1151,7 +1180,7 @@ __gnttab_unmap_common(
- "Bad frame number doesn't match gntref. (%lx != %lx)\n",
- op->frame, act->frame);
-
-- op->map->flags &= ~GNTMAP_device_map;
-+ map->flags &= ~GNTMAP_device_map;
- }
-
- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
-@@ -1161,14 +1190,23 @@ __gnttab_unmap_common(
- op->flags)) < 0 )
- goto act_release_out;
-
-- op->map->flags &= ~GNTMAP_host_map;
-+ map->flags &= ~GNTMAP_host_map;
-+ }
-+
-+ if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
-+ {
-+ map->flags = 0;
-+ put_handle = 1;
- }
-
- act_release_out:
- active_entry_release(act);
-- unmap_out:
-+ unlock_out:
- grant_read_unlock(rgt);
-
-+ if ( put_handle )
-+ put_maptrack_handle(lgt, op->handle);
-+
- if ( rc == GNTST_okay && gnttab_need_iommu_mapping(ld) )
- {
- unsigned int kind;
-@@ -1205,7 +1243,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- grant_entry_header_t *sha;
- struct page_info *pg;
- uint16_t *status;
-- bool_t put_handle = 0;
-
- if ( rd == NULL )
- {
-@@ -1226,13 +1263,13 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- if ( rgt->gt_version == 0 )
- goto unlock_out;
-
-- act = active_entry_acquire(rgt, op->map->ref);
-- sha = shared_entry_header(rgt, op->map->ref);
-+ act = active_entry_acquire(rgt, op->ref);
-+ sha = shared_entry_header(rgt, op->ref);
-
- if ( rgt->gt_version == 1 )
- status = &sha->flags;
- else
-- status = &status_entry(rgt, op->map->ref);
-+ status = &status_entry(rgt, op->ref);
-
- if ( unlikely(op->frame != act->frame) )
- {
-@@ -1289,9 +1326,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- act->pin -= GNTPIN_hstw_inc;
- }
-
-- if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
-- put_handle = 1;
--
- if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
- !(op->flags & GNTMAP_readonly) )
- gnttab_clear_flag(_GTF_writing, status);
-@@ -1304,11 +1338,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- unlock_out:
- grant_read_unlock(rgt);
-
-- if ( put_handle )
-- {
-- op->map->flags = 0;
-- put_maptrack_handle(ld->grant_table, op->handle);
-- }
- rcu_unlock_domain(rd);
- }
-
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
===================================================================
--- head/emulators/xen-kernel/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
+++ head/emulators/xen-kernel/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
@@ -1,186 +0,0 @@
-From 5d491e3cf32ff03552db9d66e842964fec06dcd4 Mon Sep 17 00:00:00 2001
-From: George Dunlap <george.dunlap@citrix.com>
-Date: Fri, 2 Jun 2017 15:21:27 +0100
-Subject: [PATCH 3/4] gnttab: correct logic to get page references during map
- requests
-
-The rules for reference counting are somewhat complicated:
-
-* Each of GNTTAB_host_map and GNTTAB_device_map need their own
-reference count
-
-* If the mapping is writeable:
- - GNTTAB_host_map needs a type count under only some conditions
- - GNTTAB_device_map always needs a type count
-
-If the mapping succeeds, we need to keep all of these; if the mapping
-fails, we need to release whatever references we have acquired so far.
-
-Additionally, the code that does a lot of this calculation "inherits"
-a reference as part of the process of finding out who the owner is.
-
-Finally, if the grant is mapped as writeable (without the
-GNTMAP_readonly flag), but the hypervisor cannot grab a
-PGT_writeable_page type, the entire operation should fail.
-
-Unfortunately, the current code has several logic holes:
-
-* If a grant is mapped only GNTTAB_device_map, and with a writeable
- mapping, but in conditions where a *host* type count is not
- necessary, the code will fail to grab the necessary type count.
-
-* If a grant is mapped both GNTTAB_device_map and GNTTAB_host_map,
- with a writeable mapping, in conditions where the host type count is
- not necessary, *and* where the page cannot be changed to type
- PGT_writeable, the condition will not be detected.
-
-In both cases, this means that on success, the type count will be
-erroneously reduced when the grant is unmapped. In the second case,
-the type count will be erroneously reduced on the failure path as
-well. (In the first case the failure path logic has the same hole
-as the reference grabbing logic.)
-
-Additionally, the return value of get_page() is not checked; but this
-may fail even if the first get_page() succeeded due to a reference
-counting overflow.
-
-First of all, simplify the restoration logic by explicitly counting
-the reference and type references acquired.
-
-Consider each mapping type separately, explicitly marking the
-'incoming' reference as used so we know when we need to grab a second
-one.
-
-Finally, always check the return value of get_page[_type]() and go to
-the failure path if appropriate.
-
-This is part of XSA-224.
-
-Reported-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 58 +++++++++++++++++++++++++++---------------------
- 1 file changed, 33 insertions(+), 25 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index 452538e..5e92e2c 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -758,12 +758,12 @@ __gnttab_map_grant_ref(
- struct grant_table *lgt, *rgt;
- struct vcpu *led;
- int handle;
-- unsigned long frame = 0, nr_gets = 0;
-+ unsigned long frame = 0;
- struct page_info *pg = NULL;
- int rc = GNTST_okay;
- u32 old_pin;
- u32 act_pin;
-- unsigned int cache_flags;
-+ unsigned int cache_flags, refcnt = 0, typecnt = 0;
- struct active_grant_entry *act = NULL;
- struct grant_mapping *mt;
- grant_entry_header_t *shah;
-@@ -889,11 +889,17 @@ __gnttab_map_grant_ref(
- else
- owner = page_get_owner(pg);
-
-+ if ( owner )
-+ refcnt++;
-+
- if ( !pg || (owner == dom_io) )
- {
- /* Only needed the reference to confirm dom_io ownership. */
- if ( pg )
-+ {
- put_page(pg);
-+ refcnt--;
-+ }
-
- if ( paging_mode_external(ld) )
- {
-@@ -921,27 +927,38 @@ __gnttab_map_grant_ref(
- }
- else if ( owner == rd || owner == dom_cow )
- {
-- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
-+ if ( (op->flags & GNTMAP_device_map) && !(op->flags & GNTMAP_readonly) )
- {
- if ( (owner == dom_cow) ||
- !get_page_type(pg, PGT_writable_page) )
- goto could_not_pin;
-+ typecnt++;
- }
-
-- nr_gets++;
- if ( op->flags & GNTMAP_host_map )
- {
-- rc = create_grant_host_mapping(op->host_addr, frame, op->flags, 0);
-- if ( rc != GNTST_okay )
-- goto undo_out;
--
-+ /*
-+ * Only need to grab another reference if device_map claimed
-+ * the other one.
-+ */
- if ( op->flags & GNTMAP_device_map )
- {
-- nr_gets++;
-- (void)get_page(pg, rd);
-- if ( !(op->flags & GNTMAP_readonly) )
-- get_page_type(pg, PGT_writable_page);
-+ if ( !get_page(pg, rd) )
-+ goto could_not_pin;
-+ refcnt++;
-+ }
-+
-+ if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
-+ {
-+ if ( (owner == dom_cow) ||
-+ !get_page_type(pg, PGT_writable_page) )
-+ goto could_not_pin;
-+ typecnt++;
- }
-+
-+ rc = create_grant_host_mapping(op->host_addr, frame, op->flags, 0);
-+ if ( rc != GNTST_okay )
-+ goto undo_out;
- }
- }
- else
-@@ -950,8 +967,6 @@ __gnttab_map_grant_ref(
- if ( !rd->is_dying )
- gdprintk(XENLOG_WARNING, "Could not pin grant frame %lx\n",
- frame);
-- if ( owner != NULL )
-- put_page(pg);
- rc = GNTST_general_error;
- goto undo_out;
- }
-@@ -1014,18 +1029,11 @@ __gnttab_map_grant_ref(
- return;
-
- undo_out:
-- if ( nr_gets > 1 )
-- {
-- if ( !(op->flags & GNTMAP_readonly) )
-- put_page_type(pg);
-- put_page(pg);
-- }
-- if ( nr_gets > 0 )
-- {
-- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
-- put_page_type(pg);
-+ while ( typecnt-- )
-+ put_page_type(pg);
-+
-+ while ( refcnt-- )
- put_page(pg);
-- }
-
- grant_read_lock(rgt);
-
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0003-x86-MSI-disallow-redundant-enabling.patch
===================================================================
--- head/emulators/xen-kernel/files/0003-x86-MSI-disallow-redundant-enabling.patch
+++ head/emulators/xen-kernel/files/0003-x86-MSI-disallow-redundant-enabling.patch
@@ -1,55 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/MSI: disallow redundant enabling
-
-At the moment, Xen attempts to allow redundant enabling of MSI by
-having pci_enable_msi() return 0, and point to the existing MSI
-descriptor, when the msi already exists.
-
-Unfortunately, if subsequent errors are encountered, the cleanup
-paths assume pci_enable_msi() had done full initialization, and
-hence undo everything that was assumed to be done by that
-function without also undoing other setup that would normally
-occur only after that function was called (in map_domain_pirq()
-itself).
-
-Rather than try to make the redundant enabling case work properly, just
-forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
-is already set up.
-
-This is part of XSA-237.
-
-Reported-by: HW42 <hw42@ipsumj.de>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/x86/msi.c
-+++ b/xen/arch/x86/msi.c
-@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
- old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
- if ( old_desc )
- {
-- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
-+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
- msi->irq, msi->seg, msi->bus,
- PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
-- *desc = old_desc;
-- return 0;
-+ return -EEXIST;
- }
-
- old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
-@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
- old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
- if ( old_desc )
- {
-- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
-+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
- msi->irq, msi->seg, msi->bus,
- PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
-- *desc = old_desc;
-- return 0;
-+ return -EEXIST;
- }
-
- old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
Index: head/emulators/xen-kernel/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
===================================================================
--- head/emulators/xen-kernel/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
+++ head/emulators/xen-kernel/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
@@ -1,319 +0,0 @@
-From 3ad26b95cd9bacedad5ba503515cf6e618162be1 Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Thu, 15 Jun 2017 16:25:27 +0100
-Subject: [PATCH 4/4] gnttab: __gnttab_unmap_common_complete() is
- all-or-nothing
-
-All failures have to be detected in __gnttab_unmap_common(), the
-completion function must not skip part of its processing. In particular
-the GNTMAP_device_map related putting of page references and adjustment
-of pin count must not occur if __gnttab_unmap_common() signaled an
-error. Furthermore the function must not make adjustments to global
-state (here: clearing GNTTAB_device_map) before all possibly failing
-operations have been performed.
-
-There's one exception for IOMMU related failures: As IOMMU manipulation
-occurs after GNTMAP_*_map have been cleared already, the related page
-reference and pin count adjustments need to be done nevertheless. A
-fundamental requirement for the correctness of this is that
-iommu_{,un}map_page() crash any affected DomU in case of failure.
-
-The version check appears to be pointless (or could perhaps be a
-BUG_ON() or ASSERT()), but for the moment also move it.
-
-This is part of XSA-224.
-
-Reported-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
----
- xen/common/grant_table.c | 108 ++++++++++++++++++--------------------
- xen/include/asm-arm/grant_table.h | 2 +-
- xen/include/asm-x86/grant_table.h | 5 +-
- 3 files changed, 55 insertions(+), 60 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index 5e92e2c..025aad0 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -96,7 +96,7 @@ struct gnttab_unmap_common {
- int16_t status;
-
- /* Shared state beteen *_unmap and *_unmap_complete */
-- u16 flags;
-+ u16 done;
- unsigned long frame;
- struct domain *rd;
- grant_ref_t ref;
-@@ -948,7 +948,8 @@ __gnttab_map_grant_ref(
- refcnt++;
- }
-
-- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
-+ if ( gnttab_host_mapping_get_page_type(op->flags & GNTMAP_readonly,
-+ ld, rd) )
- {
- if ( (owner == dom_cow) ||
- !get_page_type(pg, PGT_writable_page) )
-@@ -1095,6 +1096,7 @@ __gnttab_unmap_common(
- struct active_grant_entry *act;
- s16 rc = 0;
- struct grant_mapping *map;
-+ unsigned int flags;
- bool_t put_handle = 0;
-
- ld = current->domain;
-@@ -1145,6 +1147,20 @@ __gnttab_unmap_common(
-
- grant_read_lock(rgt);
-
-+ if ( rgt->gt_version == 0 )
-+ {
-+ /*
-+ * This ought to be impossible, as such a mapping should not have
-+ * been established (see the nr_grant_entries(rgt) bounds check in
-+ * __gnttab_map_grant_ref()). Doing this check only in
-+ * __gnttab_unmap_common_complete() - as it used to be done - would,
-+ * however, be too late.
-+ */
-+ rc = GNTST_bad_gntref;
-+ flags = 0;
-+ goto unlock_out;
-+ }
-+
- op->rd = rd;
- op->ref = map->ref;
-
-@@ -1160,6 +1176,7 @@ __gnttab_unmap_common(
- {
- gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
- rc = GNTST_bad_handle;
-+ flags = 0;
- goto unlock_out;
- }
-
-@@ -1173,9 +1190,9 @@ __gnttab_unmap_common(
- * hold anyway; see docs/misc/grant-tables.txt's "Locking" section.
- */
-
-- op->flags = read_atomic(&map->flags);
-+ flags = read_atomic(&map->flags);
- smp_rmb();
-- if ( unlikely(!op->flags) || unlikely(map->domid != dom) ||
-+ if ( unlikely(!flags) || unlikely(map->domid != dom) ||
- unlikely(map->ref != op->ref) )
- {
- gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
-@@ -1185,24 +1202,27 @@ __gnttab_unmap_common(
-
- op->frame = act->frame;
-
-- if ( op->dev_bus_addr )
-- {
-- if ( unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
-- PIN_FAIL(act_release_out, GNTST_general_error,
-- "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
-- op->dev_bus_addr, pfn_to_paddr(act->frame));
--
-- map->flags &= ~GNTMAP_device_map;
-- }
-+ if ( op->dev_bus_addr &&
-+ unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
-+ PIN_FAIL(act_release_out, GNTST_general_error,
-+ "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
-+ op->dev_bus_addr, pfn_to_paddr(act->frame));
-
-- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
-+ if ( op->host_addr && (flags & GNTMAP_host_map) )
- {
- if ( (rc = replace_grant_host_mapping(op->host_addr,
- op->frame, op->new_addr,
-- op->flags)) < 0 )
-+ flags)) < 0 )
- goto act_release_out;
-
- map->flags &= ~GNTMAP_host_map;
-+ op->done |= GNTMAP_host_map | (flags & GNTMAP_readonly);
-+ }
-+
-+ if ( op->dev_bus_addr && (flags & GNTMAP_device_map) )
-+ {
-+ map->flags &= ~GNTMAP_device_map;
-+ op->done |= GNTMAP_device_map | (flags & GNTMAP_readonly);
- }
-
- if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
-@@ -1239,7 +1259,7 @@ __gnttab_unmap_common(
- }
-
- /* If just unmapped a writable mapping, mark as dirtied */
-- if ( rc == GNTST_okay && !(op->flags & GNTMAP_readonly) )
-+ if ( rc == GNTST_okay && !(flags & GNTMAP_readonly) )
- gnttab_mark_dirty(rd, op->frame);
-
- op->status = rc;
-@@ -1256,13 +1276,9 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- struct page_info *pg;
- uint16_t *status;
-
-- if ( rd == NULL )
-+ if ( !op->done )
- {
-- /*
-- * Suggests that __gntab_unmap_common failed in
-- * rcu_lock_domain_by_id() or earlier, and so we have nothing
-- * to complete
-- */
-+ /* __gntab_unmap_common() didn't do anything - nothing to complete. */
- return;
- }
-
-@@ -1272,8 +1288,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- rgt = rd->grant_table;
-
- grant_read_lock(rgt);
-- if ( rgt->gt_version == 0 )
-- goto unlock_out;
-
- act = active_entry_acquire(rgt, op->ref);
- sha = shared_entry_header(rgt, op->ref);
-@@ -1283,72 +1297,50 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
- else
- status = &status_entry(rgt, op->ref);
-
-- if ( op->dev_bus_addr &&
-- unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
-- {
-- /*
-- * Suggests that __gntab_unmap_common failed early and so
-- * nothing further to do
-- */
-- goto act_release_out;
-- }
--
- pg = mfn_to_page(op->frame);
-
-- if ( op->dev_bus_addr && (op->flags & GNTMAP_device_map) )
-+ if ( op->done & GNTMAP_device_map )
- {
- if ( !is_iomem_page(act->frame) )
- {
-- if ( op->flags & GNTMAP_readonly )
-+ if ( op->done & GNTMAP_readonly )
- put_page(pg);
- else
- put_page_and_type(pg);
- }
-
- ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
-- if ( op->flags & GNTMAP_readonly )
-+ if ( op->done & GNTMAP_readonly )
- act->pin -= GNTPIN_devr_inc;
- else
- act->pin -= GNTPIN_devw_inc;
- }
-
-- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
-+ if ( op->done & GNTMAP_host_map )
- {
-- if ( op->status != 0 )
-+ if ( !is_iomem_page(op->frame) )
- {
-- /*
-- * Suggests that __gntab_unmap_common failed in
-- * replace_grant_host_mapping() or IOMMU handling, so nothing
-- * further to do (short of re-establishing the mapping in the
-- * latter case).
-- */
-- goto act_release_out;
-- }
--
-- if ( !is_iomem_page(op->frame) )
-- {
-- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
-+ if ( gnttab_host_mapping_get_page_type(op->done & GNTMAP_readonly,
-+ ld, rd) )
- put_page_type(pg);
- put_page(pg);
- }
-
- ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
-- if ( op->flags & GNTMAP_readonly )
-+ if ( op->done & GNTMAP_readonly )
- act->pin -= GNTPIN_hstr_inc;
- else
- act->pin -= GNTPIN_hstw_inc;
- }
-
- if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
-- !(op->flags & GNTMAP_readonly) )
-+ !(op->done & GNTMAP_readonly) )
- gnttab_clear_flag(_GTF_writing, status);
-
- if ( act->pin == 0 )
- gnttab_clear_flag(_GTF_reading, status);
-
-- act_release_out:
- active_entry_release(act);
-- unlock_out:
- grant_read_unlock(rgt);
-
- rcu_unlock_domain(rd);
-@@ -1364,6 +1356,7 @@ __gnttab_unmap_grant_ref(
- common->handle = op->handle;
-
- /* Intialise these in case common contains old state */
-+ common->done = 0;
- common->new_addr = 0;
- common->rd = NULL;
- common->frame = 0;
-@@ -1429,6 +1422,7 @@ __gnttab_unmap_and_replace(
- common->handle = op->handle;
-
- /* Intialise these in case common contains old state */
-+ common->done = 0;
- common->dev_bus_addr = 0;
- common->rd = NULL;
- common->frame = 0;
-@@ -3389,7 +3383,9 @@ gnttab_release_mappings(
- if ( gnttab_release_host_mappings(d) &&
- !is_iomem_page(act->frame) )
- {
-- if ( gnttab_host_mapping_get_page_type(map, d, rd) )
-+ if ( gnttab_host_mapping_get_page_type((map->flags &
-+ GNTMAP_readonly),
-+ d, rd) )
- put_page_type(pg);
- put_page(pg);
- }
-diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
-index 5e076cc..d76c7c7 100644
---- a/xen/include/asm-arm/grant_table.h
-+++ b/xen/include/asm-arm/grant_table.h
-@@ -9,7 +9,7 @@ void gnttab_clear_flag(unsigned long nr, uint16_t *addr);
- int create_grant_host_mapping(unsigned long gpaddr,
- unsigned long mfn, unsigned int flags, unsigned int
- cache_flags);
--#define gnttab_host_mapping_get_page_type(op, d, rd) (0)
-+#define gnttab_host_mapping_get_page_type(ro, ld, rd) (0)
- int replace_grant_host_mapping(unsigned long gpaddr, unsigned long mfn,
- unsigned long new_gpaddr, unsigned int flags);
- void gnttab_mark_dirty(struct domain *d, unsigned long l);
-diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
-index 8c9bbcf..9ca631c 100644
---- a/xen/include/asm-x86/grant_table.h
-+++ b/xen/include/asm-x86/grant_table.h
-@@ -58,9 +58,8 @@ static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
- }
-
- /* Foreign mappings of HHVM-guest pages do not modify the type count. */
--#define gnttab_host_mapping_get_page_type(op, ld, rd) \
-- (!((op)->flags & GNTMAP_readonly) && \
-- (((ld) == (rd)) || !paging_mode_external(rd)))
-+#define gnttab_host_mapping_get_page_type(ro, ld, rd) \
-+ (!(ro) && (((ld) == (rd)) || !paging_mode_external(rd)))
-
- /* Done implicitly when page tables are destroyed. */
- #define gnttab_release_host_mappings(domain) ( paging_mode_external(domain) )
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0004-gnttab-correct-maptrack-table-accesses.patch
===================================================================
--- head/emulators/xen-kernel/files/0004-gnttab-correct-maptrack-table-accesses.patch
+++ head/emulators/xen-kernel/files/0004-gnttab-correct-maptrack-table-accesses.patch
@@ -1,84 +0,0 @@
-From bb765f7863e5d19eebcfb29c117e2909bce241e7 Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Thu, 15 Jun 2017 12:05:29 +0100
-Subject: [PATCH 4/4] gnttab: correct maptrack table accesses
-
-In order to observe a consistent (limit,pointer-table) pair, the reader
-needs to either hold the maptrack lock (in line with documentation) or
-both sides need to order their accesses suitably (the writer side
-barrier was removed by commit dff515dfea ["gnttab: use per-VCPU
-maptrack free lists"], and a read side barrier has never been there).
-
-Make the writer publish a new table page before limit (for bounds
-checks to work), and new list head last (for racing maptrack_entry()
-invocations to work). At the same time add read barriers to lockless
-readers.
-
-Additionally get_maptrack_handle() must not assume ->maptrack_head to
-not change behind its back: Another handle may be put (updating only
-->maptrack_tail) and then got or stolen (updating ->maptrack_head).
-
-This is part of XSA-218.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
----
- xen/common/grant_table.c | 13 +++++++++----
- 1 file changed, 9 insertions(+), 4 deletions(-)
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index 81a1a8b..c4d73af 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -395,7 +395,7 @@ get_maptrack_handle(
- struct grant_table *lgt)
- {
- struct vcpu *curr = current;
-- int i;
-+ unsigned int i, head;
- grant_handle_t handle;
- struct grant_mapping *new_mt;
-
-@@ -451,17 +451,20 @@ get_maptrack_handle(
- new_mt[i].ref = handle + i + 1;
- new_mt[i].vcpu = curr->vcpu_id;
- }
-- new_mt[i - 1].ref = curr->maptrack_head;
-
- /* Set tail directly if this is the first page for this VCPU. */
- if ( curr->maptrack_tail == MAPTRACK_TAIL )
- curr->maptrack_tail = handle + MAPTRACK_PER_PAGE - 1;
-
-- write_atomic(&curr->maptrack_head, handle + 1);
--
- lgt->maptrack[nr_maptrack_frames(lgt)] = new_mt;
-+ smp_wmb();
- lgt->maptrack_limit += MAPTRACK_PER_PAGE;
-
-+ do {
-+ new_mt[i - 1].ref = read_atomic(&curr->maptrack_head);
-+ head = cmpxchg(&curr->maptrack_head, new_mt[i - 1].ref, handle + 1);
-+ } while ( head != new_mt[i - 1].ref );
-+
- spin_unlock(&lgt->maptrack_lock);
-
- return handle;
-@@ -727,6 +730,7 @@ static unsigned int mapkind(
- for ( handle = 0; !(kind & MAPKIND_WRITE) &&
- handle < lgt->maptrack_limit; handle++ )
- {
-+ smp_rmb();
- map = &maptrack_entry(lgt, handle);
- if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) ||
- map->domid != rd->domain_id )
-@@ -1094,6 +1098,7 @@ __gnttab_unmap_common(
- return;
- }
-
-+ smp_rmb();
- map = &maptrack_entry(lgt, op->handle);
-
- grant_read_lock(lgt);
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
===================================================================
--- head/emulators/xen-kernel/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
+++ head/emulators/xen-kernel/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
@@ -1,124 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
-
-Mappings that had been set up before should not be torn down when
-handling unrelated errors.
-
-This is part of XSA-237.
-
-Reported-by: HW42 <hw42@ipsumj.de>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/x86/irq.c
-+++ b/xen/arch/x86/irq.c
-@@ -1252,7 +1252,8 @@ static int prepare_domain_irq_pirq(struc
- return -ENOMEM;
- }
- *pinfo = info;
-- return 0;
-+
-+ return !!err;
- }
-
- static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
-@@ -1295,7 +1296,10 @@ int init_domain_irq_mapping(struct domai
- continue;
- err = prepare_domain_irq_pirq(d, i, i, &info);
- if ( err )
-+ {
-+ ASSERT(err < 0);
- break;
-+ }
- set_domain_irq_pirq(d, i, info);
- }
-
-@@ -1903,6 +1907,7 @@ int map_domain_pirq(
- struct pirq *info;
- struct irq_desc *desc;
- unsigned long flags;
-+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
-
- ASSERT(spin_is_locked(&d->event_lock));
-
-@@ -1946,8 +1951,10 @@ int map_domain_pirq(
- }
-
- ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
-- if ( ret )
-+ if ( ret < 0 )
- goto revoke;
-+ if ( !ret )
-+ __set_bit(0, prepared);
-
- desc = irq_to_desc(irq);
-
-@@ -2019,8 +2026,10 @@ int map_domain_pirq(
- irq = create_irq(NUMA_NO_NODE);
- ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
- : irq;
-- if ( ret )
-+ if ( ret < 0 )
- break;
-+ if ( !ret )
-+ __set_bit(nr, prepared);
- msi_desc[nr].irq = irq;
-
- if ( irq_permit_access(d, irq) != 0 )
-@@ -2053,15 +2062,15 @@ int map_domain_pirq(
- desc->msi_desc = NULL;
- spin_unlock_irqrestore(&desc->lock, flags);
- }
-- while ( nr-- )
-+ while ( nr )
- {
- if ( irq >= 0 && irq_deny_access(d, irq) )
- printk(XENLOG_G_ERR
- "dom%d: could not revoke access to IRQ%d (pirq %d)\n",
- d->domain_id, irq, pirq);
-- if ( info )
-+ if ( info && test_bit(nr, prepared) )
- cleanup_domain_irq_pirq(d, irq, info);
-- info = pirq_info(d, pirq + nr);
-+ info = pirq_info(d, pirq + --nr);
- irq = info->arch.irq;
- }
- msi_desc->irq = -1;
-@@ -2077,12 +2086,14 @@ int map_domain_pirq(
- spin_lock_irqsave(&desc->lock, flags);
- set_domain_irq_pirq(d, irq, info);
- spin_unlock_irqrestore(&desc->lock, flags);
-+ ret = 0;
- }
-
- done:
- if ( ret )
- {
-- cleanup_domain_irq_pirq(d, irq, info);
-+ if ( test_bit(0, prepared) )
-+ cleanup_domain_irq_pirq(d, irq, info);
- revoke:
- if ( irq_deny_access(d, irq) )
- printk(XENLOG_G_ERR
---- a/xen/arch/x86/physdev.c
-+++ b/xen/arch/x86/physdev.c
-@@ -185,7 +185,7 @@ int physdev_map_pirq(domid_t domid, int
- }
- else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
- {
-- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
-+ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
- ret = -EDOM;
- else if ( msi->entry_nr != 1 && !iommu_intremap )
- ret = -EOPNOTSUPP;
---- a/xen/include/asm-x86/msi.h
-+++ b/xen/include/asm-x86/msi.h
-@@ -55,6 +55,8 @@
- /* MAX fixed pages reserved for mapping MSIX tables. */
- #define FIX_MSIX_MAX_PAGES 512
-
-+#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
-+
- struct msi_info {
- u16 seg;
- u8 bus;
Index: head/emulators/xen-kernel/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
===================================================================
--- head/emulators/xen-kernel/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
+++ head/emulators/xen-kernel/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
@@ -1,37 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
-
-The caller and the FLASK implementation of xsm_unmap_domain_irq()
-disagreed about what the "data" argument points to in the MSI case:
-Change both sides to pass/take a PCI device.
-
-This is part of XSA-237.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/irq.c
-+++ b/xen/arch/x86/irq.c
-@@ -2144,7 +2144,8 @@ int unmap_domain_pirq(struct domain *d,
- nr = msi_desc->msi.nvec;
- }
-
-- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
-+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
-+ msi_desc ? msi_desc->dev : NULL);
- if ( ret )
- goto done;
-
---- a/xen/xsm/flask/hooks.c
-+++ b/xen/xsm/flask/hooks.c
-@@ -915,8 +915,8 @@ static int flask_unmap_domain_msi (struc
- u32 *sid, struct avc_audit_data *ad)
- {
- #ifdef CONFIG_HAS_PCI
-- struct msi_info *msi = data;
-- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
-+ const struct pci_dev *pdev = data;
-+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
-
- AVC_AUDIT_DATA_INIT(ad, DEV);
- ad->device = machine_bdf;
Index: head/emulators/xen-kernel/files/kconf_arch.patch
===================================================================
--- head/emulators/xen-kernel/files/kconf_arch.patch
+++ head/emulators/xen-kernel/files/kconf_arch.patch
@@ -1,33 +0,0 @@
-diff --git a/xen/Makefile b/xen/Makefile
-index 0d5f240..f232d01 100644
---- a/xen/Makefile
-+++ b/xen/Makefile
-@@ -21,8 +21,8 @@ MAKEFLAGS += -rR
-
- EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi
-
--ARCH=$(XEN_TARGET_ARCH)
--SRCARCH=$(shell echo $(ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
-+KCONF_ARCH=$(XEN_TARGET_ARCH)
-+KCONF_SRCARCH=$(shell echo $(KCONF_ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
-
- # Don't break if the build process wasn't called from the top level
- # we need XEN_TARGET_ARCH to generate the proper config
-@@ -246,14 +246,14 @@ kconfig := silentoldconfig oldconfig config menuconfig defconfig \
- randconfig
- .PHONY: $(kconfig)
- $(kconfig):
-- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" $@
-+ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" $@
-
- include/config/%.conf: include/config/auto.conf.cmd $(KCONFIG_CONFIG)
-- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" silentoldconfig
-+ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" silentoldconfig
-
- # Allow people to just run `make` as before and not force them to configure
- $(KCONFIG_CONFIG):
-- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" defconfig
-+ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" defconfig
-
- # Break the dependency chain for the first run
- include/config/auto.conf.cmd: ;
Index: head/emulators/xen-kernel/files/xen.4th
===================================================================
--- head/emulators/xen-kernel/files/xen.4th
+++ head/emulators/xen-kernel/files/xen.4th
@@ -1,99 +0,0 @@
-\ Copyright (c) 2015 Devin Teske <dteske@FreeBSD.org>
-\ All rights reserved.
-\
-\ Redistribution and use in source and binary forms, with or without
-\ modification, are permitted provided that the following conditions
-\ are met:
-\ 1. Redistributions of source code must retain the above copyright
-\ notice, this list of conditions and the following disclaimer.
-\ 2. Redistributions in binary form must reproduce the above copyright
-\ notice, this list of conditions and the following disclaimer in the
-\ documentation and/or other materials provided with the distribution.
-\
-\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-\ SUCH DAMAGE.
-\
-\ $FreeBSD$
-
-create xenkerndefault 64 allot
-0 xenkerndefault c!
-
-also menu-command-helpers
-also menu-namespace
-
-: init_xen_active ( N -- N )
- s" [X]en Kernel.. off" 2 pick menu_caption[x] setenv
- s" [X]en Kernel.. On" 2 pick toggled_text[x] setenv
- s" toggle_xen" 2 pick menu_command[x] setenv
- s" 120" 2 pick menu_keycode[x] setenv
- s" ^[1mX^[men Kernel.. ^[34;1mOff^[m" 2 pick ansi_caption[x] setenv
- s" ^[1mX^[men Kernel.. ^[32;7mOn^[m" 2 pick toggled_ansi[x] setenv
-;
-
-: init_xen_inactive ( N -- N )
- s" Xen Kernel.. N/A" 2dup
- 4 pick menu_caption[x] setenv
- 2 pick ansi_caption[x] setenv
- s" true" 2 pick menu_command[x] setenv
-;
-
-: init_xen ( -- )
- s" optionsmenu_options" getenv 0> if
- c@ dup [char] 0 > over [char] 9 < and false = if
- drop [char] 0
- then
- 1+
- else
- [char] 1
- then
- begin
- dup [char] 8 > if
- false ( break )
- else
- dup s" optionsmenu_caption[x]" 20 +c! getenv -1 = if
- false ( break )
- else
- drop true
- then
- then
- while
- 1+
- repeat
-
- s" xen_kernel" getenv dup -1 <> over 0> and if
- xenkerndefault 1+ 0 2swap strcat swap 1- c!
- init_xen_active ( n -- n )
- toggle_menuitem ( n -- n )
- else
- drop
- xenkerndefault c@ 0<> if
- init_xen_active ( n -- n )
- else
- init_xen_inactive ( n -- n )
- then
- then
-;
-
-: toggle_xen ( N -- N TRUE )
- toggle_menuitem ( n -- n )
- menu-redraw
-
- dup toggle_stateN @ 0= if
- s" xen_kernel" unsetenv
- else
- xenkerndefault count s" xen_kernel" setenv
- then
-
- TRUE \ loop menu again
-;
-
-set optionsmenu_init="$optionsmenu_init init_xen"
Index: head/emulators/xen-kernel/files/xsa212.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa212.patch
+++ head/emulators/xen-kernel/files/xsa212.patch
@@ -1,87 +0,0 @@
-memory: properly check guest memory ranges in XENMEM_exchange handling
-
-The use of guest_handle_okay() here (as introduced by the XSA-29 fix)
-is insufficient here, guest_handle_subrange_okay() needs to be used
-instead.
-
-Note that the uses are okay in
-- XENMEM_add_to_physmap_batch handling due to the size field being only
- 16 bits wide,
-- livepatch_list() due to the limit of 1024 enforced on the
- number-of-entries input (leaving aside the fact that this can be
- called by a privileged domain only anyway),
-- compat mode handling due to counts there being limited to 32 bits,
-- everywhere else due to guest arrays being accessed sequentially from
- index zero.
-
-This is XSA-212.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/common/memory.c
-+++ b/xen/common/memory.c
-@@ -436,8 +436,8 @@ static long memory_exchange(XEN_GUEST_HA
- goto fail_early;
- }
-
-- if ( !guest_handle_okay(exch.in.extent_start, exch.in.nr_extents) ||
-- !guest_handle_okay(exch.out.extent_start, exch.out.nr_extents) )
-+ if ( !guest_handle_subrange_okay(exch.in.extent_start, exch.nr_exchanged,
-+ exch.in.nr_extents - 1) )
- {
- rc = -EFAULT;
- goto fail_early;
-@@ -447,11 +447,27 @@ static long memory_exchange(XEN_GUEST_HA
- {
- in_chunk_order = exch.out.extent_order - exch.in.extent_order;
- out_chunk_order = 0;
-+
-+ if ( !guest_handle_subrange_okay(exch.out.extent_start,
-+ exch.nr_exchanged >> in_chunk_order,
-+ exch.out.nr_extents - 1) )
-+ {
-+ rc = -EFAULT;
-+ goto fail_early;
-+ }
- }
- else
- {
- in_chunk_order = 0;
- out_chunk_order = exch.in.extent_order - exch.out.extent_order;
-+
-+ if ( !guest_handle_subrange_okay(exch.out.extent_start,
-+ exch.nr_exchanged << out_chunk_order,
-+ exch.out.nr_extents - 1) )
-+ {
-+ rc = -EFAULT;
-+ goto fail_early;
-+ }
- }
-
- d = rcu_lock_domain_by_any_id(exch.in.domid);
---- a/xen/include/asm-x86/x86_64/uaccess.h
-+++ b/xen/include/asm-x86/x86_64/uaccess.h
-@@ -29,8 +29,9 @@ extern void *xlat_malloc(unsigned long *
- /*
- * Valid if in +ve half of 48-bit address space, or above Xen-reserved area.
- * This is also valid for range checks (addr, addr+size). As long as the
-- * start address is outside the Xen-reserved area then we will access a
-- * non-canonical address (and thus fault) before ever reaching VIRT_START.
-+ * start address is outside the Xen-reserved area, sequential accesses
-+ * (starting at addr) will hit a non-canonical address (and thus fault)
-+ * before ever reaching VIRT_START.
- */
- #define __addr_ok(addr) \
- (((unsigned long)(addr) < (1UL<<47)) || \
-@@ -40,7 +41,8 @@ extern void *xlat_malloc(unsigned long *
- (__addr_ok(addr) || is_compat_arg_xlat_range(addr, size))
-
- #define array_access_ok(addr, count, size) \
-- (access_ok(addr, (count)*(size)))
-+ (likely(((count) ?: 0UL) < (~0UL / (size))) && \
-+ access_ok(addr, (count) * (size)))
-
- #define __compat_addr_ok(d, addr) \
- ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(d))
Index: head/emulators/xen-kernel/files/xsa213-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa213-4.7.patch
+++ head/emulators/xen-kernel/files/xsa213-4.7.patch
@@ -1,173 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: multicall: deal with early exit conditions
-
-In particular changes to guest privilege level require the multicall
-sequence to be aborted, as hypercalls are permitted from kernel mode
-only. While likely not very useful in a multicall, also properly handle
-the return value in the HYPERVISOR_iret case (which should be the guest
-specified value).
-
-This is XSA-213.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Acked-by: Julien Grall <julien.grall@arm.com>
-
---- a/xen/arch/arm/traps.c
-+++ b/xen/arch/arm/traps.c
-@@ -1529,30 +1529,33 @@ static bool_t check_multicall_32bit_clea
- return true;
- }
-
--void do_multicall_call(struct multicall_entry *multi)
-+enum mc_disposition do_multicall_call(struct multicall_entry *multi)
- {
- arm_hypercall_fn_t call = NULL;
-
- if ( multi->op >= ARRAY_SIZE(arm_hypercall_table) )
- {
- multi->result = -ENOSYS;
-- return;
-+ return mc_continue;
- }
-
- call = arm_hypercall_table[multi->op].fn;
- if ( call == NULL )
- {
- multi->result = -ENOSYS;
-- return;
-+ return mc_continue;
- }
-
- if ( is_32bit_domain(current->domain) &&
- !check_multicall_32bit_clean(multi) )
-- return;
-+ return mc_continue;
-
- multi->result = call(multi->args[0], multi->args[1],
- multi->args[2], multi->args[3],
- multi->args[4]);
-+
-+ return likely(!psr_mode_is_user(guest_cpu_user_regs()))
-+ ? mc_continue : mc_preempt;
- }
-
- /*
---- a/xen/common/multicall.c
-+++ b/xen/common/multicall.c
-@@ -40,6 +40,7 @@ do_multicall(
- struct mc_state *mcs = &current->mc_state;
- uint32_t i;
- int rc = 0;
-+ enum mc_disposition disp = mc_continue;
-
- if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
- {
-@@ -50,7 +51,7 @@ do_multicall(
- if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
- rc = -EFAULT;
-
-- for ( i = 0; !rc && i < nr_calls; i++ )
-+ for ( i = 0; !rc && disp == mc_continue && i < nr_calls; i++ )
- {
- if ( i && hypercall_preempt_check() )
- goto preempted;
-@@ -63,7 +64,7 @@ do_multicall(
-
- trace_multicall_call(&mcs->call);
-
-- do_multicall_call(&mcs->call);
-+ disp = do_multicall_call(&mcs->call);
-
- #ifndef NDEBUG
- {
-@@ -77,7 +78,14 @@ do_multicall(
- }
- #endif
-
-- if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
-+ if ( unlikely(disp == mc_exit) )
-+ {
-+ if ( __copy_field_to_guest(call_list, &mcs->call, result) )
-+ /* nothing, best effort only */;
-+ rc = mcs->call.result;
-+ }
-+ else if ( unlikely(__copy_field_to_guest(call_list, &mcs->call,
-+ result)) )
- rc = -EFAULT;
- else if ( mcs->flags & MCSF_call_preempted )
- {
-@@ -93,6 +101,9 @@ do_multicall(
- guest_handle_add_offset(call_list, 1);
- }
-
-+ if ( unlikely(disp == mc_preempt) && i < nr_calls )
-+ goto preempted;
-+
- perfc_incr(calls_to_multicall);
- perfc_add(calls_from_multicall, i);
- mcs->flags = 0;
---- a/xen/include/asm-arm/multicall.h
-+++ b/xen/include/asm-arm/multicall.h
-@@ -1,7 +1,11 @@
- #ifndef __ASM_ARM_MULTICALL_H__
- #define __ASM_ARM_MULTICALL_H__
-
--extern void do_multicall_call(struct multicall_entry *call);
-+extern enum mc_disposition {
-+ mc_continue,
-+ mc_exit,
-+ mc_preempt,
-+} do_multicall_call(struct multicall_entry *call);
-
- #endif /* __ASM_ARM_MULTICALL_H__ */
- /*
---- a/xen/include/asm-x86/multicall.h
-+++ b/xen/include/asm-x86/multicall.h
-@@ -7,8 +7,21 @@
-
- #include <xen/errno.h>
-
-+enum mc_disposition {
-+ mc_continue,
-+ mc_exit,
-+ mc_preempt,
-+};
-+
-+#define multicall_ret(call) \
-+ (unlikely((call)->op == __HYPERVISOR_iret) \
-+ ? mc_exit \
-+ : likely(guest_kernel_mode(current, \
-+ guest_cpu_user_regs())) \
-+ ? mc_continue : mc_preempt)
-+
- #define do_multicall_call(_call) \
-- do { \
-+ ({ \
- __asm__ __volatile__ ( \
- " movq %c1(%0),%%rax; " \
- " leaq hypercall_table(%%rip),%%rdi; " \
-@@ -37,9 +50,11 @@
- /* all the caller-saves registers */ \
- : "rax", "rcx", "rdx", "rsi", "rdi", \
- "r8", "r9", "r10", "r11" ); \
-- } while ( 0 )
-+ multicall_ret(_call); \
-+ })
-
- #define compat_multicall_call(_call) \
-+ ({ \
- __asm__ __volatile__ ( \
- " movl %c1(%0),%%eax; " \
- " leaq compat_hypercall_table(%%rip),%%rdi; "\
-@@ -67,6 +82,8 @@
- "i" (-ENOSYS) \
- /* all the caller-saves registers */ \
- : "rax", "rcx", "rdx", "rsi", "rdi", \
-- "r8", "r9", "r10", "r11" ) \
-+ "r8", "r9", "r10", "r11" ); \
-+ multicall_ret(_call); \
-+ })
-
- #endif /* __ASM_X86_MULTICALL_H__ */
Index: head/emulators/xen-kernel/files/xsa214.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa214.patch
+++ head/emulators/xen-kernel/files/xsa214.patch
@@ -1,41 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: discard type information when stealing pages
-
-While a page having just a single general reference left necessarily
-has a zero type reference count too, its type may still be valid (and
-in validated state; at present this is only possible and relevant for
-PGT_seg_desc_page, as page tables have their type forcibly zapped when
-their type reference count drops to zero, and
-PGT_{writable,shared}_page pages don't require any validation). In
-such a case when the page is being re-used with the same type again,
-validation is being skipped. As validation criteria differ between
-32- and 64-bit guests, pages to be transferred between guests need to
-have their validation indicator zapped (and with it we zap all other
-type information at once).
-
-This is XSA-214.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -4466,6 +4466,17 @@ int steal_page(
- y = cmpxchg(&page->count_info, x, x & ~PGC_count_mask);
- } while ( y != x );
-
-+ /*
-+ * With the sole reference dropped temporarily, no-one can update type
-+ * information. Type count also needs to be zero in this case, but e.g.
-+ * PGT_seg_desc_page may still have PGT_validated set, which we need to
-+ * clear before transferring ownership (as validation criteria vary
-+ * depending on domain type).
-+ */
-+ BUG_ON(page->u.inuse.type_info & (PGT_count_mask | PGT_locked |
-+ PGT_pinned));
-+ page->u.inuse.type_info = 0;
-+
- /* Swizzle the owner then reinstate the PGC_allocated reference. */
- page_set_owner(page, NULL);
- y = page->count_info;
Index: head/emulators/xen-kernel/files/xsa215.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa215.patch
+++ head/emulators/xen-kernel/files/xsa215.patch
@@ -1,37 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: correct create_bounce_frame
-
-We may push up to 96 bytes on the guest (kernel) stack, so we should
-also cover as much in the early range check. Note that this is the
-simplest possible patch, which has the theoretical potential of
-breaking a guest: We only really push 96 bytes when invoking the
-failsafe callback, ordinary exceptions only have 56 or 64 bytes pushed
-(without / with error code respectively). There is, however, no PV OS
-known to place a kernel stack there.
-
-This is XSA-215.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/x86_64/entry.S
-+++ b/xen/arch/x86/x86_64/entry.S
-@@ -347,7 +347,7 @@ int80_slow_path:
- jmp handle_exception_saved
-
- /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
--/* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
-+/* { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
- /* %rdx: trap_bounce, %rbx: struct vcpu */
- /* On return only %rbx and %rdx are guaranteed non-clobbered. */
- create_bounce_frame:
-@@ -367,7 +367,7 @@ create_bounce_frame:
- 2: andq $~0xf,%rsi # Stack frames are 16-byte aligned.
- movq $HYPERVISOR_VIRT_START,%rax
- cmpq %rax,%rsi
-- movq $HYPERVISOR_VIRT_END+60,%rax
-+ movq $HYPERVISOR_VIRT_END+12*8,%rax
- sbb %ecx,%ecx # In +ve address space? Then okay.
- cmpq %rax,%rsi
- adc %ecx,%ecx # Above Xen private area? Then okay.
Index: head/emulators/xen-kernel/files/xsa217.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa217.patch
+++ head/emulators/xen-kernel/files/xsa217.patch
@@ -1,41 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/mm: disallow page stealing from HVM domains
-
-The operation's success can't be controlled by the guest, as the device
-model may have an active mapping of the page. If we nevertheless
-permitted this operation, we'd have to add further TLB flushing to
-prevent scenarios like
-
-"Domains A (HVM), B (PV), C (PV); B->target==A
- Steps:
- 1. B maps page X from A as writable
- 2. B unmaps page X without a TLB flush
- 3. A sends page X to C via GNTTABOP_transfer
- 4. C maps page X as pagetable (potentially causing a TLB flush in C,
- but not in B)
-
- At this point, X would be mapped as a pagetable in C while being
- writable through a stale TLB entry in B."
-
-A similar scenario could be constructed for A using XENMEM_exchange and
-some arbitrary PV domain C then having this page allocated.
-
-This is XSA-217.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Acked-by: George Dunlap <george.dunlap@citrix.com>
-Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -4449,6 +4449,9 @@ int steal_page(
- bool_t drop_dom_ref = 0;
- const struct domain *owner = dom_xen;
-
-+ if ( paging_mode_external(d) )
-+ return -1;
-+
- spin_lock(&d->page_alloc_lock);
-
- if ( is_xen_heap_page(page) || ((owner = page_get_owner(page)) != d) )
Index: head/emulators/xen-kernel/files/xsa219-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa219-4.8.patch
+++ head/emulators/xen-kernel/files/xsa219-4.8.patch
@@ -1,151 +0,0 @@
-From 3986b845e87c3f963227ece86bb633450761ec18 Mon Sep 17 00:00:00 2001
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Date: Thu, 11 May 2017 14:47:00 +0100
-Subject: [PATCH] x86/shadow: Hold references for the duration of emulated
- writes
-
-The (misnamed) emulate_gva_to_mfn() function translates a linear address to an
-mfn, but releases its page reference before returning the mfn to its caller.
-
-sh_emulate_map_dest() uses the results of one or two translations to construct
-a virtual mapping to the underlying frames, completes an emulated
-write/cmpxchg, then unmaps the virtual mappings.
-
-The page references need holding until the mappings are unmapped, or the
-frames can change ownership before the writes occurs.
-
-This is XSA-219
-
-Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Tim Deegan <tim@xen.org>
----
- xen/arch/x86/mm/shadow/common.c | 54 +++++++++++++++++++++++++++--------------
- 1 file changed, 36 insertions(+), 18 deletions(-)
-
-diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
-index ced2313..13305d2 100644
---- a/xen/arch/x86/mm/shadow/common.c
-+++ b/xen/arch/x86/mm/shadow/common.c
-@@ -1703,7 +1703,10 @@ static unsigned int shadow_get_allocation(struct domain *d)
- /**************************************************************************/
- /* Handling guest writes to pagetables. */
-
--/* Translate a VA to an MFN, injecting a page-fault if we fail. */
-+/*
-+ * Translate a VA to an MFN, injecting a page-fault if we fail. If the
-+ * mapping succeeds, a reference will be held on the underlying page.
-+ */
- #define BAD_GVA_TO_GFN (~0UL)
- #define BAD_GFN_TO_MFN (~1UL)
- #define READONLY_GFN (~2UL)
-@@ -1751,16 +1754,15 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v, unsigned long vaddr,
- ASSERT(mfn_valid(mfn));
-
- v->arch.paging.last_write_was_pt = !!sh_mfn_is_a_page_table(mfn);
-- /*
-- * Note shadow cannot page out or unshare this mfn, so the map won't
-- * disappear. Otherwise, caller must hold onto page until done.
-- */
-- put_page(page);
-
- return mfn;
- }
-
--/* Check that the user is allowed to perform this write. */
-+/*
-+ * Check that the user is allowed to perform this write. If a mapping is
-+ * returned, page references will be held on sh_ctxt->mfn[0] and
-+ * sh_ctxt->mfn[1] iff !INVALID_MFN.
-+ */
- void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
- unsigned int bytes,
- struct sh_emulate_ctxt *sh_ctxt)
-@@ -1768,13 +1770,6 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
- struct domain *d = v->domain;
- void *map;
-
-- sh_ctxt->mfn[0] = emulate_gva_to_mfn(v, vaddr, sh_ctxt);
-- if ( !mfn_valid(sh_ctxt->mfn[0]) )
-- return ((mfn_x(sh_ctxt->mfn[0]) == BAD_GVA_TO_GFN) ?
-- MAPPING_EXCEPTION :
-- (mfn_x(sh_ctxt->mfn[0]) == READONLY_GFN) ?
-- MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE);
--
- #ifndef NDEBUG
- /* We don't emulate user-mode writes to page tables. */
- if ( has_hvm_container_domain(d)
-@@ -1787,6 +1782,17 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
- }
- #endif
-
-+ sh_ctxt->mfn[0] = emulate_gva_to_mfn(v, vaddr, sh_ctxt);
-+ if ( !mfn_valid(sh_ctxt->mfn[0]) )
-+ {
-+ switch ( mfn_x(sh_ctxt->mfn[0]) )
-+ {
-+ case BAD_GVA_TO_GFN: return MAPPING_EXCEPTION;
-+ case READONLY_GFN: return MAPPING_SILENT_FAIL;
-+ default: return MAPPING_UNHANDLEABLE;
-+ }
-+ }
-+
- /* Unaligned writes mean probably this isn't a pagetable. */
- if ( vaddr & (bytes - 1) )
- sh_remove_shadows(d, sh_ctxt->mfn[0], 0, 0 /* Slow, can fail. */ );
-@@ -1803,6 +1809,7 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
- * Cross-page emulated writes are only supported for HVM guests;
- * PV guests ought to know better.
- */
-+ put_page(mfn_to_page(sh_ctxt->mfn[0]));
- return MAPPING_UNHANDLEABLE;
- }
- else
-@@ -1810,17 +1817,26 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
- /* This write crosses a page boundary. Translate the second page. */
- sh_ctxt->mfn[1] = emulate_gva_to_mfn(v, vaddr + bytes - 1, sh_ctxt);
- if ( !mfn_valid(sh_ctxt->mfn[1]) )
-- return ((mfn_x(sh_ctxt->mfn[1]) == BAD_GVA_TO_GFN) ?
-- MAPPING_EXCEPTION :
-- (mfn_x(sh_ctxt->mfn[1]) == READONLY_GFN) ?
-- MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE);
-+ {
-+ put_page(mfn_to_page(sh_ctxt->mfn[0]));
-+ switch ( mfn_x(sh_ctxt->mfn[1]) )
-+ {
-+ case BAD_GVA_TO_GFN: return MAPPING_EXCEPTION;
-+ case READONLY_GFN: return MAPPING_SILENT_FAIL;
-+ default: return MAPPING_UNHANDLEABLE;
-+ }
-+ }
-
- /* Cross-page writes mean probably not a pagetable. */
- sh_remove_shadows(d, sh_ctxt->mfn[1], 0, 0 /* Slow, can fail. */ );
-
- map = vmap(sh_ctxt->mfn, 2);
- if ( !map )
-+ {
-+ put_page(mfn_to_page(sh_ctxt->mfn[0]));
-+ put_page(mfn_to_page(sh_ctxt->mfn[1]));
- return MAPPING_UNHANDLEABLE;
-+ }
- map += (vaddr & ~PAGE_MASK);
- }
-
-@@ -1890,10 +1906,12 @@ void sh_emulate_unmap_dest(struct vcpu *v, void *addr, unsigned int bytes,
- }
-
- paging_mark_dirty(v->domain, mfn_x(sh_ctxt->mfn[0]));
-+ put_page(mfn_to_page(sh_ctxt->mfn[0]));
-
- if ( unlikely(mfn_valid(sh_ctxt->mfn[1])) )
- {
- paging_mark_dirty(v->domain, mfn_x(sh_ctxt->mfn[1]));
-+ put_page(mfn_to_page(sh_ctxt->mfn[1]));
- vunmap((void *)((unsigned long)addr & PAGE_MASK));
- }
- else
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/xsa220-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa220-4.7.patch
+++ head/emulators/xen-kernel/files/xsa220-4.7.patch
@@ -1,133 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: avoid leaking PKRU and BND* between vCPU-s
-
-PKRU is explicitly "XSAVE-managed but not XSAVE-enabled", so guests
-might access the register (via {RD,WR}PKRU) without setting XCR0.PKRU.
-Force context switching as well as migrating the register as soon as
-CR4.PKE is being set the first time.
-
-For MPX (BND<n>, BNDCFGU, and BNDSTATUS) the situation is less clear,
-and the SDM has not entirely consistent information for that case.
-While experimentally the instructions don't change register state as
-long as the two XCR0 bits aren't both 1, be on the safe side and enable
-both if BNDCFGS.EN is being set the first time.
-
-This is XSA-220.
-
-Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/hvm/hvm.c
-+++ b/xen/arch/x86/hvm/hvm.c
-@@ -2452,6 +2452,27 @@ int hvm_set_cr4(unsigned long value, boo
- paging_update_paging_modes(v);
- }
-
-+ /*
-+ * {RD,WR}PKRU are not gated on XCR0.PKRU and hence an oddly behaving
-+ * guest may enable the feature in CR4 without enabling it in XCR0. We
-+ * need to context switch / migrate PKRU nevertheless.
-+ */
-+ if ( (value & X86_CR4_PKE) && !(v->arch.xcr0_accum & XSTATE_PKRU) )
-+ {
-+ int rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
-+ get_xcr0() | XSTATE_PKRU);
-+
-+ if ( rc )
-+ {
-+ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.PKRU: %d", rc);
-+ goto gpf;
-+ }
-+
-+ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
-+ get_xcr0() & ~XSTATE_PKRU) )
-+ /* nothing, best effort only */;
-+ }
-+
- return X86EMUL_OKAY;
-
- gpf:
---- a/xen/arch/x86/hvm/vmx/vmx.c
-+++ b/xen/arch/x86/hvm/vmx/vmx.c
-@@ -31,6 +31,7 @@
- #include <asm/regs.h>
- #include <asm/cpufeature.h>
- #include <asm/processor.h>
-+#include <asm/xstate.h>
- #include <asm/guest_access.h>
- #include <asm/debugreg.h>
- #include <asm/msr.h>
-@@ -783,6 +784,45 @@ static int vmx_load_vmcs_ctxt(struct vcp
- return 0;
- }
-
-+static bool_t vmx_set_guest_bndcfgs(struct vcpu *v, u64 val)
-+{
-+ if ( !cpu_has_mpx || !cpu_has_vmx_mpx ||
-+ !is_canonical_address(val) ||
-+ (val & IA32_BNDCFGS_RESERVED) )
-+ return 0;
-+
-+ /*
-+ * While MPX instructions are supposed to be gated on XCR0.BND*, let's
-+ * nevertheless force the relevant XCR0 bits on when the feature is being
-+ * enabled in BNDCFGS.
-+ */
-+ if ( (val & IA32_BNDCFGS_ENABLE) &&
-+ !(v->arch.xcr0_accum & (XSTATE_BNDREGS | XSTATE_BNDCSR)) )
-+ {
-+ uint64_t xcr0 = get_xcr0();
-+ int rc;
-+
-+ if ( v != current )
-+ return 0;
-+
-+ rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
-+ xcr0 | XSTATE_BNDREGS | XSTATE_BNDCSR);
-+
-+ if ( rc )
-+ {
-+ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.BND*: %d", rc);
-+ return 0;
-+ }
-+
-+ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK, xcr0) )
-+ /* nothing, best effort only */;
-+ }
-+
-+ __vmwrite(GUEST_BNDCFGS, val);
-+
-+ return 1;
-+}
-+
- static unsigned int __init vmx_init_msr(void)
- {
- return (cpu_has_mpx && cpu_has_vmx_mpx) +
-@@ -822,11 +862,8 @@ static int vmx_load_msr(struct vcpu *v,
- switch ( ctxt->msr[i].index )
- {
- case MSR_IA32_BNDCFGS:
-- if ( cpu_has_mpx && cpu_has_vmx_mpx &&
-- is_canonical_address(ctxt->msr[i].val) &&
-- !(ctxt->msr[i].val & IA32_BNDCFGS_RESERVED) )
-- __vmwrite(GUEST_BNDCFGS, ctxt->msr[i].val);
-- else if ( ctxt->msr[i].val )
-+ if ( !vmx_set_guest_bndcfgs(v, ctxt->msr[i].val) &&
-+ ctxt->msr[i].val )
- err = -ENXIO;
- break;
- case MSR_IA32_XSS:
-@@ -2878,11 +2915,8 @@ static int vmx_msr_write_intercept(unsig
- break;
- }
- case MSR_IA32_BNDCFGS:
-- if ( !cpu_has_mpx || !cpu_has_vmx_mpx ||
-- !is_canonical_address(msr_content) ||
-- (msr_content & IA32_BNDCFGS_RESERVED) )
-+ if ( !vmx_set_guest_bndcfgs(v, msr_content) )
- goto gp_fault;
-- __vmwrite(GUEST_BNDCFGS, msr_content);
- break;
- case IA32_FEATURE_CONTROL_MSR:
- case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS:
Index: head/emulators/xen-kernel/files/xsa221.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa221.patch
+++ head/emulators/xen-kernel/files/xsa221.patch
@@ -1,194 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: evtchn: avoid NULL derefs
-
-Commit fbbd5009e6 ("evtchn: refactor low-level event channel port ops")
-added a de-reference of the struct evtchn pointer for a port without
-first making sure the bucket pointer is non-NULL. This de-reference is
-actually entirely unnecessary, as all relevant callers (beyond the
-problematic do_poll()) already hold the port number in their hands, and
-the actual leaf functions need nothing else.
-
-For FIFO event channels there's a second problem in that the ordering
-of reads and updates to ->num_evtchns and ->event_array[] was so far
-undefined (the read side isn't always holding the domain's event lock).
-Add respective barriers.
-
-This is XSA-221.
-
-Reported-by: Ankur Arora <ankur.a.arora@oracle.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/arch/x86/irq.c
-+++ b/xen/arch/x86/irq.c
-@@ -1486,7 +1486,7 @@ int pirq_guest_unmask(struct domain *d)
- {
- pirq = pirqs[i]->pirq;
- if ( pirqs[i]->masked &&
-- !evtchn_port_is_masked(d, evtchn_from_port(d, pirqs[i]->evtchn)) )
-+ !evtchn_port_is_masked(d, pirqs[i]->evtchn) )
- pirq_guest_eoi(pirqs[i]);
- }
- } while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
-@@ -2244,7 +2244,6 @@ static void dump_irqs(unsigned char key)
- int i, irq, pirq;
- struct irq_desc *desc;
- irq_guest_action_t *action;
-- struct evtchn *evtchn;
- struct domain *d;
- const struct pirq *info;
- unsigned long flags;
-@@ -2287,11 +2286,10 @@ static void dump_irqs(unsigned char key)
- d = action->guest[i];
- pirq = domain_irq_to_pirq(d, irq);
- info = pirq_info(d, pirq);
-- evtchn = evtchn_from_port(d, info->evtchn);
- printk("%u:%3d(%c%c%c)",
- d->domain_id, pirq,
-- (evtchn_port_is_pending(d, evtchn) ? 'P' : '-'),
-- (evtchn_port_is_masked(d, evtchn) ? 'M' : '-'),
-+ evtchn_port_is_pending(d, info->evtchn) ? 'P' : '-',
-+ evtchn_port_is_masked(d, info->evtchn) ? 'M' : '-',
- (info->masked ? 'M' : '-'));
- if ( i != action->nr_guests )
- printk(",");
---- a/xen/common/event_2l.c
-+++ b/xen/common/event_2l.c
-@@ -61,16 +61,20 @@ static void evtchn_2l_unmask(struct doma
- }
- }
-
--static bool_t evtchn_2l_is_pending(struct domain *d,
-- const struct evtchn *evtchn)
-+static bool_t evtchn_2l_is_pending(struct domain *d, evtchn_port_t port)
- {
-- return test_bit(evtchn->port, &shared_info(d, evtchn_pending));
-+ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
-+
-+ ASSERT(port < max_ports);
-+ return port < max_ports && test_bit(port, &shared_info(d, evtchn_pending));
- }
-
--static bool_t evtchn_2l_is_masked(struct domain *d,
-- const struct evtchn *evtchn)
-+static bool_t evtchn_2l_is_masked(struct domain *d, evtchn_port_t port)
- {
-- return test_bit(evtchn->port, &shared_info(d, evtchn_mask));
-+ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
-+
-+ ASSERT(port < max_ports);
-+ return port >= max_ports || test_bit(port, &shared_info(d, evtchn_mask));
- }
-
- static void evtchn_2l_print_state(struct domain *d,
---- a/xen/common/event_channel.c
-+++ b/xen/common/event_channel.c
-@@ -1380,8 +1380,8 @@ static void domain_dump_evtchn_info(stru
-
- printk(" %4u [%d/%d/",
- port,
-- !!evtchn_port_is_pending(d, chn),
-- !!evtchn_port_is_masked(d, chn));
-+ evtchn_port_is_pending(d, port),
-+ evtchn_port_is_masked(d, port));
- evtchn_port_print_state(d, chn);
- printk("]: s=%d n=%d x=%d",
- chn->state, chn->notify_vcpu_id, chn->xen_consumer);
---- a/xen/common/event_fifo.c
-+++ b/xen/common/event_fifo.c
-@@ -27,6 +27,12 @@ static inline event_word_t *evtchn_fifo_
- if ( unlikely(port >= d->evtchn_fifo->num_evtchns) )
- return NULL;
-
-+ /*
-+ * Callers aren't required to hold d->event_lock, so we need to synchronize
-+ * with add_page_to_event_array().
-+ */
-+ smp_rmb();
-+
- p = port / EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
- w = port % EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
-
-@@ -287,24 +293,22 @@ static void evtchn_fifo_unmask(struct do
- evtchn_fifo_set_pending(v, evtchn);
- }
-
--static bool_t evtchn_fifo_is_pending(struct domain *d,
-- const struct evtchn *evtchn)
-+static bool_t evtchn_fifo_is_pending(struct domain *d, evtchn_port_t port)
- {
- event_word_t *word;
-
-- word = evtchn_fifo_word_from_port(d, evtchn->port);
-+ word = evtchn_fifo_word_from_port(d, port);
- if ( unlikely(!word) )
- return 0;
-
- return test_bit(EVTCHN_FIFO_PENDING, word);
- }
-
--static bool_t evtchn_fifo_is_masked(struct domain *d,
-- const struct evtchn *evtchn)
-+static bool_t evtchn_fifo_is_masked(struct domain *d, evtchn_port_t port)
- {
- event_word_t *word;
-
-- word = evtchn_fifo_word_from_port(d, evtchn->port);
-+ word = evtchn_fifo_word_from_port(d, port);
- if ( unlikely(!word) )
- return 1;
-
-@@ -593,6 +597,10 @@ static int add_page_to_event_array(struc
- return rc;
-
- d->evtchn_fifo->event_array[slot] = virt;
-+
-+ /* Synchronize with evtchn_fifo_word_from_port(). */
-+ smp_wmb();
-+
- d->evtchn_fifo->num_evtchns += EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
-
- /*
---- a/xen/common/schedule.c
-+++ b/xen/common/schedule.c
-@@ -965,7 +965,7 @@ static long do_poll(struct sched_poll *s
- goto out;
-
- rc = 0;
-- if ( evtchn_port_is_pending(d, evtchn_from_port(d, port)) )
-+ if ( evtchn_port_is_pending(d, port) )
- goto out;
- }
-
---- a/xen/include/xen/event.h
-+++ b/xen/include/xen/event.h
-@@ -137,8 +137,8 @@ struct evtchn_port_ops {
- void (*set_pending)(struct vcpu *v, struct evtchn *evtchn);
- void (*clear_pending)(struct domain *d, struct evtchn *evtchn);
- void (*unmask)(struct domain *d, struct evtchn *evtchn);
-- bool_t (*is_pending)(struct domain *d, const struct evtchn *evtchn);
-- bool_t (*is_masked)(struct domain *d, const struct evtchn *evtchn);
-+ bool_t (*is_pending)(struct domain *d, evtchn_port_t port);
-+ bool_t (*is_masked)(struct domain *d, evtchn_port_t port);
- /*
- * Is the port unavailable because it's still being cleaned up
- * after being closed?
-@@ -175,15 +175,15 @@ static inline void evtchn_port_unmask(st
- }
-
- static inline bool_t evtchn_port_is_pending(struct domain *d,
-- const struct evtchn *evtchn)
-+ evtchn_port_t port)
- {
-- return d->evtchn_port_ops->is_pending(d, evtchn);
-+ return d->evtchn_port_ops->is_pending(d, port);
- }
-
- static inline bool_t evtchn_port_is_masked(struct domain *d,
-- const struct evtchn *evtchn)
-+ evtchn_port_t port)
- {
-- return d->evtchn_port_ops->is_masked(d, evtchn);
-+ return d->evtchn_port_ops->is_masked(d, port);
- }
-
- static inline bool_t evtchn_port_is_busy(struct domain *d, evtchn_port_t port)
Index: head/emulators/xen-kernel/files/xsa222-1-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa222-1-4.7.patch
+++ head/emulators/xen-kernel/files/xsa222-1-4.7.patch
@@ -1,119 +0,0 @@
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Subject: xen/memory: Fix return value handing of guest_remove_page()
-
-Despite the description in mm.h, guest_remove_page() previously returned 0 for
-paging errors.
-
-Switch guest_remove_page() to having regular 0/-error semantics, and propagate
-the return values from clear_mmio_p2m_entry() and mem_sharing_unshare_page()
-to the callers (although decrease_reservation() is the only caller which
-currently cares).
-
-This is part of XSA-222.
-
-Reported-by: Julien Grall <julien.grall@arm.com>
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/common/memory.c
-+++ b/xen/common/memory.c
-@@ -244,6 +244,7 @@ int guest_remove_page(struct domain *d,
- p2m_type_t p2mt;
- #endif
- unsigned long mfn;
-+ int rc;
-
- #ifdef CONFIG_X86
- mfn = mfn_x(get_gfn_query(d, gmfn, &p2mt));
-@@ -261,13 +262,15 @@ int guest_remove_page(struct domain *d,
- put_page(page);
- }
- p2m_mem_paging_drop_page(d, gmfn, p2mt);
-- return 1;
-+
-+ return 0;
- }
- if ( p2mt == p2m_mmio_direct )
- {
-- clear_mmio_p2m_entry(d, gmfn, _mfn(mfn), 0);
-+ rc = clear_mmio_p2m_entry(d, gmfn, _mfn(mfn), PAGE_ORDER_4K);
- put_gfn(d, gmfn);
-- return 1;
-+
-+ return rc;
- }
- #else
- mfn = gmfn_to_mfn(d, gmfn);
-@@ -277,21 +280,25 @@ int guest_remove_page(struct domain *d,
- put_gfn(d, gmfn);
- gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
- d->domain_id, gmfn);
-- return 0;
-+
-+ return -EINVAL;
- }
-
- #ifdef CONFIG_X86
- if ( p2m_is_shared(p2mt) )
- {
-- /* Unshare the page, bail out on error. We unshare because
-- * we might be the only one using this shared page, and we
-- * need to trigger proper cleanup. Once done, this is
-- * like any other page. */
-- if ( mem_sharing_unshare_page(d, gmfn, 0) )
-+ /*
-+ * Unshare the page, bail out on error. We unshare because we
-+ * might be the only one using this shared page, and we need to
-+ * trigger proper cleanup. Once done, this is like any other page.
-+ */
-+ rc = mem_sharing_unshare_page(d, gmfn, 0);
-+ if ( rc )
- {
- put_gfn(d, gmfn);
- (void)mem_sharing_notify_enomem(d, gmfn, 0);
-- return 0;
-+
-+ return rc;
- }
- /* Maybe the mfn changed */
- mfn = mfn_x(get_gfn_query_unlocked(d, gmfn, &p2mt));
-@@ -304,7 +311,8 @@ int guest_remove_page(struct domain *d,
- {
- put_gfn(d, gmfn);
- gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
-- return 0;
-+
-+ return -ENXIO;
- }
-
- if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
-@@ -327,7 +335,7 @@ int guest_remove_page(struct domain *d,
- put_page(page);
- put_gfn(d, gmfn);
-
-- return 1;
-+ return 0;
- }
-
- static void decrease_reservation(struct memop_args *a)
-@@ -371,7 +379,7 @@ static void decrease_reservation(struct
- continue;
-
- for ( j = 0; j < (1 << a->extent_order); j++ )
-- if ( !guest_remove_page(a->domain, gmfn + j) )
-+ if ( guest_remove_page(a->domain, gmfn + j) )
- goto out;
- }
-
---- a/xen/include/xen/mm.h
-+++ b/xen/include/xen/mm.h
-@@ -509,8 +509,7 @@ int xenmem_add_to_physmap_one(struct dom
- union xen_add_to_physmap_batch_extra extra,
- unsigned long idx, xen_pfn_t gpfn);
-
--/* Returns 1 on success, 0 on error, negative if the ring
-- * for event propagation is full in the presence of paging */
-+/* Returns 0 on success, or negative on error. */
- int guest_remove_page(struct domain *d, unsigned long gmfn);
-
- #define RAM_TYPE_CONVENTIONAL 0x00000001
Index: head/emulators/xen-kernel/files/xsa222-2-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa222-2-4.7.patch
+++ head/emulators/xen-kernel/files/xsa222-2-4.7.patch
@@ -1,412 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: guest_physmap_remove_page() needs its return value checked
-
-Callers, namely such subsequently freeing the page, must not blindly
-assume success - the function may namely fail when needing to shatter a
-super page, but there not being memory available for the then needed
-intermediate page table.
-
-As it happens, guest_remove_page() callers now also all check the
-return value.
-
-Furthermore a missed put_gfn() on an error path in gnttab_transfer() is
-also being taken care of.
-
-This is part of XSA-222.
-
-Reported-by: Julien Grall <julien.grall@arm.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Julien Grall <julien.grall@arm.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/arm/mm.c
-+++ b/xen/arch/arm/mm.c
-@@ -1299,13 +1299,14 @@ int replace_grant_host_mapping(unsigned
- {
- unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
- struct domain *d = current->domain;
-+ int rc;
-
- if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
- return GNTST_general_error;
-
-- guest_physmap_remove_page(d, gfn, mfn, 0);
-+ rc = guest_physmap_remove_page(d, gfn, mfn, 0);
-
-- return GNTST_okay;
-+ return rc ? GNTST_general_error : GNTST_okay;
- }
-
- int is_iomem_page(unsigned long mfn)
---- a/xen/arch/arm/p2m.c
-+++ b/xen/arch/arm/p2m.c
-@@ -1313,15 +1313,14 @@ int guest_physmap_add_entry(struct domai
- d->arch.p2m.default_access);
- }
-
--void guest_physmap_remove_page(struct domain *d,
-- unsigned long gpfn,
-- unsigned long mfn, unsigned int page_order)
-+int guest_physmap_remove_page(struct domain *d, unsigned long gfn,
-+ unsigned long mfn, unsigned int page_order)
- {
-- apply_p2m_changes(d, REMOVE,
-- pfn_to_paddr(gpfn),
-- pfn_to_paddr(gpfn + (1<<page_order)),
-- pfn_to_paddr(mfn), MATTR_MEM, 0, p2m_invalid,
-- d->arch.p2m.default_access);
-+ return apply_p2m_changes(d, REMOVE,
-+ pfn_to_paddr(gfn),
-+ pfn_to_paddr(gfn + (1 << page_order)),
-+ pfn_to_paddr(mfn), MATTR_MEM, 0, p2m_invalid,
-+ d->arch.p2m.default_access);
- }
-
- int p2m_alloc_table(struct domain *d)
---- a/xen/arch/x86/domain.c
-+++ b/xen/arch/x86/domain.c
-@@ -802,7 +802,15 @@ int arch_domain_soft_reset(struct domain
- ret = -ENOMEM;
- goto exit_put_gfn;
- }
-- guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
-+
-+ ret = guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
-+ if ( ret )
-+ {
-+ printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame %lx\n",
-+ d->domain_id, gfn);
-+ free_domheap_page(new_page);
-+ goto exit_put_gfn;
-+ }
-
- ret = guest_physmap_add_page(d, gfn, page_to_mfn(new_page), PAGE_ORDER_4K);
- if ( ret )
---- a/xen/arch/x86/domain_build.c
-+++ b/xen/arch/x86/domain_build.c
-@@ -427,7 +427,9 @@ static __init void pvh_add_mem_mapping(s
- if ( !iomem_access_permitted(d, mfn + i, mfn + i) )
- {
- omfn = get_gfn_query_unlocked(d, gfn + i, &t);
-- guest_physmap_remove_page(d, gfn + i, mfn_x(omfn), PAGE_ORDER_4K);
-+ if ( guest_physmap_remove_page(d, gfn + i, mfn_x(omfn),
-+ PAGE_ORDER_4K) )
-+ /* nothing, best effort only */;
- continue;
- }
-
---- a/xen/arch/x86/hvm/ioreq.c
-+++ b/xen/arch/x86/hvm/ioreq.c
-@@ -267,8 +267,9 @@ bool_t is_ioreq_server_page(struct domai
- static void hvm_remove_ioreq_gmfn(
- struct domain *d, struct hvm_ioreq_page *iorp)
- {
-- guest_physmap_remove_page(d, iorp->gmfn,
-- page_to_mfn(iorp->page), 0);
-+ if ( guest_physmap_remove_page(d, iorp->gmfn,
-+ page_to_mfn(iorp->page), 0) )
-+ domain_crash(d);
- clear_page(iorp->va);
- }
-
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -4271,7 +4271,11 @@ static int replace_grant_p2m_mapping(
- type, mfn_x(old_mfn), frame);
- return GNTST_general_error;
- }
-- guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K);
-+ if ( guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K) )
-+ {
-+ put_gfn(d, gfn);
-+ return GNTST_general_error;
-+ }
-
- put_gfn(d, gfn);
- return GNTST_okay;
-@@ -4793,7 +4797,7 @@ int xenmem_add_to_physmap_one(
- struct page_info *page = NULL;
- unsigned long gfn = 0; /* gcc ... */
- unsigned long prev_mfn, mfn = 0, old_gpfn;
-- int rc;
-+ int rc = 0;
- p2m_type_t p2mt;
-
- switch ( space )
-@@ -4867,25 +4871,30 @@ int xenmem_add_to_physmap_one(
- {
- if ( is_xen_heap_mfn(prev_mfn) )
- /* Xen heap frames are simply unhooked from this phys slot. */
-- guest_physmap_remove_page(d, gpfn, prev_mfn, PAGE_ORDER_4K);
-+ rc = guest_physmap_remove_page(d, gpfn, prev_mfn, PAGE_ORDER_4K);
- else
- /* Normal domain memory is freed, to avoid leaking memory. */
-- guest_remove_page(d, gpfn);
-+ rc = guest_remove_page(d, gpfn);
- }
- /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page. */
- put_gfn(d, gpfn);
-
-+ if ( rc )
-+ goto put_both;
-+
- /* Unmap from old location, if any. */
- old_gpfn = get_gpfn_from_mfn(mfn);
- ASSERT( old_gpfn != SHARED_M2P_ENTRY );
- if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range )
- ASSERT( old_gpfn == gfn );
- if ( old_gpfn != INVALID_M2P_ENTRY )
-- guest_physmap_remove_page(d, old_gpfn, mfn, PAGE_ORDER_4K);
-+ rc = guest_physmap_remove_page(d, old_gpfn, mfn, PAGE_ORDER_4K);
-
- /* Map at new location. */
-- rc = guest_physmap_add_page(d, gpfn, mfn, PAGE_ORDER_4K);
-+ if ( !rc )
-+ rc = guest_physmap_add_page(d, gpfn, mfn, PAGE_ORDER_4K);
-
-+ put_both:
- /* In the XENMAPSPACE_gmfn, we took a ref of the gfn at the top */
- if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range )
- put_gfn(d, gfn);
---- a/xen/arch/x86/mm/p2m.c
-+++ b/xen/arch/x86/mm/p2m.c
-@@ -2837,10 +2837,12 @@ int p2m_add_foreign(struct domain *tdom,
- {
- if ( is_xen_heap_mfn(prev_mfn) )
- /* Xen heap frames are simply unhooked from this phys slot */
-- guest_physmap_remove_page(tdom, gpfn, prev_mfn, 0);
-+ rc = guest_physmap_remove_page(tdom, gpfn, prev_mfn, 0);
- else
- /* Normal domain memory is freed, to avoid leaking memory. */
-- guest_remove_page(tdom, gpfn);
-+ rc = guest_remove_page(tdom, gpfn);
-+ if ( rc )
-+ goto put_both;
- }
- /*
- * Create the new mapping. Can't use guest_physmap_add_page() because it
-@@ -2853,6 +2855,7 @@ int p2m_add_foreign(struct domain *tdom,
- "gpfn:%lx mfn:%lx fgfn:%lx td:%d fd:%d\n",
- gpfn, mfn, fgfn, tdom->domain_id, fdom->domain_id);
-
-+ put_both:
- put_page(page);
-
- /*
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -1768,6 +1768,7 @@ gnttab_transfer(
- for ( i = 0; i < count; i++ )
- {
- bool_t okay;
-+ int rc;
-
- if (i && hypercall_preempt_check())
- return i;
-@@ -1818,27 +1819,33 @@ gnttab_transfer(
- goto copyback;
- }
-
-- guest_physmap_remove_page(d, gop.mfn, mfn, 0);
-+ rc = guest_physmap_remove_page(d, gop.mfn, mfn, 0);
- gnttab_flush_tlb(d);
-+ if ( rc )
-+ {
-+ gdprintk(XENLOG_INFO,
-+ "gnttab_transfer: can't remove GFN %"PRI_xen_pfn" (MFN %lx)\n",
-+ gop.mfn, mfn);
-+ gop.status = GNTST_general_error;
-+ goto put_gfn_and_copyback;
-+ }
-
- /* Find the target domain. */
- if ( unlikely((e = rcu_lock_domain_by_id(gop.domid)) == NULL) )
- {
-- put_gfn(d, gop.mfn);
- gdprintk(XENLOG_INFO, "gnttab_transfer: can't find domain %d\n",
- gop.domid);
-- page->count_info &= ~(PGC_count_mask|PGC_allocated);
-- free_domheap_page(page);
- gop.status = GNTST_bad_domain;
-- goto copyback;
-+ goto put_gfn_and_copyback;
- }
-
- if ( xsm_grant_transfer(XSM_HOOK, d, e) )
- {
-- put_gfn(d, gop.mfn);
- gop.status = GNTST_permission_denied;
- unlock_and_copyback:
- rcu_unlock_domain(e);
-+ put_gfn_and_copyback:
-+ put_gfn(d, gop.mfn);
- page->count_info &= ~(PGC_count_mask|PGC_allocated);
- free_domheap_page(page);
- goto copyback;
-@@ -1887,12 +1894,8 @@ gnttab_transfer(
- "Transferee (d%d) has no headroom (tot %u, max %u)\n",
- e->domain_id, e->tot_pages, e->max_pages);
-
-- rcu_unlock_domain(e);
-- put_gfn(d, gop.mfn);
-- page->count_info &= ~(PGC_count_mask|PGC_allocated);
-- free_domheap_page(page);
- gop.status = GNTST_general_error;
-- goto copyback;
-+ goto unlock_and_copyback;
- }
-
- /* Okay, add the page to 'e'. */
-@@ -1921,13 +1924,8 @@ gnttab_transfer(
-
- if ( drop_dom_ref )
- put_domain(e);
-- rcu_unlock_domain(e);
--
-- put_gfn(d, gop.mfn);
-- page->count_info &= ~(PGC_count_mask|PGC_allocated);
-- free_domheap_page(page);
- gop.status = GNTST_general_error;
-- goto copyback;
-+ goto unlock_and_copyback;
- }
-
- page_list_add_tail(page, &e->page_list);
---- a/xen/common/memory.c
-+++ b/xen/common/memory.c
-@@ -250,8 +250,12 @@ int guest_remove_page(struct domain *d,
- mfn = mfn_x(get_gfn_query(d, gmfn, &p2mt));
- if ( unlikely(p2m_is_paging(p2mt)) )
- {
-- guest_physmap_remove_page(d, gmfn, mfn, 0);
-+ rc = guest_physmap_remove_page(d, gmfn, mfn, 0);
- put_gfn(d, gmfn);
-+
-+ if ( rc )
-+ return rc;
-+
- /* If the page hasn't yet been paged out, there is an
- * actual page that needs to be released. */
- if ( p2mt == p2m_ram_paging_out )
-@@ -315,7 +319,9 @@ int guest_remove_page(struct domain *d,
- return -ENXIO;
- }
-
-- if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
-+ rc = guest_physmap_remove_page(d, gmfn, mfn, 0);
-+
-+ if ( !rc && test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
- put_page_and_type(page);
-
- /*
-@@ -326,16 +332,14 @@ int guest_remove_page(struct domain *d,
- * For this purpose (and to match populate_physmap() behavior), the page
- * is kept allocated.
- */
-- if ( !is_domain_direct_mapped(d) &&
-+ if ( !rc && !is_domain_direct_mapped(d) &&
- test_and_clear_bit(_PGC_allocated, &page->count_info) )
- put_page(page);
-
-- guest_physmap_remove_page(d, gmfn, mfn, 0);
--
- put_page(page);
- put_gfn(d, gmfn);
-
-- return 0;
-+ return rc;
- }
-
- static void decrease_reservation(struct memop_args *a)
-@@ -570,7 +574,8 @@ static long memory_exchange(XEN_GUEST_HA
- gfn = mfn_to_gmfn(d, mfn);
- /* Pages were unshared above */
- BUG_ON(SHARED_M2P(gfn));
-- guest_physmap_remove_page(d, gfn, mfn, 0);
-+ if ( guest_physmap_remove_page(d, gfn, mfn, 0) )
-+ domain_crash(d);
- put_page(page);
- }
-
-@@ -1120,7 +1125,7 @@ long do_memory_op(unsigned long cmd, XEN
- page = get_page_from_gfn(d, xrfp.gpfn, NULL, P2M_ALLOC);
- if ( page )
- {
-- guest_physmap_remove_page(d, xrfp.gpfn, page_to_mfn(page), 0);
-+ rc = guest_physmap_remove_page(d, xrfp.gpfn, page_to_mfn(page), 0);
- put_page(page);
- }
- else
---- a/xen/drivers/passthrough/arm/smmu.c
-+++ b/xen/drivers/passthrough/arm/smmu.c
-@@ -2783,9 +2783,7 @@ static int arm_smmu_unmap_page(struct do
- if ( !is_domain_direct_mapped(d) )
- return -EINVAL;
-
-- guest_physmap_remove_page(d, gfn, gfn, 0);
--
-- return 0;
-+ return guest_physmap_remove_page(d, gfn, gfn, 0);
- }
-
- static const struct iommu_ops arm_smmu_iommu_ops = {
---- a/xen/include/asm-arm/p2m.h
-+++ b/xen/include/asm-arm/p2m.h
-@@ -177,10 +177,6 @@ static inline int guest_physmap_add_page
- return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
- }
-
--void guest_physmap_remove_page(struct domain *d,
-- unsigned long gpfn,
-- unsigned long mfn, unsigned int page_order);
--
- unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn);
-
- /*
---- a/xen/include/asm-x86/p2m.h
-+++ b/xen/include/asm-x86/p2m.h
-@@ -558,11 +558,6 @@ static inline int guest_physmap_add_page
- return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
- }
-
--/* Remove a page from a domain's p2m table */
--int guest_physmap_remove_page(struct domain *d,
-- unsigned long gfn,
-- unsigned long mfn, unsigned int page_order);
--
- /* Set a p2m range as populate-on-demand */
- int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
- unsigned int order);
---- a/xen/include/xen/p2m-common.h
-+++ b/xen/include/xen/p2m-common.h
-@@ -1,6 +1,7 @@
- #ifndef _XEN_P2M_COMMON_H
- #define _XEN_P2M_COMMON_H
-
-+#include <xen/mm.h>
- #include <public/vm_event.h>
-
- /*
-@@ -33,6 +34,11 @@ typedef enum {
- /* NOTE: Assumed to be only 4 bits right now on x86. */
- } p2m_access_t;
-
-+/* Remove a page from a domain's p2m table */
-+int __must_check
-+guest_physmap_remove_page(struct domain *d, unsigned long gfn,
-+ unsigned long mfn, unsigned int page_order);
-+
- /* Map MMIO regions in the p2m: start_gfn and nr describe the range in
- * * the guest physical address space to map, starting from the machine
- * * frame number mfn. */
---- a/xen/include/xen/mm.h
-+++ b/xen/include/xen/mm.h
-@@ -510,7 +510,7 @@ int xenmem_add_to_physmap_one(struct dom
- unsigned long idx, xen_pfn_t gpfn);
-
- /* Returns 0 on success, or negative on error. */
--int guest_remove_page(struct domain *d, unsigned long gmfn);
-+int __must_check guest_remove_page(struct domain *d, unsigned long gmfn);
-
- #define RAM_TYPE_CONVENTIONAL 0x00000001
- #define RAM_TYPE_RESERVED 0x00000002
Index: head/emulators/xen-kernel/files/xsa226-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa226-4.7.patch
+++ head/emulators/xen-kernel/files/xsa226-4.7.patch
@@ -1,133 +0,0 @@
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Subject: grant_table: Default to v1, and disallow transitive grants
-
-The reference counting and locking discipline for transitive grants is broken.
-Their use is therefore declared out of security support.
-
-This is XSA-226.
-
-Transitive grants are expected to be unconditionally available with grant
-table v2. Hiding transitive grants alone is an ABI breakage for the guest.
-Modern versions of Linux and the Windows PV drivers use grant table v1, but
-older versions did use v2.
-
-In principle, disabling gnttab v2 entirely is the safer way to cause guests to
-avoid using transitive grants. However, some older guests which defaulted to
-using gnttab v2 don't tolerate falling back from v2 to v1 over migrate.
-
-This patch introduces a new command line option to control grant table
-behaviour. One suboption allows a choice of the maximum grant table version
-Xen will allow the guest to use, and defaults to v2. A different suboption
-independently controls whether transitive grants can be used.
-
-The default case is:
-
- gnttab=max_ver:2
-
-To disable gnttab v2 entirely, use:
-
- gnttab=max_ver:1
-
-To allow gnttab v2 and transitive grants, use:
-
- gnttab=max_ver:2,transitive
-
-Reported-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
-index 73f5265..b792abf 100644
---- a/docs/misc/xen-command-line.markdown
-+++ b/docs/misc/xen-command-line.markdown
-@@ -758,6 +758,22 @@ Controls EPT related features.
-
- Specify which console gdbstub should use. See **console**.
-
-+### gnttab
-+> `= List of [ max_ver:<integer>, transitive ]`
-+
-+> Default: `gnttab=max_ver:2,no-transitive`
-+
-+Control various aspects of the grant table behaviour available to guests.
-+
-+* `max_ver` Select the maximum grant table version to offer to guests. Valid
-+version are 1 and 2.
-+* `transitive` Permit or disallow the use of transitive grants. Note that the
-+use of grant table v2 without transitive grants is an ABI breakage from the
-+guests point of view.
-+
-+*Warning:*
-+Due to XSA-226, the use of transitive grants is outside of security support.
-+
- ### gnttab\_max\_frames
- > `= <integer>`
-
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index f06b664..109c552 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -50,6 +50,42 @@ integer_param("gnttab_max_nr_frames", max_nr_grant_frames);
- unsigned int __read_mostly max_grant_frames;
- integer_param("gnttab_max_frames", max_grant_frames);
-
-+static unsigned int __read_mostly opt_gnttab_max_version = 2;
-+static bool_t __read_mostly opt_transitive_grants;
-+
-+static void __init parse_gnttab(char *s)
-+{
-+ char *ss;
-+
-+ do {
-+ ss = strchr(s, ',');
-+ if ( ss )
-+ *ss = '\0';
-+
-+ if ( !strncmp(s, "max_ver:", 8) )
-+ {
-+ long ver = simple_strtol(s + 8, NULL, 10);
-+
-+ if ( ver >= 1 && ver <= 2 )
-+ opt_gnttab_max_version = ver;
-+ }
-+ else
-+ {
-+ bool_t val = !!strncmp(s, "no-", 3);
-+
-+ if ( !val )
-+ s += 3;
-+
-+ if ( !strcmp(s, "transitive") )
-+ opt_transitive_grants = val;
-+ }
-+
-+ s = ss + 1;
-+ } while ( ss );
-+}
-+
-+custom_param("gnttab", parse_gnttab);
-+
- /* The maximum number of grant mappings is defined as a multiplier of the
- * maximum number of grant table entries. This defines the multiplier used.
- * Pretty arbitrary. [POLICY]
-@@ -2188,6 +2224,10 @@ __acquire_grant_for_copy(
- }
- else if ( (shah->flags & GTF_type_mask) == GTF_transitive )
- {
-+ if ( !opt_transitive_grants )
-+ PIN_FAIL(unlock_out_clear, GNTST_general_error,
-+ "transitive grant disallowed by policy\n");
-+
- if ( !allow_transitive )
- PIN_FAIL(unlock_out_clear, GNTST_general_error,
- "transitive grant when transitivity not allowed\n");
-@@ -3156,7 +3196,10 @@ do_grant_table_op(
- }
- case GNTTABOP_set_version:
- {
-- rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t));
-+ if ( opt_gnttab_max_version == 1 )
-+ rc = -ENOSYS; /* Behave as before set_version was introduced. */
-+ else
-+ rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t));
- break;
- }
- case GNTTABOP_get_status_frames:
Index: head/emulators/xen-kernel/files/xsa227.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa227.patch
+++ head/emulators/xen-kernel/files/xsa227.patch
@@ -1,52 +0,0 @@
-From fa7268b94f8a0a7792ee12d5b8e23a60e52a3a84 Mon Sep 17 00:00:00 2001
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Date: Tue, 20 Jun 2017 19:18:54 +0100
-Subject: [PATCH] x86/grant: Disallow misaligned PTEs
-
-Pagetable entries must be aligned to function correctly. Disallow attempts
-from the guest to have a grant PTE created at a misaligned address, which
-would result in corruption of the L1 table with largely-guest-controlled
-values.
-
-This is XSA-227
-
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
----
- xen/arch/x86/mm.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
-index 97b3b4b..00f517a 100644
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -3763,6 +3763,9 @@ static int create_grant_pte_mapping(
- l1_pgentry_t ol1e;
- struct domain *d = v->domain;
-
-+ if ( !IS_ALIGNED(pte_addr, sizeof(nl1e)) )
-+ return GNTST_general_error;
-+
- adjust_guest_l1e(nl1e, d);
-
- gmfn = pte_addr >> PAGE_SHIFT;
-@@ -3819,6 +3822,16 @@ static int destroy_grant_pte_mapping(
- struct page_info *page;
- l1_pgentry_t ol1e;
-
-+ /*
-+ * addr comes from Xen's active_entry tracking so isn't guest controlled,
-+ * but it had still better be PTE-aligned.
-+ */
-+ if ( !IS_ALIGNED(addr, sizeof(ol1e)) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ return GNTST_general_error;
-+ }
-+
- gmfn = addr >> PAGE_SHIFT;
- page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
-
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/xsa228-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa228-4.8.patch
+++ head/emulators/xen-kernel/files/xsa228-4.8.patch
@@ -1,198 +0,0 @@
-From cb91f4c43bd4158daa6561c73921a6455176f278 Mon Sep 17 00:00:00 2001
-From: Jan Beulich <jbeulich@suse.com>
-Date: Mon, 31 Jul 2017 15:17:56 +0100
-Subject: [PATCH] gnttab: split maptrack lock to make it fulfill its purpose
- again
-
-The way the lock is currently being used in get_maptrack_handle(), it
-protects only the maptrack limit: The function acts on current's list
-only, so races on list accesses are impossible even without the lock.
-
-Otoh list access races are possible between __get_maptrack_handle() and
-put_maptrack_handle(), due to the invocation of the former for other
-than current from steal_maptrack_handle(). Introduce a per-vCPU lock
-for list accesses to become race free again. This lock will be
-uncontended except when it becomes necessary to take the steal path,
-i.e. in the common case there should be no meaningful performance
-impact.
-
-When in get_maptrack_handle adds a stolen entry to a fresh, empty,
-freelist, we think that there is probably no concurrency. However,
-this is not a fast path and adding the locking there makes the code
-clearly correct.
-
-Also, while we are here: the stolen maptrack_entry's tail pointer was
-not properly set. Set it.
-
-This is XSA-228.
-
-Reported-by: Ian Jackson <ian.jackson@eu.citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
----
- docs/misc/grant-tables.txt | 7 ++++++-
- xen/common/grant_table.c | 30 ++++++++++++++++++++++++------
- xen/include/xen/grant_table.h | 2 +-
- xen/include/xen/sched.h | 1 +
- 4 files changed, 32 insertions(+), 8 deletions(-)
-
-diff --git a/docs/misc/grant-tables.txt b/docs/misc/grant-tables.txt
-index 417ce2d..64da5cf 100644
---- a/docs/misc/grant-tables.txt
-+++ b/docs/misc/grant-tables.txt
-@@ -87,7 +87,8 @@ is complete.
- inconsistent grant table state such as current
- version, partially initialized active table pages,
- etc.
-- grant_table->maptrack_lock : spinlock used to protect the maptrack free list
-+ grant_table->maptrack_lock : spinlock used to protect the maptrack limit
-+ v->maptrack_freelist_lock : spinlock used to protect the maptrack free list
- active_grant_entry->lock : spinlock used to serialize modifications to
- active entries
-
-@@ -102,6 +103,10 @@ is complete.
- The maptrack free list is protected by its own spinlock. The maptrack
- lock may be locked while holding the grant table lock.
-
-+ The maptrack_freelist_lock is an innermost lock. It may be locked
-+ while holding other locks, but no other locks may be acquired within
-+ it.
-+
- Active entries are obtained by calling active_entry_acquire(gt, ref).
- This function returns a pointer to the active entry after locking its
- spinlock. The caller must hold the grant table read lock before
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index f9654f1..593121c 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -304,11 +304,16 @@ __get_maptrack_handle(
- {
- unsigned int head, next, prev_head;
-
-+ spin_lock(&v->maptrack_freelist_lock);
-+
- do {
- /* No maptrack pages allocated for this VCPU yet? */
- head = read_atomic(&v->maptrack_head);
- if ( unlikely(head == MAPTRACK_TAIL) )
-+ {
-+ spin_unlock(&v->maptrack_freelist_lock);
- return -1;
-+ }
-
- /*
- * Always keep one entry in the free list to make it easier to
-@@ -316,12 +321,17 @@ __get_maptrack_handle(
- */
- next = read_atomic(&maptrack_entry(t, head).ref);
- if ( unlikely(next == MAPTRACK_TAIL) )
-+ {
-+ spin_unlock(&v->maptrack_freelist_lock);
- return -1;
-+ }
-
- prev_head = head;
- head = cmpxchg(&v->maptrack_head, prev_head, next);
- } while ( head != prev_head );
-
-+ spin_unlock(&v->maptrack_freelist_lock);
-+
- return head;
- }
-
-@@ -380,6 +390,8 @@ put_maptrack_handle(
- /* 2. Add entry to the tail of the list on the original VCPU. */
- v = currd->vcpu[maptrack_entry(t, handle).vcpu];
-
-+ spin_lock(&v->maptrack_freelist_lock);
-+
- cur_tail = read_atomic(&v->maptrack_tail);
- do {
- prev_tail = cur_tail;
-@@ -388,6 +400,8 @@ put_maptrack_handle(
-
- /* 3. Update the old tail entry to point to the new entry. */
- write_atomic(&maptrack_entry(t, prev_tail).ref, handle);
-+
-+ spin_unlock(&v->maptrack_freelist_lock);
- }
-
- static inline int
-@@ -411,10 +425,6 @@ get_maptrack_handle(
- */
- if ( nr_maptrack_frames(lgt) >= max_maptrack_frames )
- {
-- /*
-- * Can drop the lock since no other VCPU can be adding a new
-- * frame once they've run out.
-- */
- spin_unlock(&lgt->maptrack_lock);
-
- /*
-@@ -426,8 +436,12 @@ get_maptrack_handle(
- handle = steal_maptrack_handle(lgt, curr);
- if ( handle == -1 )
- return -1;
-+ spin_lock(&curr->maptrack_freelist_lock);
-+ maptrack_entry(lgt, handle).ref = MAPTRACK_TAIL;
- curr->maptrack_tail = handle;
-- write_atomic(&curr->maptrack_head, handle);
-+ if ( curr->maptrack_head == MAPTRACK_TAIL )
-+ write_atomic(&curr->maptrack_head, handle);
-+ spin_unlock(&curr->maptrack_freelist_lock);
- }
- return steal_maptrack_handle(lgt, curr);
- }
-@@ -460,12 +474,15 @@ get_maptrack_handle(
- smp_wmb();
- lgt->maptrack_limit += MAPTRACK_PER_PAGE;
-
-+ spin_unlock(&lgt->maptrack_lock);
-+ spin_lock(&curr->maptrack_freelist_lock);
-+
- do {
- new_mt[i - 1].ref = read_atomic(&curr->maptrack_head);
- head = cmpxchg(&curr->maptrack_head, new_mt[i - 1].ref, handle + 1);
- } while ( head != new_mt[i - 1].ref );
-
-- spin_unlock(&lgt->maptrack_lock);
-+ spin_unlock(&curr->maptrack_freelist_lock);
-
- return handle;
- }
-@@ -3474,6 +3491,7 @@ grant_table_destroy(
-
- void grant_table_init_vcpu(struct vcpu *v)
- {
-+ spin_lock_init(&v->maptrack_freelist_lock);
- v->maptrack_head = MAPTRACK_TAIL;
- v->maptrack_tail = MAPTRACK_TAIL;
- }
-diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
-index 4e77899..100f2b3 100644
---- a/xen/include/xen/grant_table.h
-+++ b/xen/include/xen/grant_table.h
-@@ -78,7 +78,7 @@ struct grant_table {
- /* Mapping tracking table per vcpu. */
- struct grant_mapping **maptrack;
- unsigned int maptrack_limit;
-- /* Lock protecting the maptrack page list, head, and limit */
-+ /* Lock protecting the maptrack limit */
- spinlock_t maptrack_lock;
- /* The defined versions are 1 and 2. Set to 0 if we don't know
- what version to use yet. */
-diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
-index 1fbda87..ff0f38f 100644
---- a/xen/include/xen/sched.h
-+++ b/xen/include/xen/sched.h
-@@ -223,6 +223,7 @@ struct vcpu
- int controller_pause_count;
-
- /* Maptrack */
-+ spinlock_t maptrack_freelist_lock;
- unsigned int maptrack_head;
- unsigned int maptrack_tail;
-
---
-2.1.4
-
Index: head/emulators/xen-kernel/files/xsa230.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa230.patch
+++ head/emulators/xen-kernel/files/xsa230.patch
@@ -1,38 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: gnttab: correct pin status fixup for copy
-
-Regardless of copy operations only setting GNTPIN_hst*, GNTPIN_dev*
-also need to be taken into account when deciding whether to clear
-_GTF_{read,writ}ing. At least for consistency with code elsewhere the
-read part better doesn't use any mask at all.
-
-This is XSA-230.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
-index ae34547..9c9d33c 100644
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -2107,10 +2107,10 @@ __release_grant_for_copy(
- static void __fixup_status_for_copy_pin(const struct active_grant_entry *act,
- uint16_t *status)
- {
-- if ( !(act->pin & GNTPIN_hstw_mask) )
-+ if ( !(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
-
-- if ( !(act->pin & GNTPIN_hstr_mask) )
-+ if ( !act->pin )
- gnttab_clear_flag(_GTF_reading, status);
- }
-
-@@ -2318,7 +2318,7 @@ __acquire_grant_for_copy(
-
- unlock_out_clear:
- if ( !(readonly) &&
-- !(act->pin & GNTPIN_hstw_mask) )
-+ !(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
- gnttab_clear_flag(_GTF_writing, status);
-
- if ( !act->pin )
Index: head/emulators/xen-kernel/files/xsa231-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa231-4.7.patch
+++ head/emulators/xen-kernel/files/xsa231-4.7.patch
@@ -1,108 +0,0 @@
-From: George Dunlap <george.dunlap@citrix.com>
-Subject: xen/mm: make sure node is less than MAX_NUMNODES
-
-The output of MEMF_get_node(memflags) can be as large as nodeid_t can
-hold (currently 255). This is then used as an index to arrays of size
-MAX_NUMNODE, which is 64 on x86 and 1 on ARM, can be passed in by an
-untrusted guest (via memory_exchange and increase_reservation) and is
-not currently bounds-checked.
-
-Check the value in page_alloc.c before using it, and also check the
-value in the hypercall call sites and return -EINVAL if appropriate.
-Don't permit domains other than the hardware or control domain to
-allocate node-constrained memory.
-
-This is XSA-231.
-
-Reported-by: Matthew Daley <mattd@bugfuzz.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/common/memory.c
-+++ b/xen/common/memory.c
-@@ -390,6 +390,31 @@ static void decrease_reservation(struct
- a->nr_done = i;
- }
-
-+static bool_t propagate_node(unsigned int xmf, unsigned int *memflags)
-+{
-+ const struct domain *currd = current->domain;
-+
-+ BUILD_BUG_ON(XENMEMF_get_node(0) != NUMA_NO_NODE);
-+ BUILD_BUG_ON(MEMF_get_node(0) != NUMA_NO_NODE);
-+
-+ if ( XENMEMF_get_node(xmf) == NUMA_NO_NODE )
-+ return 1;
-+
-+ if ( is_hardware_domain(currd) || is_control_domain(currd) )
-+ {
-+ if ( XENMEMF_get_node(xmf) >= MAX_NUMNODES )
-+ return 0;
-+
-+ *memflags |= MEMF_node(XENMEMF_get_node(xmf));
-+ if ( xmf & XENMEMF_exact_node_request )
-+ *memflags |= MEMF_exact_node;
-+ }
-+ else if ( xmf & XENMEMF_exact_node_request )
-+ return 0;
-+
-+ return 1;
-+}
-+
- static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
- {
- struct xen_memory_exchange exch;
-@@ -462,6 +487,12 @@ static long memory_exchange(XEN_GUEST_HA
- }
- }
-
-+ if ( unlikely(!propagate_node(exch.out.mem_flags, &memflags)) )
-+ {
-+ rc = -EINVAL;
-+ goto fail_early;
-+ }
-+
- d = rcu_lock_domain_by_any_id(exch.in.domid);
- if ( d == NULL )
- {
-@@ -480,7 +511,6 @@ static long memory_exchange(XEN_GUEST_HA
- d,
- XENMEMF_get_address_bits(exch.out.mem_flags) ? :
- (BITS_PER_LONG+PAGE_SHIFT)));
-- memflags |= MEMF_node(XENMEMF_get_node(exch.out.mem_flags));
-
- for ( i = (exch.nr_exchanged >> in_chunk_order);
- i < (exch.in.nr_extents >> in_chunk_order);
-@@ -834,12 +864,8 @@ static int construct_memop_from_reservat
- }
- read_unlock(&d->vnuma_rwlock);
- }
-- else
-- {
-- a->memflags |= MEMF_node(XENMEMF_get_node(r->mem_flags));
-- if ( r->mem_flags & XENMEMF_exact_node_request )
-- a->memflags |= MEMF_exact_node;
-- }
-+ else if ( unlikely(!propagate_node(r->mem_flags, &a->memflags)) )
-+ return -EINVAL;
-
- return 0;
- }
---- a/xen/common/page_alloc.c
-+++ b/xen/common/page_alloc.c
-@@ -711,9 +711,13 @@ static struct page_info *alloc_heap_page
- if ( node >= MAX_NUMNODES )
- node = cpu_to_node(smp_processor_id());
- }
-+ else if ( unlikely(node >= MAX_NUMNODES) )
-+ {
-+ ASSERT_UNREACHABLE();
-+ return NULL;
-+ }
- first_node = node;
-
-- ASSERT(node < MAX_NUMNODES);
- ASSERT(zone_lo <= zone_hi);
- ASSERT(zone_hi < NR_ZONES);
-
Index: head/emulators/xen-kernel/files/xsa232.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa232.patch
+++ head/emulators/xen-kernel/files/xsa232.patch
@@ -1,23 +0,0 @@
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Subject: grant_table: fix GNTTABOP_cache_flush handling
-
-Don't fall over a NULL grant_table pointer when the owner of the domain
-is a system domain (DOMID_{XEN,IO} etc).
-
-This is XSA-232.
-
-Reported-by: Matthew Daley <mattd@bugfuzz.com>
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -3053,7 +3053,7 @@ static int cache_flush(gnttab_cache_flus
-
- page = mfn_to_page(mfn);
- owner = page_get_owner_and_reference(page);
-- if ( !owner )
-+ if ( !owner || !owner->grant_table )
- {
- rcu_unlock_domain(d);
- return -EPERM;
Index: head/emulators/xen-kernel/files/xsa233.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa233.patch
+++ head/emulators/xen-kernel/files/xsa233.patch
@@ -1,52 +0,0 @@
-From: Juergen Gross <jgross@suse.com>
-Subject: tools/xenstore: dont unlink connection object twice
-
-A connection object of a domain with associated stubdom has two
-parents: the domain and the stubdom. When cleaning up the list of
-active domains in domain_cleanup() make sure not to unlink the
-connection twice from the same domain. This could happen when the
-domain and its stubdom are being destroyed at the same time leading
-to the domain loop being entered twice.
-
-Additionally don't use talloc_free() in this case as it will remove
-a random parent link, leading eventually to a memory leak. Use
-talloc_unlink() instead specifying the context from which the
-connection object should be removed.
-
-This is XSA-233.
-
-Reported-by: Eric Chanudet <chanudete@ainfosec.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
-Reviewed-by: Ian Jackson <ian.jackson@eu.citrix.com>
-
---- a/tools/xenstore/xenstored_domain.c
-+++ b/tools/xenstore/xenstored_domain.c
-@@ -221,10 +221,11 @@ static int destroy_domain(void *_domain)
- static void domain_cleanup(void)
- {
- xc_dominfo_t dominfo;
-- struct domain *domain, *tmp;
-+ struct domain *domain;
- int notify = 0;
-
-- list_for_each_entry_safe(domain, tmp, &domains, list) {
-+ again:
-+ list_for_each_entry(domain, &domains, list) {
- if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
- &dominfo) == 1 &&
- dominfo.domid == domain->domid) {
-@@ -236,8 +237,12 @@ static void domain_cleanup(void)
- if (!dominfo.dying)
- continue;
- }
-- talloc_free(domain->conn);
-- notify = 0; /* destroy_domain() fires the watch */
-+ if (domain->conn) {
-+ talloc_unlink(talloc_autofree_context(), domain->conn);
-+ domain->conn = NULL;
-+ notify = 0; /* destroy_domain() fires the watch */
-+ goto again;
-+ }
- }
-
- if (notify)
Index: head/emulators/xen-kernel/files/xsa234-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa234-4.8.patch
+++ head/emulators/xen-kernel/files/xsa234-4.8.patch
@@ -1,185 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: gnttab: also validate PTE permissions upon destroy/replace
-
-In order for PTE handling to match up with the reference counting done
-by common code, presence and writability of grant mapping PTEs must
-also be taken into account; validating just the frame number is not
-enough. This is in particular relevant if a guest fiddles with grant
-PTEs via non-grant hypercalls.
-
-Note that the flags being passed to replace_grant_host_mapping()
-already happen to be those of the existing mapping, so no new function
-parameter is needed.
-
-This is XSA-234.
-
-Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -4017,7 +4017,8 @@ static int create_grant_pte_mapping(
- }
-
- static int destroy_grant_pte_mapping(
-- uint64_t addr, unsigned long frame, struct domain *d)
-+ uint64_t addr, unsigned long frame, unsigned int grant_pte_flags,
-+ struct domain *d)
- {
- int rc = GNTST_okay;
- void *va;
-@@ -4063,16 +4064,27 @@ static int destroy_grant_pte_mapping(
-
- ol1e = *(l1_pgentry_t *)va;
-
-- /* Check that the virtual address supplied is actually mapped to frame. */
-- if ( unlikely(l1e_get_pfn(ol1e) != frame) )
-+ /*
-+ * Check that the PTE supplied actually maps frame (with appropriate
-+ * permissions).
-+ */
-+ if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
-+ unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
-+ (_PAGE_PRESENT | _PAGE_RW)) )
- {
- page_unlock(page);
-- MEM_LOG("PTE entry %lx for address %"PRIx64" doesn't match frame %lx",
-- (unsigned long)l1e_get_intpte(ol1e), addr, frame);
-+ MEM_LOG("PTE %"PRIpte" at %"PRIx64" doesn't match grant (%"PRIpte")",
-+ l1e_get_intpte(ol1e), addr,
-+ l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
- rc = GNTST_general_error;
- goto failed;
- }
-
-+ if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
-+ ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
-+ MEM_LOG("PTE flags %x at %"PRIx64" don't match grant (%x)\n",
-+ l1e_get_flags(ol1e), addr, grant_pte_flags);
-+
- /* Delete pagetable entry. */
- if ( unlikely(!UPDATE_ENTRY
- (l1,
-@@ -4081,7 +4093,7 @@ static int destroy_grant_pte_mapping(
- 0)) )
- {
- page_unlock(page);
-- MEM_LOG("Cannot delete PTE entry at %p", va);
-+ MEM_LOG("Cannot delete PTE entry at %"PRIx64, addr);
- rc = GNTST_general_error;
- goto failed;
- }
-@@ -4149,7 +4161,8 @@ static int create_grant_va_mapping(
- }
-
- static int replace_grant_va_mapping(
-- unsigned long addr, unsigned long frame, l1_pgentry_t nl1e, struct vcpu *v)
-+ unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
-+ l1_pgentry_t nl1e, struct vcpu *v)
- {
- l1_pgentry_t *pl1e, ol1e;
- unsigned long gl1mfn;
-@@ -4185,19 +4198,30 @@ static int replace_grant_va_mapping(
-
- ol1e = *pl1e;
-
-- /* Check that the virtual address supplied is actually mapped to frame. */
-- if ( unlikely(l1e_get_pfn(ol1e) != frame) )
-- {
-- MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx",
-- l1e_get_pfn(ol1e), addr, frame);
-+ /*
-+ * Check that the virtual address supplied is actually mapped to frame
-+ * (with appropriate permissions).
-+ */
-+ if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
-+ unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
-+ (_PAGE_PRESENT | _PAGE_RW)) )
-+ {
-+ MEM_LOG("PTE %"PRIpte" for %lx doesn't match grant (%"PRIpte")",
-+ l1e_get_intpte(ol1e), addr,
-+ l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
- rc = GNTST_general_error;
- goto unlock_and_out;
- }
-
-+ if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
-+ ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
-+ MEM_LOG("PTE flags %x for %"PRIx64" don't match grant (%x)",
-+ l1e_get_flags(ol1e), addr, grant_pte_flags);
-+
- /* Delete pagetable entry. */
- if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) )
- {
-- MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e);
-+ MEM_LOG("Cannot delete PTE entry for %"PRIx64, addr);
- rc = GNTST_general_error;
- goto unlock_and_out;
- }
-@@ -4211,9 +4235,11 @@ static int replace_grant_va_mapping(
- }
-
- static int destroy_grant_va_mapping(
-- unsigned long addr, unsigned long frame, struct vcpu *v)
-+ unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
-+ struct vcpu *v)
- {
-- return replace_grant_va_mapping(addr, frame, l1e_empty(), v);
-+ return replace_grant_va_mapping(addr, frame, grant_pte_flags,
-+ l1e_empty(), v);
- }
-
- static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame,
-@@ -4307,21 +4333,40 @@ int replace_grant_host_mapping(
- unsigned long gl1mfn;
- struct page_info *l1pg;
- int rc;
-+ unsigned int grant_pte_flags;
-
- if ( paging_mode_external(current->domain) )
- return replace_grant_p2m_mapping(addr, frame, new_addr, flags);
-
-+ grant_pte_flags =
-+ _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_GNTTAB | _PAGE_NX;
-+
-+ if ( flags & GNTMAP_application_map )
-+ grant_pte_flags |= _PAGE_USER;
-+ if ( !(flags & GNTMAP_readonly) )
-+ grant_pte_flags |= _PAGE_RW;
-+ /*
-+ * On top of the explicit settings done by create_grant_host_mapping()
-+ * also open-code relevant parts of adjust_guest_l1e(). Don't mirror
-+ * available and cachability flags, though.
-+ */
-+ if ( !is_pv_32bit_domain(curr->domain) )
-+ grant_pte_flags |= (grant_pte_flags & _PAGE_USER)
-+ ? _PAGE_GLOBAL
-+ : _PAGE_GUEST_KERNEL | _PAGE_USER;
-+
- if ( flags & GNTMAP_contains_pte )
- {
- if ( !new_addr )
-- return destroy_grant_pte_mapping(addr, frame, curr->domain);
-+ return destroy_grant_pte_mapping(addr, frame, grant_pte_flags,
-+ curr->domain);
-
- MEM_LOG("Unsupported grant table operation");
- return GNTST_general_error;
- }
-
- if ( !new_addr )
-- return destroy_grant_va_mapping(addr, frame, curr);
-+ return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr);
-
- pl1e = guest_map_l1e(new_addr, &gl1mfn);
- if ( !pl1e )
-@@ -4369,7 +4414,7 @@ int replace_grant_host_mapping(
- put_page(l1pg);
- guest_unmap_l1e(pl1e);
-
-- rc = replace_grant_va_mapping(addr, frame, ol1e, curr);
-+ rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr);
- if ( rc && !paging_mode_refcounts(curr->domain) )
- put_page_from_l1e(ol1e, curr->domain);
-
Index: head/emulators/xen-kernel/files/xsa236-4.9.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa236-4.9.patch
+++ head/emulators/xen-kernel/files/xsa236-4.9.patch
@@ -1,66 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: gnttab: fix pin count / page reference race
-
-Dropping page references before decrementing pin counts is a bad idea
-if assumptions are being made that a non-zero pin count implies a valid
-page. Fix the order of operations in gnttab_copy_release_buf(), but at
-the same time also remove the assertion that was found to trigger:
-map_grant_ref() also has the potential of causing a race here, and
-changing the order of operations there would likely be quite a bit more
-involved.
-
-This is XSA-236.
-
-Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/common/grant_table.c
-+++ b/xen/common/grant_table.c
-@@ -2330,9 +2330,20 @@ __acquire_grant_for_copy(
- td = page_get_owner_and_reference(*page);
- /*
- * act->pin being non-zero should guarantee the page to have a
-- * non-zero refcount and hence a valid owner.
-+ * non-zero refcount and hence a valid owner (matching the one on
-+ * record), with one exception: If the owning domain is dying we
-+ * had better not make implications from pin count (map_grant_ref()
-+ * updates pin counts before obtaining page references, for
-+ * example).
- */
-- ASSERT(td);
-+ if ( td != rd || rd->is_dying )
-+ {
-+ if ( td )
-+ put_page(*page);
-+ *page = NULL;
-+ rc = GNTST_bad_domain;
-+ goto unlock_out_clear;
-+ }
- }
-
- act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
-@@ -2451,6 +2462,11 @@ static void gnttab_copy_release_buf(stru
- unmap_domain_page(buf->virt);
- buf->virt = NULL;
- }
-+ if ( buf->have_grant )
-+ {
-+ __release_grant_for_copy(buf->domain, buf->ptr.u.ref, buf->read_only);
-+ buf->have_grant = 0;
-+ }
- if ( buf->have_type )
- {
- put_page_type(buf->page);
-@@ -2461,11 +2477,6 @@ static void gnttab_copy_release_buf(stru
- put_page(buf->page);
- buf->page = NULL;
- }
-- if ( buf->have_grant )
-- {
-- __release_grant_for_copy(buf->domain, buf->ptr.u.ref, buf->read_only);
-- buf->have_grant = 0;
-- }
- }
-
- static int gnttab_copy_claim_buf(const struct gnttab_copy *op,
Index: head/emulators/xen-kernel/files/xsa238.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa238.patch
+++ head/emulators/xen-kernel/files/xsa238.patch
@@ -1,45 +0,0 @@
-From cdc2887076b19b39fab9faec495082586f3113df Mon Sep 17 00:00:00 2001
-From: XenProject Security Team <security@xenproject.org>
-Date: Tue, 5 Sep 2017 13:41:37 +0200
-Subject: x86/ioreq server: correctly handle bogus
- XEN_DMOP_{,un}map_io_range_to_ioreq_server arguments
-
-Misbehaving device model can pass incorrect XEN_DMOP_map/
-unmap_io_range_to_ioreq_server arguments, namely end < start when
-specifying address range. When this happens we hit ASSERT(s <= e) in
-rangeset_contains_range()/rangeset_overlaps_range() with debug builds.
-Production builds will not trap right away but may misbehave later
-while handling such bogus ranges.
-
-This is XSA-238.
-
-Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
----
- xen/arch/x86/hvm/ioreq.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
-index b2a8b0e986..8c8bf1f0ec 100644
---- a/xen/arch/x86/hvm/ioreq.c
-+++ b/xen/arch/x86/hvm/ioreq.c
-@@ -820,6 +820,9 @@ int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
- struct hvm_ioreq_server *s;
- int rc;
-
-+ if ( start > end )
-+ return -EINVAL;
-+
- spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
-
- rc = -ENOENT;
-@@ -872,6 +875,9 @@ int hvm_unmap_io_range_from_ioreq_server(struct domain *d, ioservid_t id,
- struct hvm_ioreq_server *s;
- int rc;
-
-+ if ( start > end )
-+ return -EINVAL;
-+
- spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
-
- rc = -ENOENT;
Index: head/emulators/xen-kernel/files/xsa239.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa239.patch
+++ head/emulators/xen-kernel/files/xsa239.patch
@@ -1,46 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/HVM: prefill partially used variable on emulation paths
-
-Certain handlers ignore the access size (vioapic_write() being the
-example this was found with), perhaps leading to subsequent reads
-seeing data that wasn't actually written by the guest. For
-consistency and extra safety also do this on the read path of
-hvm_process_io_intercept(), even if this doesn't directly affect what
-guests get to see, as we've supposedly already dealt with read handlers
-leaving data completely unitialized.
-
-This is XSA-239.
-
-Reported-by: Roger Pau Monné <roger.pau@citrix.com>
-Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/arch/x86/hvm/emulate.c
-+++ b/xen/arch/x86/hvm/emulate.c
-@@ -129,7 +129,7 @@ static int hvmemul_do_io(
- .count = *reps,
- .dir = dir,
- .df = df,
-- .data = data,
-+ .data = data_is_addr ? data : 0,
- .data_is_ptr = data_is_addr, /* ioreq_t field name is misleading */
- .state = STATE_IOREQ_READY,
- };
---- a/xen/arch/x86/hvm/intercept.c
-+++ b/xen/arch/x86/hvm/intercept.c
-@@ -127,6 +127,7 @@ int hvm_process_io_intercept(const struc
- addr = (p->type == IOREQ_TYPE_COPY) ?
- p->addr + step * i :
- p->addr;
-+ data = 0;
- rc = ops->read(handler, addr, p->size, &data);
- if ( rc != X86EMUL_OKAY )
- break;
-@@ -161,6 +162,7 @@ int hvm_process_io_intercept(const struc
- {
- if ( p->data_is_ptr )
- {
-+ data = 0;
- switch ( hvm_copy_from_guest_phys(&data, p->data + step * i,
- p->size) )
- {
Index: head/emulators/xen-kernel/files/xsa241-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa241-4.8.patch
+++ head/emulators/xen-kernel/files/xsa241-4.8.patch
@@ -1,120 +0,0 @@
-x86: don't store possibly stale TLB flush time stamp
-
-While the timing window is extremely narrow, it is theoretically
-possible for an update to the TLB flush clock and a subsequent flush
-IPI to happen between the read and write parts of the update of the
-per-page stamp. Exclude this possibility by disabling interrupts
-across the update, preventing the IPI to be serviced in the middle.
-
-This is XSA-241.
-
-Reported-by: Jann Horn <jannh@google.com>
-Suggested-by: George Dunlap <george.dunlap@citrix.com>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/arm/smp.c
-+++ b/xen/arch/arm/smp.c
-@@ -1,4 +1,5 @@
- #include <xen/config.h>
-+#include <xen/mm.h>
- #include <asm/system.h>
- #include <asm/smp.h>
- #include <asm/cpregs.h>
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -2524,7 +2524,7 @@ static int _put_final_page_type(struct p
- */
- if ( !(shadow_mode_enabled(page_get_owner(page)) &&
- (page->count_info & PGC_page_table)) )
-- page->tlbflush_timestamp = tlbflush_current_time();
-+ page_set_tlbflush_timestamp(page);
- wmb();
- page->u.inuse.type_info--;
- }
-@@ -2534,7 +2534,7 @@ static int _put_final_page_type(struct p
- (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
- if ( !(shadow_mode_enabled(page_get_owner(page)) &&
- (page->count_info & PGC_page_table)) )
-- page->tlbflush_timestamp = tlbflush_current_time();
-+ page_set_tlbflush_timestamp(page);
- wmb();
- page->u.inuse.type_info |= PGT_validated;
- }
-@@ -2588,7 +2588,7 @@ static int _put_page_type(struct page_in
- if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
- {
- /*
-- * page_set_tlbflush_timestamp() accesses the same union
-+ * set_tlbflush_timestamp() accesses the same union
- * linear_pt_count lives in. Unvalidated page table pages,
- * however, should occur during domain destruction only
- * anyway. Updating of linear_pt_count luckily is not
-@@ -2609,7 +2609,7 @@ static int _put_page_type(struct page_in
- */
- if ( !(shadow_mode_enabled(page_get_owner(page)) &&
- (page->count_info & PGC_page_table)) )
-- page->tlbflush_timestamp = tlbflush_current_time();
-+ page_set_tlbflush_timestamp(page);
- }
-
- if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
---- a/xen/arch/x86/mm/shadow/common.c
-+++ b/xen/arch/x86/mm/shadow/common.c
-@@ -1464,7 +1464,7 @@ void shadow_free(struct domain *d, mfn_t
- * TLBs when we reuse the page. Because the destructors leave the
- * contents of the pages in place, we can delay TLB flushes until
- * just before the allocator hands the page out again. */
-- sp->tlbflush_timestamp = tlbflush_current_time();
-+ page_set_tlbflush_timestamp(sp);
- perfc_decr(shadow_alloc_count);
- page_list_add_tail(sp, &d->arch.paging.shadow.freelist);
- sp = next;
---- a/xen/common/page_alloc.c
-+++ b/xen/common/page_alloc.c
-@@ -960,7 +960,7 @@ static void free_heap_pages(
- /* If a page has no owner it will need no safety TLB flush. */
- pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
- if ( pg[i].u.free.need_tlbflush )
-- pg[i].tlbflush_timestamp = tlbflush_current_time();
-+ page_set_tlbflush_timestamp(&pg[i]);
-
- /* This page is not a guest frame any more. */
- page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
---- a/xen/include/asm-arm/flushtlb.h
-+++ b/xen/include/asm-arm/flushtlb.h
-@@ -12,6 +12,11 @@ static inline void tlbflush_filter(cpuma
-
- #define tlbflush_current_time() (0)
-
-+static inline void page_set_tlbflush_timestamp(struct page_info *page)
-+{
-+ page->tlbflush_timestamp = tlbflush_current_time();
-+}
-+
- #if defined(CONFIG_ARM_32)
- # include <asm/arm32/flushtlb.h>
- #elif defined(CONFIG_ARM_64)
---- a/xen/include/asm-x86/flushtlb.h
-+++ b/xen/include/asm-x86/flushtlb.h
-@@ -23,6 +23,20 @@ DECLARE_PER_CPU(u32, tlbflush_time);
-
- #define tlbflush_current_time() tlbflush_clock
-
-+static inline void page_set_tlbflush_timestamp(struct page_info *page)
-+{
-+ /*
-+ * Prevent storing a stale time stamp, which could happen if an update
-+ * to tlbflush_clock plus a subsequent flush IPI happen between the
-+ * reading of tlbflush_clock and the writing of the struct page_info
-+ * field.
-+ */
-+ ASSERT(local_irq_is_enabled());
-+ local_irq_disable();
-+ page->tlbflush_timestamp = tlbflush_current_time();
-+ local_irq_enable();
-+}
-+
- /*
- * @cpu_stamp is the timestamp at last TLB flush for the CPU we are testing.
- * @lastuse_stamp is a timestamp taken when the PFN we are testing was last
Index: head/emulators/xen-kernel/files/xsa242-4.9.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa242-4.9.patch
+++ head/emulators/xen-kernel/files/xsa242-4.9.patch
@@ -1,43 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86: don't allow page_unlock() to drop the last type reference
-
-Only _put_page_type() does the necessary cleanup, and hence not all
-domain pages can be released during guest cleanup (leaving around
-zombie domains) if we get this wrong.
-
-This is XSA-242.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/arch/x86/mm.c
-+++ b/xen/arch/x86/mm.c
-@@ -1923,7 +1923,11 @@ void page_unlock(struct page_info *page)
-
- do {
- x = y;
-+ ASSERT((x & PGT_count_mask) && (x & PGT_locked));
-+
- nx = x - (1 | PGT_locked);
-+ /* We must not drop the last reference here. */
-+ ASSERT(nx & PGT_count_mask);
- } while ( (y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x );
- }
-
-@@ -2611,6 +2615,17 @@ static int _put_page_type(struct page_in
- (page->count_info & PGC_page_table)) )
- page_set_tlbflush_timestamp(page);
- }
-+ else if ( unlikely((nx & (PGT_locked | PGT_count_mask)) ==
-+ (PGT_locked | 1)) )
-+ {
-+ /*
-+ * We must not drop the second to last reference when the page is
-+ * locked, as page_unlock() doesn't do any cleanup of the type.
-+ */
-+ cpu_relax();
-+ y = page->u.inuse.type_info;
-+ continue;
-+ }
-
- if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
- break;
Index: head/emulators/xen-kernel/files/xsa243-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa243-4.7.patch
+++ head/emulators/xen-kernel/files/xsa243-4.7.patch
@@ -1,93 +0,0 @@
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests
-
-When initially creating a monitor table for 4-level translated guests, don't
-install a shadow-linear mapping. This mapping is actually self-linear, and
-trips up the writeable heuristic logic into following Xen's mappings, not the
-guests' shadows it was expecting to follow.
-
-A consequence of this is that sh_guess_wrmap() needs to cope with there being
-no shadow-linear mapping present, which in practice occurs once each time a
-vcpu switches to 4-level paging from a different paging mode.
-
-An appropriate shadow-linear slot will be inserted into the monitor table
-either while constructing lower level monitor tables, or by sh_update_cr3().
-
-While fixing this, clarify the safety of the other mappings. Despite
-appearing unsafe, it is correct to create a guest-linear mapping for
-translated domains; this is self-linear and doesn't point into the translated
-domain. Drop a dead clause for translate != external guests.
-
-This is XSA-243.
-
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Acked-by: Tim Deegan <tim@xen.org>
-
-diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
-index 428be37..c83932f 100644
---- a/xen/arch/x86/mm/shadow/multi.c
-+++ b/xen/arch/x86/mm/shadow/multi.c
-@@ -1472,26 +1472,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
- sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
- }
-
-- /* Shadow linear mapping for 4-level shadows. N.B. for 3-level
-- * shadows on 64-bit xen, this linear mapping is later replaced by the
-- * monitor pagetable structure, which is built in make_monitor_table
-- * and maintained by sh_update_linear_entries. */
-- sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-- shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
--
-- /* Self linear mapping. */
-- if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
-+ /*
-+ * Linear mapping slots:
-+ *
-+ * Calling this function with gl4mfn == sl4mfn is used to construct a
-+ * monitor table for translated domains. In this case, gl4mfn forms the
-+ * self-linear mapping (i.e. not pointing into the translated domain), and
-+ * the shadow-linear slot is skipped. The shadow-linear slot is either
-+ * filled when constructing lower level monitor tables, or via
-+ * sh_update_cr3() for 4-level guests.
-+ *
-+ * Calling this function with gl4mfn != sl4mfn is used for non-translated
-+ * guests, where the shadow-linear slot is actually self-linear, and the
-+ * guest-linear slot points into the guests view of its pagetables.
-+ */
-+ if ( shadow_mode_translate(d) )
- {
-- // linear tables may not be used with translated PV guests
-- sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-+ ASSERT(mfn_x(gl4mfn) == mfn_x(sl4mfn));
-+
-+ sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
- shadow_l4e_empty();
- }
- else
- {
-- sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-- shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
-+ ASSERT(mfn_x(gl4mfn) != mfn_x(sl4mfn));
-+
-+ sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-+ shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
- }
-
-+ sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-+ shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
-+
- unmap_domain_page(sl4e);
- }
- #endif
-@@ -4293,6 +4305,11 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn)
-
- /* Carefully look in the shadow linear map for the l1e we expect */
- #if SHADOW_PAGING_LEVELS >= 4
-+ /* Is a shadow linear map is installed in the first place? */
-+ sl4p = v->arch.paging.shadow.guest_vtable;
-+ sl4p += shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START);
-+ if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
-+ return 0;
- sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
- if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
- return 0;
Index: head/emulators/xen-kernel/files/xsa244-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa244-4.7.patch
+++ head/emulators/xen-kernel/files/xsa244-4.7.patch
@@ -1,51 +0,0 @@
-From: Andrew Cooper <andrew.cooper3@citrix.com>
-Subject: x86/cpu: fix IST handling during PCPU bringup
-
-Clear IST references in newly allocated IDTs. Nothing good will come of
-having them set before the TSS is suitably constructed (although the chances
-of the CPU surviving such an IST interrupt/exception is extremely slim).
-
-Uniformly set the IST references after the TSS is in place. This fixes an
-issue on AMD hardware, where onlining a PCPU while PCPU0 is in HVM context
-will cause IST_NONE to be copied into the new IDT, making that PCPU vulnerable
-to privilege escalation from PV guests until it subsequently schedules an HVM
-guest.
-
-This is XSA-244.
-
-Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
-Reviewed-by: Jan Beulich <jbeulich@suse.com>
-
---- a/xen/arch/x86/cpu/common.c
-+++ b/xen/arch/x86/cpu/common.c
-@@ -617,6 +617,7 @@ void __init early_cpu_init(void)
- * - Sets up TSS with stack pointers, including ISTs
- * - Inserts TSS selector into regular and compat GDTs
- * - Loads GDT, IDT, TR then null LDT
-+ * - Sets up IST references in the IDT
- */
- void load_system_tables(void)
- {
-@@ -663,6 +664,10 @@ void load_system_tables(void)
- asm volatile ("lidt %0" : : "m" (idtr) );
- asm volatile ("ltr %w0" : : "rm" (TSS_ENTRY << 3) );
- asm volatile ("lldt %w0" : : "rm" (0) );
-+
-+ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_DF);
-+ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NMI);
-+ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_MCE);
- }
-
- /*
---- a/xen/arch/x86/smpboot.c
-+++ b/xen/arch/x86/smpboot.c
-@@ -715,6 +715,9 @@ static int cpu_smpboot_alloc(unsigned in
- if ( idt_tables[cpu] == NULL )
- goto oom;
- memcpy(idt_tables[cpu], idt_table, IDT_ENTRIES * sizeof(idt_entry_t));
-+ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_NONE);
-+ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NONE);
-+ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
-
- for ( stub_page = 0, i = cpu & ~(STUBS_PER_PAGE - 1);
- i < nr_cpu_ids && i <= (cpu | (STUBS_PER_PAGE - 1)); ++i )
Index: head/emulators/xen-kernel/files/xsa246-4.7.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa246-4.7.patch
+++ head/emulators/xen-kernel/files/xsa246-4.7.patch
@@ -1,74 +0,0 @@
-From: Julien Grall <julien.grall@linaro.org>
-Subject: x86/pod: prevent infinite loop when shattering large pages
-
-When populating pages, the PoD may need to split large ones using
-p2m_set_entry and request the caller to retry (see ept_get_entry for
-instance).
-
-p2m_set_entry may fail to shatter if it is not possible to allocate
-memory for the new page table. However, the error is not propagated
-resulting to the callers to retry infinitely the PoD.
-
-Prevent the infinite loop by return false when it is not possible to
-shatter the large mapping.
-
-This is XSA-246.
-
-Signed-off-by: Julien Grall <julien.grall@linaro.org>
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/x86/mm/p2m-pod.c
-+++ b/xen/arch/x86/mm/p2m-pod.c
-@@ -1073,9 +1073,8 @@ p2m_pod_demand_populate(struct p2m_domai
- * NOTE: In a fine-grained p2m locking scenario this operation
- * may need to promote its locking from gfn->1g superpage
- */
-- p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_2M,
-- p2m_populate_on_demand, p2m->default_access);
-- return 0;
-+ return p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_2M,
-+ p2m_populate_on_demand, p2m->default_access);
- }
-
- /* Only reclaim if we're in actual need of more cache. */
-@@ -1106,8 +1105,12 @@ p2m_pod_demand_populate(struct p2m_domai
-
- gfn_aligned = (gfn >> order) << order;
-
-- p2m_set_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw,
-- p2m->default_access);
-+ if ( p2m_set_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw,
-+ p2m->default_access) )
-+ {
-+ p2m_pod_cache_add(p2m, p, order);
-+ goto out_fail;
-+ }
-
- for( i = 0; i < (1UL << order); i++ )
- {
-@@ -1152,13 +1155,18 @@ remap_and_retry:
- BUG_ON(order != PAGE_ORDER_2M);
- pod_unlock(p2m);
-
-- /* Remap this 2-meg region in singleton chunks */
-- /* NOTE: In a p2m fine-grained lock scenario this might
-- * need promoting the gfn lock from gfn->2M superpage */
-+ /*
-+ * Remap this 2-meg region in singleton chunks. See the comment on the
-+ * 1G page splitting path above for why a single call suffices.
-+ *
-+ * NOTE: In a p2m fine-grained lock scenario this might
-+ * need promoting the gfn lock from gfn->2M superpage.
-+ */
- gfn_aligned = (gfn>>order)<<order;
-- for(i=0; i<(1<<order); i++)
-- p2m_set_entry(p2m, gfn_aligned + i, _mfn(INVALID_MFN), PAGE_ORDER_4K,
-- p2m_populate_on_demand, p2m->default_access);
-+ if ( p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_4K,
-+ p2m_populate_on_demand, p2m->default_access) )
-+ return -1;
-+
- if ( tb_init_done )
- {
- struct {
Index: head/emulators/xen-kernel/files/xsa248-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa248-4.8.patch
+++ head/emulators/xen-kernel/files/xsa248-4.8.patch
@@ -1,162 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/mm: don't wrongly set page ownership
-
-PV domains can obtain mappings of any pages owned by the correct domain,
-including ones that aren't actually assigned as "normal" RAM, but used
-by Xen internally. At the moment such "internal" pages marked as owned
-by a guest include pages used to track logdirty bits, as well as p2m
-pages and the "unpaged pagetable" for HVM guests. Since the PV memory
-management and shadow code conflict in their use of struct page_info
-fields, and since shadow code is being used for log-dirty handling for
-PV domains, pages coming from the shadow pool must, for PV domains, not
-have the domain set as their owner.
-
-While the change could be done conditionally for just the PV case in
-shadow code, do it unconditionally (and for consistency also for HAP),
-just to be on the safe side.
-
-There's one special case though for shadow code: The page table used for
-running a HVM guest in unpaged mode is subject to get_page() (in
-set_shadow_status()) and hence must have its owner set.
-
-This is XSA-248.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Tim Deegan <tim@xen.org>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-
---- a/xen/arch/x86/mm/hap/hap.c
-+++ b/xen/arch/x86/mm/hap/hap.c
-@@ -283,8 +283,7 @@ static struct page_info *hap_alloc_p2m_p
- {
- d->arch.paging.hap.total_pages--;
- d->arch.paging.hap.p2m_pages++;
-- page_set_owner(pg, d);
-- pg->count_info |= 1;
-+ ASSERT(!page_get_owner(pg) && !(pg->count_info & PGC_count_mask));
- }
- else if ( !d->arch.paging.p2m_alloc_failed )
- {
-@@ -299,21 +298,23 @@ static struct page_info *hap_alloc_p2m_p
-
- static void hap_free_p2m_page(struct domain *d, struct page_info *pg)
- {
-+ struct domain *owner = page_get_owner(pg);
-+
- /* This is called both from the p2m code (which never holds the
- * paging lock) and the log-dirty code (which always does). */
- paging_lock_recursive(d);
-
-- ASSERT(page_get_owner(pg) == d);
-- /* Should have just the one ref we gave it in alloc_p2m_page() */
-- if ( (pg->count_info & PGC_count_mask) != 1 ) {
-- HAP_ERROR("Odd p2m page %p count c=%#lx t=%"PRtype_info"\n",
-- pg, pg->count_info, pg->u.inuse.type_info);
-+ /* Should still have no owner and count zero. */
-+ if ( owner || (pg->count_info & PGC_count_mask) )
-+ {
-+ HAP_ERROR("d%d: Odd p2m page %"PRI_mfn" d=%d c=%lx t=%"PRtype_info"\n",
-+ d->domain_id, mfn_x(page_to_mfn(pg)),
-+ owner ? owner->domain_id : DOMID_INVALID,
-+ pg->count_info, pg->u.inuse.type_info);
- WARN();
-+ pg->count_info &= ~PGC_count_mask;
-+ page_set_owner(pg, NULL);
- }
-- pg->count_info &= ~PGC_count_mask;
-- /* Free should not decrement domain's total allocation, since
-- * these pages were allocated without an owner. */
-- page_set_owner(pg, NULL);
- d->arch.paging.hap.p2m_pages--;
- d->arch.paging.hap.total_pages++;
- hap_free(d, page_to_mfn(pg));
---- a/xen/arch/x86/mm/shadow/common.c
-+++ b/xen/arch/x86/mm/shadow/common.c
-@@ -1573,32 +1573,29 @@ shadow_alloc_p2m_page(struct domain *d)
- pg = mfn_to_page(shadow_alloc(d, SH_type_p2m_table, 0));
- d->arch.paging.shadow.p2m_pages++;
- d->arch.paging.shadow.total_pages--;
-+ ASSERT(!page_get_owner(pg) && !(pg->count_info & PGC_count_mask));
-
- paging_unlock(d);
-
-- /* Unlike shadow pages, mark p2m pages as owned by the domain.
-- * Marking the domain as the owner would normally allow the guest to
-- * create mappings of these pages, but these p2m pages will never be
-- * in the domain's guest-physical address space, and so that is not
-- * believed to be a concern. */
-- page_set_owner(pg, d);
-- pg->count_info |= 1;
- return pg;
- }
-
- static void
- shadow_free_p2m_page(struct domain *d, struct page_info *pg)
- {
-- ASSERT(page_get_owner(pg) == d);
-- /* Should have just the one ref we gave it in alloc_p2m_page() */
-- if ( (pg->count_info & PGC_count_mask) != 1 )
-+ struct domain *owner = page_get_owner(pg);
-+
-+ /* Should still have no owner and count zero. */
-+ if ( owner || (pg->count_info & PGC_count_mask) )
- {
-- SHADOW_ERROR("Odd p2m page count c=%#lx t=%"PRtype_info"\n",
-+ SHADOW_ERROR("d%d: Odd p2m page %"PRI_mfn" d=%d c=%lx t=%"PRtype_info"\n",
-+ d->domain_id, mfn_x(page_to_mfn(pg)),
-+ owner ? owner->domain_id : DOMID_INVALID,
- pg->count_info, pg->u.inuse.type_info);
-+ pg->count_info &= ~PGC_count_mask;
-+ page_set_owner(pg, NULL);
- }
-- pg->count_info &= ~PGC_count_mask;
- pg->u.sh.type = SH_type_p2m_table; /* p2m code reuses type-info */
-- page_set_owner(pg, NULL);
-
- /* This is called both from the p2m code (which never holds the
- * paging lock) and the log-dirty code (which always does). */
-@@ -3216,7 +3213,9 @@ int shadow_enable(struct domain *d, u32
- | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER
- | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
- unmap_domain_page(e);
-+ pg->count_info = 1;
- pg->u.inuse.type_info = PGT_l2_page_table | 1 | PGT_validated;
-+ page_set_owner(pg, d);
- }
-
- paging_lock(d);
-@@ -3254,7 +3253,11 @@ int shadow_enable(struct domain *d, u32
- if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) )
- p2m_teardown(p2m);
- if ( rv != 0 && pg != NULL )
-+ {
-+ pg->count_info &= ~PGC_count_mask;
-+ page_set_owner(pg, NULL);
- shadow_free_p2m_page(d, pg);
-+ }
- domain_unpause(d);
- return rv;
- }
-@@ -3363,7 +3366,22 @@ out:
-
- /* Must be called outside the lock */
- if ( unpaged_pagetable )
-+ {
-+ if ( page_get_owner(unpaged_pagetable) == d &&
-+ (unpaged_pagetable->count_info & PGC_count_mask) == 1 )
-+ {
-+ unpaged_pagetable->count_info &= ~PGC_count_mask;
-+ page_set_owner(unpaged_pagetable, NULL);
-+ }
-+ /* Complain here in cases where shadow_free_p2m_page() won't. */
-+ else if ( !page_get_owner(unpaged_pagetable) &&
-+ !(unpaged_pagetable->count_info & PGC_count_mask) )
-+ SHADOW_ERROR("d%d: Odd unpaged pt %"PRI_mfn" c=%lx t=%"PRtype_info"\n",
-+ d->domain_id, mfn_x(page_to_mfn(unpaged_pagetable)),
-+ unpaged_pagetable->count_info,
-+ unpaged_pagetable->u.inuse.type_info);
- shadow_free_p2m_page(d, unpaged_pagetable);
-+ }
- }
-
- void shadow_final_teardown(struct domain *d)
Index: head/emulators/xen-kernel/files/xsa249.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa249.patch
+++ head/emulators/xen-kernel/files/xsa249.patch
@@ -1,42 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/shadow: fix refcount overflow check
-
-Commit c385d27079 ("x86 shadow: for multi-page shadows, explicitly track
-the first page") reduced the refcount width to 25, without adjusting the
-overflow check. Eliminate the disconnect by using a manifest constant.
-
-Interestingly, up to commit 047782fa01 ("Out-of-sync L1 shadows: OOS
-snapshot") the refcount was 27 bits wide, yet the check was already
-using 26.
-
-This is XSA-249.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: George Dunlap <george.dunlap@citrix.com>
-Reviewed-by: Tim Deegan <tim@xen.org>
----
-v2: Simplify expression back to the style it was.
-
---- a/xen/arch/x86/mm/shadow/private.h
-+++ b/xen/arch/x86/mm/shadow/private.h
-@@ -529,7 +529,7 @@ static inline int sh_get_ref(struct doma
- x = sp->u.sh.count;
- nx = x + 1;
-
-- if ( unlikely(nx >= 1U<<26) )
-+ if ( unlikely(nx >= (1U << PAGE_SH_REFCOUNT_WIDTH)) )
- {
- SHADOW_PRINTK("shadow ref overflow, gmfn=%lx smfn=%lx\n",
- __backpointer(sp), mfn_x(smfn));
---- a/xen/include/asm-x86/mm.h
-+++ b/xen/include/asm-x86/mm.h
-@@ -82,7 +82,8 @@ struct page_info
- unsigned long type:5; /* What kind of shadow is this? */
- unsigned long pinned:1; /* Is the shadow pinned? */
- unsigned long head:1; /* Is this the first page of the shadow? */
-- unsigned long count:25; /* Reference count */
-+#define PAGE_SH_REFCOUNT_WIDTH 25
-+ unsigned long count:PAGE_SH_REFCOUNT_WIDTH; /* Reference count */
- } sh;
-
- /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
Index: head/emulators/xen-kernel/files/xsa250.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa250.patch
+++ head/emulators/xen-kernel/files/xsa250.patch
@@ -1,67 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/shadow: fix ref-counting error handling
-
-The old-Linux handling in shadow_set_l4e() mistakenly ORed together the
-results of sh_get_ref() and sh_pin(). As the latter failing is not a
-correctness problem, simply ignore its return value.
-
-In sh_set_toplevel_shadow() a failing sh_get_ref() must not be
-accompanied by installing the entry, despite the domain being crashed.
-
-This is XSA-250.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Tim Deegan <tim@xen.org>
-
---- a/xen/arch/x86/mm/shadow/multi.c
-+++ b/xen/arch/x86/mm/shadow/multi.c
-@@ -923,7 +923,7 @@ static int shadow_set_l4e(struct domain
- shadow_l4e_t new_sl4e,
- mfn_t sl4mfn)
- {
-- int flags = 0, ok;
-+ int flags = 0;
- shadow_l4e_t old_sl4e;
- paddr_t paddr;
- ASSERT(sl4e != NULL);
-@@ -938,15 +938,16 @@ static int shadow_set_l4e(struct domain
- {
- /* About to install a new reference */
- mfn_t sl3mfn = shadow_l4e_get_mfn(new_sl4e);
-- ok = sh_get_ref(d, sl3mfn, paddr);
-- /* Are we pinning l3 shadows to handle wierd linux behaviour? */
-- if ( sh_type_is_pinnable(d, SH_type_l3_64_shadow) )
-- ok |= sh_pin(d, sl3mfn);
-- if ( !ok )
-+
-+ if ( !sh_get_ref(d, sl3mfn, paddr) )
- {
- domain_crash(d);
- return SHADOW_SET_ERROR;
- }
-+
-+ /* Are we pinning l3 shadows to handle weird Linux behaviour? */
-+ if ( sh_type_is_pinnable(d, SH_type_l3_64_shadow) )
-+ sh_pin(d, sl3mfn);
- }
-
- /* Write the new entry */
-@@ -3965,14 +3966,15 @@ sh_set_toplevel_shadow(struct vcpu *v,
-
- /* Take a ref to this page: it will be released in sh_detach_old_tables()
- * or the next call to set_toplevel_shadow() */
-- if ( !sh_get_ref(d, smfn, 0) )
-+ if ( sh_get_ref(d, smfn, 0) )
-+ new_entry = pagetable_from_mfn(smfn);
-+ else
- {
- SHADOW_ERROR("can't install %#lx as toplevel shadow\n", mfn_x(smfn));
- domain_crash(d);
-+ new_entry = pagetable_null();
- }
-
-- new_entry = pagetable_from_mfn(smfn);
--
- install_new_entry:
- /* Done. Install it */
- SHADOW_PRINTK("%u/%u [%u] gmfn %#"PRI_mfn" smfn %#"PRI_mfn"\n",
Index: head/emulators/xen-kernel/files/xsa251-4.8.patch
===================================================================
--- head/emulators/xen-kernel/files/xsa251-4.8.patch
+++ head/emulators/xen-kernel/files/xsa251-4.8.patch
@@ -1,21 +0,0 @@
-From: Jan Beulich <jbeulich@suse.com>
-Subject: x86/paging: don't unconditionally BUG() on finding SHARED_M2P_ENTRY
-
-PV guests can fully control the values written into the P2M.
-
-This is XSA-251.
-
-Signed-off-by: Jan Beulich <jbeulich@suse.com>
-Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
-
---- a/xen/arch/x86/mm/paging.c
-+++ b/xen/arch/x86/mm/paging.c
-@@ -276,7 +276,7 @@ void paging_mark_pfn_dirty(struct domain
- return;
-
- /* Shared MFNs should NEVER be marked dirty */
-- BUG_ON(SHARED_M2P(pfn));
-+ BUG_ON(paging_mode_translate(d) && SHARED_M2P(pfn));
-
- /*
- * Values with the MSB set denote MFNs that aren't really part of the
Index: head/emulators/xen-kernel/pkg-descr
===================================================================
--- head/emulators/xen-kernel/pkg-descr
+++ head/emulators/xen-kernel/pkg-descr
@@ -1,10 +0,0 @@
-The Xen Project hypervisor is an open-source type-1 or baremetal hypervisor,
-which makes it possible to run many instances of an operating system or indeed
-different operating systems in parallel on a single machine (or host). The Xen
-Project hypervisor is the only type-1 hypervisor that is available as open
-source. It is used as the basis for a number of different commercial and open
-source applications, such as: server virtualization, Infrastructure as a Service
-(IaaS), desktop virtualization, security applications, embedded and hardware
-appliances
-
-WWW: http://www.xenproject.org/
Index: head/emulators/xen-kernel/pkg-message
===================================================================
--- head/emulators/xen-kernel/pkg-message
+++ head/emulators/xen-kernel/pkg-message
@@ -1,18 +0,0 @@
-Please add the following entries in order to boot the xen kernel
-
-In /etc/sysctl.conf:
- vm.max_wired=-1
-
-In /etc/ttys:
- xc0 "/usr/libexec/getty Pc" xterm on secure
-
-In /boot/loader.conf for a dom0 with 2G memory and 4 vcpus:
- hw.pci.mcfg=0
- xen_kernel="/boot/xen"
- xen_cmdline="dom0_mem=2048M dom0_max_vcpus=4 dom0pvh=1 com1=115200,8n1 guest_loglvl=all loglvl=all"
-
-Add to the above xen_cmdline in order to activate the serial console:
- console=com1
-
-In /boot/menu.rc.local:
- try-include /boot/xen.4th
Index: head/emulators/xen-kernel47/Makefile
===================================================================
--- head/emulators/xen-kernel47/Makefile
+++ head/emulators/xen-kernel47/Makefile
@@ -0,0 +1,124 @@
+# $FreeBSD$
+
+PORTNAME= xen
+PORTVERSION= 4.7.2
+PORTREVISION= 9
+CATEGORIES= emulators
+MASTER_SITES= http://downloads.xenproject.org/release/xen/${PORTVERSION}/
+PKGNAMESUFFIX= -kernel
+
+MAINTAINER= royger@FreeBSD.org
+COMMENT= Hypervisor using a microkernel design
+
+LICENSE= GPLv2
+
+ONLY_FOR_ARCHS= amd64
+
+USES= cpe gmake python:2.7,build
+
+# We need to use ld from ports because the version in base doesn't
+# support the '--build-id' switch that's needed for live hypervisor
+# hot-patching. Once the ld version in base supports this option the
+# dependency can be removed.
+#
+# GNU objcopy is used instead of elftc objcopy because of bug #533:
+# https://sourceforge.net/p/elftoolchain/tickets/533/
+# Once this is solved we should be able to switch to elfcopy.
+#
+# And finally we also need to use nm from binutils because the one
+# from base cannot deal with i386pep binary files which is the format
+# of the Xen EFI image (note that FreeBSD cannot yet boot as Dom0 from EFI,
+# but the image is built anyway). This is reported to elftc as bug #534:
+# https://sourceforge.net/p/elftoolchain/tickets/534/
+MAKE_ARGS= clang=y PYTHON=${PYTHON_CMD} LD="${LD}" OBJCOPY="${OBJCOPY}" \
+ NM="${NM}"
+USE_BINUTILS= yes
+NO_MTREE= yes
+STRIP= #
+PLIST_FILES= /boot/xen \
+ /boot/xen.4th
+EXTRA_PATCHES= ${FILESDIR}/0001-xen-logdirty-prevent-preemption-if-finished.patch:-p1 \
+ ${FILESDIR}/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch:-p1 \
+ ${FILESDIR}/kconf_arch.patch:-p1 \
+ ${FILESDIR}/0001-x86-drop-unneeded-__packed-attributes.patch:-p1 \
+ ${FILESDIR}/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch:-p1 \
+ ${FILESDIR}/xsa212.patch:-p1 \
+ ${FILESDIR}/xsa213-4.7.patch:-p1 \
+ ${FILESDIR}/xsa214.patch:-p1 \
+ ${FILESDIR}/xsa215.patch:-p1 \
+ ${FILESDIR}/xsa217.patch:-p1 \
+ ${FILESDIR}/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch:-p1 \
+ ${FILESDIR}/0002-gnttab-fix-unmap-pin-accounting-race.patch:-p1 \
+ ${FILESDIR}/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch:-p1 \
+ ${FILESDIR}/0004-gnttab-correct-maptrack-table-accesses.patch:-p1 \
+ ${FILESDIR}/xsa219-4.8.patch:-p1 \
+ ${FILESDIR}/xsa220-4.7.patch:-p1 \
+ ${FILESDIR}/xsa221.patch:-p1 \
+ ${FILESDIR}/xsa222-1-4.7.patch:-p1 \
+ ${FILESDIR}/xsa222-2-4.7.patch:-p1 \
+ ${FILESDIR}/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch:-p1 \
+ ${FILESDIR}/0002-gnttab-never-create-host-mapping-unless-asked-to.patch:-p1 \
+ ${FILESDIR}/0003-gnttab-correct-logic-to-get-page-references-during-m.patch:-p1 \
+ ${FILESDIR}/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch:-p1 \
+ ${FILESDIR}/xsa226-4.7.patch:-p1 \
+ ${FILESDIR}/xsa227.patch:-p1 \
+ ${FILESDIR}/xsa228-4.8.patch:-p1 \
+ ${FILESDIR}/xsa230.patch:-p1 \
+ ${FILESDIR}/xsa231-4.7.patch:-p1 \
+ ${FILESDIR}/xsa232.patch:-p1 \
+ ${FILESDIR}/xsa233.patch:-p1 \
+ ${FILESDIR}/xsa234-4.8.patch:-p1 \
+ ${FILESDIR}/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch:-p1 \
+ ${FILESDIR}/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch:-p1 \
+ ${FILESDIR}/0003-x86-MSI-disallow-redundant-enabling.patch:-p1 \
+ ${FILESDIR}/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch:-p1 \
+ ${FILESDIR}/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch:-p1 \
+ ${FILESDIR}/xsa238.patch:-p1 \
+ ${FILESDIR}/xsa239.patch:-p1 \
+ ${FILESDIR}/0001-x86-limit-linear-page-table-use-to-a-single-level.patch:-p1 \
+ ${FILESDIR}/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch:-p1 \
+ ${FILESDIR}/xsa241-4.8.patch:-p1 \
+ ${FILESDIR}/xsa242-4.9.patch:-p1 \
+ ${FILESDIR}/xsa243-4.7.patch:-p1 \
+ ${FILESDIR}/xsa244-4.7.patch:-p1 \
+ ${FILESDIR}/xsa236-4.9.patch:-p1 \
+ ${FILESDIR}/0001-x86-compat-fix-compilation-errors-with-clang-6.patch:-p1 \
+ ${FILESDIR}/xsa246-4.7.patch:-p1 \
+ ${FILESDIR}/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch:-p1 \
+ ${FILESDIR}/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch:-p1 \
+ ${FILESDIR}/xsa248-4.8.patch:-p1 \
+ ${FILESDIR}/xsa249.patch:-p1 \
+ ${FILESDIR}/xsa250.patch:-p1 \
+ ${FILESDIR}/xsa251-4.8.patch:-p1 \
+ ${FILESDIR}/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch:-p1 \
+ ${FILESDIR}/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch:-p1 \
+ ${FILESDIR}/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch:-p1 \
+ ${FILESDIR}/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch:-p1
+
+.include <bsd.port.options.mk>
+
+.if ${OPSYS} != FreeBSD
+IGNORE= only supported on FreeBSD
+.endif
+
+.if ${OSVERSION} < 1100055
+IGNORE= only supported on recent FreeBSD 11
+.endif
+
+pre-build:
+ ${MAKE_CMD} -C ${WRKSRC}/xen defconfig ${MAKE_ARGS}
+ # Enable hypervisor hot-patching.
+ echo 'CONFIG_XSPLICE=y' >> ${WRKSRC}/xen/.config
+ echo 'CONFIG_FAST_SYMBOL_LOOKUP=y' >> ${WRKSRC}/xen/.config
+
+# The ports native 'build' target cannot be used because it sets
+# CFLAGS, and that breaks the Xen build system.
+do-build:
+ ${MAKE_CMD} -j${MAKE_JOBS_NUMBER} -C ${WRKSRC}/xen build ${MAKE_ARGS}
+
+do-install:
+ ${MKDIR} ${STAGEDIR}/boot
+ ${INSTALL_PROGRAM} ${WRKSRC}/xen/xen ${STAGEDIR}/boot
+ ${INSTALL_DATA} ${FILESDIR}/xen.4th ${STAGEDIR}/boot
+
+.include <bsd.port.mk>
Index: head/emulators/xen-kernel47/distinfo
===================================================================
--- head/emulators/xen-kernel47/distinfo
+++ head/emulators/xen-kernel47/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1489059095
+SHA256 (xen-4.7.2.tar.gz) = 61494a56d9251e2108080f95b0dc8e3d175f1ba4da34603fc07b91cfebf358d5
+SIZE (xen-4.7.2.tar.gz) = 20714281
Index: head/emulators/xen-kernel47/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
+++ head/emulators/xen-kernel47/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch
@@ -0,0 +1,78 @@
+From 03f872b98f24e25cafb478b5d7c34e1eb18e1e4c Mon Sep 17 00:00:00 2001
+From: Quan Xu <quan.xu@intel.com>
+Date: Fri, 2 Jun 2017 12:30:34 +0100
+Subject: [PATCH 1/4] IOMMU: handle IOMMU mapping and unmapping failures
+
+Treat IOMMU mapping and unmapping failures as a fatal to the DomU
+If IOMMU mapping and unmapping failed, crash the DomU and propagate
+the error up to the call trees.
+
+No spamming of the log can occur. For DomU, we avoid logging any
+message for already dying domains. For Dom0, that'll still be more
+verbose than we'd really like, but it at least wouldn't outright
+flood the console.
+
+Signed-off-by: Quan Xu <quan.xu@intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/drivers/passthrough/iommu.c | 30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
+index 1a315ee..927966f 100644
+--- a/xen/drivers/passthrough/iommu.c
++++ b/xen/drivers/passthrough/iommu.c
+@@ -239,21 +239,47 @@ int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
+ unsigned int flags)
+ {
+ const struct domain_iommu *hd = dom_iommu(d);
++ int rc;
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return 0;
+
+- return hd->platform_ops->map_page(d, gfn, mfn, flags);
++ rc = hd->platform_ops->map_page(d, gfn, mfn, flags);
++ if ( unlikely(rc) )
++ {
++ if ( !d->is_shutting_down && printk_ratelimit() )
++ printk(XENLOG_ERR
++ "d%d: IOMMU mapping gfn %#lx to mfn %#lx failed: %d\n",
++ d->domain_id, gfn, mfn, rc);
++
++ if ( !is_hardware_domain(d) )
++ domain_crash(d);
++ }
++
++ return rc;
+ }
+
+ int iommu_unmap_page(struct domain *d, unsigned long gfn)
+ {
+ const struct domain_iommu *hd = dom_iommu(d);
++ int rc;
+
+ if ( !iommu_enabled || !hd->platform_ops )
+ return 0;
+
+- return hd->platform_ops->unmap_page(d, gfn);
++ rc = hd->platform_ops->unmap_page(d, gfn);
++ if ( unlikely(rc) )
++ {
++ if ( !d->is_shutting_down && printk_ratelimit() )
++ printk(XENLOG_ERR
++ "d%d: IOMMU unmapping gfn %#lx failed: %d\n",
++ d->domain_id, gfn, rc);
++
++ if ( !is_hardware_domain(d) )
++ domain_crash(d);
++ }
++
++ return rc;
+ }
+
+ static void iommu_free_pagetables(unsigned long unused)
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
+++ head/emulators/xen-kernel47/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch
@@ -0,0 +1,111 @@
+From fd97f5f5ba9375163c8d8771fe551bb4a6423b36 Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Thu, 15 Jun 2017 16:24:02 +0100
+Subject: [PATCH 1/4] gnttab: Fix handling of dev_bus_addr during unmap
+
+If a grant has been mapped with the GNTTAB_device_map flag, calling
+grant_unmap_ref() with dev_bus_addr set to zero should cause the
+GNTTAB_device_map part of the mapping to be left alone.
+
+Unfortunately, at the moment, op->dev_bus_addr is implicitly checked
+before clearing the map and adjusting the pin count, but only the bits
+above 12; and it is not checked at all before dropping page
+references. This means a guest can repeatedly make such a call to
+cause the reference count to drop to zero, causing the page to be
+freed and re-used, even though it's still mapped in its pagetables.
+
+To fix this, always check op->dev_bus_addr explicitly for being
+non-zero, as well as op->flag & GNTMAP_device_map, before doing
+operations on the device_map.
+
+While we're here, make the logic a bit cleaner:
+
+* Always initialize op->frame to zero and set it from act->frame, to reduce the
+chance of untrusted input being used
+
+* Explicitly check the full dev_bus_addr against act->frame <<
+ PAGE_SHIFT, rather than ignoring the lower 12 bits
+
+This is part of XSA-224.
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index c4d73af..69cbdb6 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -1089,8 +1089,6 @@ __gnttab_unmap_common(
+ ld = current->domain;
+ lgt = ld->grant_table;
+
+- op->frame = (unsigned long)(op->dev_bus_addr >> PAGE_SHIFT);
+-
+ if ( unlikely(op->handle >= lgt->maptrack_limit) )
+ {
+ gdprintk(XENLOG_INFO, "Bad handle (%d).\n", op->handle);
+@@ -1174,16 +1172,14 @@ __gnttab_unmap_common(
+ goto act_release_out;
+ }
+
+- if ( op->frame == 0 )
+- {
+- op->frame = act->frame;
+- }
+- else
++ op->frame = act->frame;
++
++ if ( op->dev_bus_addr )
+ {
+- if ( unlikely(op->frame != act->frame) )
++ if ( unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
+ PIN_FAIL(act_release_out, GNTST_general_error,
+- "Bad frame number doesn't match gntref. (%lx != %lx)\n",
+- op->frame, act->frame);
++ "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
++ op->dev_bus_addr, pfn_to_paddr(act->frame));
+
+ map->flags &= ~GNTMAP_device_map;
+ }
+@@ -1276,7 +1272,8 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ else
+ status = &status_entry(rgt, op->ref);
+
+- if ( unlikely(op->frame != act->frame) )
++ if ( op->dev_bus_addr &&
++ unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
+ {
+ /*
+ * Suggests that __gntab_unmap_common failed early and so
+@@ -1287,7 +1284,7 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+
+ pg = mfn_to_page(op->frame);
+
+- if ( op->flags & GNTMAP_device_map )
++ if ( op->dev_bus_addr && (op->flags & GNTMAP_device_map) )
+ {
+ if ( !is_iomem_page(act->frame) )
+ {
+@@ -1358,6 +1355,7 @@ __gnttab_unmap_grant_ref(
+ /* Intialise these in case common contains old state */
+ common->new_addr = 0;
+ common->rd = NULL;
++ common->frame = 0;
+
+ __gnttab_unmap_common(common);
+ op->status = common->status;
+@@ -1422,6 +1420,7 @@ __gnttab_unmap_and_replace(
+ /* Intialise these in case common contains old state */
+ common->dev_bus_addr = 0;
+ common->rd = NULL;
++ common->frame = 0;
+
+ __gnttab_unmap_common(common);
+ op->status = common->status;
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
+++ head/emulators/xen-kernel47/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch
@@ -0,0 +1,176 @@
+From f345ca185e0c042ed12bf929a9e93efaf33397bb Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Fri, 10 Nov 2017 16:53:54 +0000
+Subject: [PATCH 1/2] p2m: Always check to see if removing a p2m entry actually
+ worked
+
+The PoD zero-check functions speculatively remove memory from the p2m,
+then check to see if it's completely zeroed, before putting it in the
+cache.
+
+Unfortunately, the p2m_set_entry() calls may fail if the underlying
+pagetable structure needs to change and the domain has exhausted its
+p2m memory pool: for instance, if we're removing a 2MiB region out of
+a 1GiB entry (in the p2m_pod_zero_check_superpage() case), or a 4k
+region out of a 2MiB or larger entry (in the p2m_pod_zero_check()
+case); and the return value is not checked.
+
+The underlying mfn will then be added into the PoD cache, and at some
+point mapped into another location in the p2m. If the guest
+afterwards ballons out this memory, it will be freed to the hypervisor
+and potentially reused by another domain, in spite of the fact that
+the original domain still has writable mappings to it.
+
+There are several places where p2m_set_entry() shouldn't be able to
+fail, as it is guaranteed to write an entry of the same order that
+succeeded before. Add a backstop of crashing the domain just in case,
+and an ASSERT_UNREACHABLE() to flag up the broken assumption on debug
+builds.
+
+While we're here, use PAGE_ORDER_2M rather than a magic constant.
+
+This is part of XSA-247.
+
+Reported-by: George Dunlap <george.dunlap.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+v4:
+- Removed some training whitespace
+v3:
+- Reformat reset clause to be more compact
+- Make sure to set map[i] = NULL when unmapping in case we need to bail
+v2:
+- Crash a domain if a p2m_set_entry we think cannot fail fails anyway.
+---
+ xen/arch/x86/mm/p2m-pod.c | 77 +++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 61 insertions(+), 16 deletions(-)
+
+diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
+index 87082cf65f..5ec8a37949 100644
+--- a/xen/arch/x86/mm/p2m-pod.c
++++ b/xen/arch/x86/mm/p2m-pod.c
+@@ -754,8 +754,10 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
+ }
+
+ /* Try to remove the page, restoring old mapping if it fails. */
+- p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_2M,
+- p2m_populate_on_demand, p2m->default_access);
++ if ( p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_2M,
++ p2m_populate_on_demand, p2m->default_access) )
++ goto out;
++
+ p2m_tlb_flush_sync(p2m);
+
+ /* Make none of the MFNs are used elsewhere... for example, mapped
+@@ -812,9 +814,18 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
+ ret = SUPERPAGE_PAGES;
+
+ out_reset:
+- if ( reset )
+- p2m_set_entry(p2m, gfn, mfn0, 9, type0, p2m->default_access);
+-
++ /*
++ * This p2m_set_entry() call shouldn't be able to fail, since the same order
++ * on the same gfn succeeded above. If that turns out to be false, crashing
++ * the domain should be the safest way of making sure we don't leak memory.
++ */
++ if ( reset && p2m_set_entry(p2m, gfn, mfn0, PAGE_ORDER_2M,
++ type0, p2m->default_access) )
++ {
++ ASSERT_UNREACHABLE();
++ domain_crash(d);
++ }
++
+ out:
+ gfn_unlock(p2m, gfn, SUPERPAGE_ORDER);
+ return ret;
+@@ -871,19 +882,30 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
+ }
+
+ /* Try to remove the page, restoring old mapping if it fails. */
+- p2m_set_entry(p2m, gfns[i], _mfn(INVALID_MFN), PAGE_ORDER_4K,
+- p2m_populate_on_demand, p2m->default_access);
++ if ( p2m_set_entry(p2m, gfns[i], _mfn(INVALID_MFN), PAGE_ORDER_4K,
++ p2m_populate_on_demand, p2m->default_access) )
++ goto skip;
+
+ /* See if the page was successfully unmapped. (Allow one refcount
+ * for being allocated to a domain.) */
+ if ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) > 1 )
+ {
++ /*
++ * If the previous p2m_set_entry call succeeded, this one shouldn't
++ * be able to fail. If it does, crashing the domain should be safe.
++ */
++ if ( p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
++ types[i], p2m->default_access) )
++ {
++ ASSERT_UNREACHABLE();
++ domain_crash(d);
++ goto out_unmap;
++ }
++
++ skip:
+ unmap_domain_page(map[i]);
+ map[i] = NULL;
+
+- p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
+- types[i], p2m->default_access);
+-
+ continue;
+ }
+ }
+@@ -902,12 +924,25 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
+
+ unmap_domain_page(map[i]);
+
+- /* See comment in p2m_pod_zero_check_superpage() re gnttab
+- * check timing. */
+- if ( j < PAGE_SIZE/sizeof(*map[i]) )
++ map[i] = NULL;
++
++ /*
++ * See comment in p2m_pod_zero_check_superpage() re gnttab
++ * check timing.
++ */
++ if ( j < (PAGE_SIZE / sizeof(*map[i])) )
+ {
+- p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
+- types[i], p2m->default_access);
++ /*
++ * If the previous p2m_set_entry call succeeded, this one shouldn't
++ * be able to fail. If it does, crashing the domain should be safe.
++ */
++ if ( p2m_set_entry(p2m, gfns[i], mfns[i], PAGE_ORDER_4K,
++ types[i], p2m->default_access) )
++ {
++ ASSERT_UNREACHABLE();
++ domain_crash(d);
++ goto out_unmap;
++ }
+ }
+ else
+ {
+@@ -931,7 +966,17 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
+ p2m->pod.entry_count++;
+ }
+ }
+-
++
++ return;
++
++out_unmap:
++ /*
++ * Something went wrong, probably crashing the domain. Unmap
++ * everything and return.
++ */
++ for ( i = 0; i < count; i++ )
++ if ( map[i] )
++ unmap_domain_page(map[i]);
+ }
+
+ #define POD_SWEEP_LIMIT 1024
+--
+2.15.0
+
Index: head/emulators/xen-kernel47/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
+++ head/emulators/xen-kernel47/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch
@@ -0,0 +1,756 @@
+From e19517a3355acaaa2ff83018bc41e7fd044161e5 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Wed, 17 Jan 2018 17:24:12 +0100
+Subject: [PATCH 1/2] x86: Meltdown band-aid against malicious 64-bit PV guests
+
+This is a very simplistic change limiting the amount of memory a running
+64-bit PV guest has mapped (and hence available for attacking): Only the
+mappings of stack, IDT, and TSS are being cloned from the direct map
+into per-CPU page tables. Guest controlled parts of the page tables are
+being copied into those per-CPU page tables upon entry into the guest.
+Cross-vCPU synchronization of top level page table entry changes is
+being effected by forcing other active vCPU-s of the guest into the
+hypervisor.
+
+The change to context_switch() isn't strictly necessary, but there's no
+reason to keep switching page tables once a PV guest is being scheduled
+out.
+
+This isn't providing full isolation yet, but it should be covering all
+pieces of information exposure of which would otherwise require an XSA.
+
+There is certainly much room for improvement, especially of performance,
+here - first and foremost suppressing all the negative effects on AMD
+systems. But in the interest of backportability (including to really old
+hypervisors, which may not even have alternative patching) any such is
+being left out here.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+master commit: 5784de3e2067ed73efc2fe42e62831e8ae7f46c4
+master date: 2018-01-16 17:49:03 +0100
+---
+ xen/arch/x86/domain.c | 5 +
+ xen/arch/x86/mm.c | 17 ++++
+ xen/arch/x86/smpboot.c | 198 +++++++++++++++++++++++++++++++++++++
+ xen/arch/x86/x86_64/asm-offsets.c | 2 +
+ xen/arch/x86/x86_64/compat/entry.S | 11 +++
+ xen/arch/x86/x86_64/entry.S | 149 +++++++++++++++++++++++++++-
+ xen/include/asm-x86/asm_defns.h | 30 ++++++
+ xen/include/asm-x86/current.h | 12 +++
+ xen/include/asm-x86/processor.h | 1 +
+ xen/include/asm-x86/x86_64/page.h | 5 +-
+ 10 files changed, 424 insertions(+), 6 deletions(-)
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index 6539b75fa7..3cf18f95b7 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -1949,6 +1949,9 @@ static void paravirt_ctxt_switch_to(struct vcpu *v)
+
+ switch_kernel_stack(v);
+
++ this_cpu(root_pgt)[root_table_offset(PERDOMAIN_VIRT_START)] =
++ l4e_from_page(v->domain->arch.perdomain_l3_pg, __PAGE_HYPERVISOR_RW);
++
+ cr4 = pv_guest_cr4_to_real_cr4(v);
+ if ( unlikely(cr4 != read_cr4()) )
+ write_cr4(cr4);
+@@ -2096,6 +2099,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
+
+ ASSERT(local_irq_is_enabled());
+
++ get_cpu_info()->xen_cr3 = 0;
++
+ cpumask_copy(&dirty_mask, next->vcpu_dirty_cpumask);
+ /* Allow at most one CPU at a time to be dirty. */
+ ASSERT(cpumask_weight(&dirty_mask) <= 1);
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index 50f500c940..c9e4003989 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -3857,6 +3857,7 @@ long do_mmu_update(
+ struct vcpu *curr = current, *v = curr;
+ struct domain *d = v->domain, *pt_owner = d, *pg_owner;
+ struct domain_mmap_cache mapcache;
++ bool_t sync_guest = 0;
+ uint32_t xsm_needed = 0;
+ uint32_t xsm_checked = 0;
+ int rc = put_old_guest_table(curr);
+@@ -4005,6 +4006,8 @@ long do_mmu_update(
+ case PGT_l4_page_table:
+ rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
+ cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
++ if ( !rc )
++ sync_guest = 1;
+ break;
+ case PGT_writable_page:
+ perfc_incr(writable_mmu_updates);
+@@ -4107,6 +4110,20 @@ long do_mmu_update(
+
+ domain_mmap_cache_destroy(&mapcache);
+
++ if ( sync_guest )
++ {
++ /*
++ * Force other vCPU-s of the affected guest to pick up L4 entry
++ * changes (if any). Issue a flush IPI with empty operation mask to
++ * facilitate this (including ourselves waiting for the IPI to
++ * actually have arrived). Utilize the fact that FLUSH_VA_VALID is
++ * meaningless without FLUSH_CACHE, but will allow to pass the no-op
++ * check in flush_area_mask().
++ */
++ flush_area_mask(pt_owner->domain_dirty_cpumask,
++ ZERO_BLOCK_PTR, FLUSH_VA_VALID);
++ }
++
+ perfc_add(num_page_updates, i);
+
+ out:
+diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
+index f9e4ee85ff..eaeec5acf0 100644
+--- a/xen/arch/x86/smpboot.c
++++ b/xen/arch/x86/smpboot.c
+@@ -319,6 +319,9 @@ void start_secondary(void *unused)
+ */
+ spin_debug_disable();
+
++ get_cpu_info()->xen_cr3 = 0;
++ get_cpu_info()->pv_cr3 = __pa(this_cpu(root_pgt));
++
+ load_system_tables();
+
+ /* Full exception support from here on in. */
+@@ -628,6 +631,187 @@ void cpu_exit_clear(unsigned int cpu)
+ set_cpu_state(CPU_STATE_DEAD);
+ }
+
++static int clone_mapping(const void *ptr, root_pgentry_t *rpt)
++{
++ unsigned long linear = (unsigned long)ptr, pfn;
++ unsigned int flags;
++ l3_pgentry_t *pl3e = l4e_to_l3e(idle_pg_table[root_table_offset(linear)]) +
++ l3_table_offset(linear);
++ l2_pgentry_t *pl2e;
++ l1_pgentry_t *pl1e;
++
++ if ( linear < DIRECTMAP_VIRT_START )
++ return 0;
++
++ flags = l3e_get_flags(*pl3e);
++ ASSERT(flags & _PAGE_PRESENT);
++ if ( flags & _PAGE_PSE )
++ {
++ pfn = (l3e_get_pfn(*pl3e) & ~((1UL << (2 * PAGETABLE_ORDER)) - 1)) |
++ (PFN_DOWN(linear) & ((1UL << (2 * PAGETABLE_ORDER)) - 1));
++ flags &= ~_PAGE_PSE;
++ }
++ else
++ {
++ pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(linear);
++ flags = l2e_get_flags(*pl2e);
++ ASSERT(flags & _PAGE_PRESENT);
++ if ( flags & _PAGE_PSE )
++ {
++ pfn = (l2e_get_pfn(*pl2e) & ~((1UL << PAGETABLE_ORDER) - 1)) |
++ (PFN_DOWN(linear) & ((1UL << PAGETABLE_ORDER) - 1));
++ flags &= ~_PAGE_PSE;
++ }
++ else
++ {
++ pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(linear);
++ flags = l1e_get_flags(*pl1e);
++ if ( !(flags & _PAGE_PRESENT) )
++ return 0;
++ pfn = l1e_get_pfn(*pl1e);
++ }
++ }
++
++ if ( !(root_get_flags(rpt[root_table_offset(linear)]) & _PAGE_PRESENT) )
++ {
++ pl3e = alloc_xen_pagetable();
++ if ( !pl3e )
++ return -ENOMEM;
++ clear_page(pl3e);
++ l4e_write(&rpt[root_table_offset(linear)],
++ l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR));
++ }
++ else
++ pl3e = l4e_to_l3e(rpt[root_table_offset(linear)]);
++
++ pl3e += l3_table_offset(linear);
++
++ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
++ {
++ pl2e = alloc_xen_pagetable();
++ if ( !pl2e )
++ return -ENOMEM;
++ clear_page(pl2e);
++ l3e_write(pl3e, l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR));
++ }
++ else
++ {
++ ASSERT(!(l3e_get_flags(*pl3e) & _PAGE_PSE));
++ pl2e = l3e_to_l2e(*pl3e);
++ }
++
++ pl2e += l2_table_offset(linear);
++
++ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
++ {
++ pl1e = alloc_xen_pagetable();
++ if ( !pl1e )
++ return -ENOMEM;
++ clear_page(pl1e);
++ l2e_write(pl2e, l2e_from_paddr(__pa(pl1e), __PAGE_HYPERVISOR));
++ }
++ else
++ {
++ ASSERT(!(l2e_get_flags(*pl2e) & _PAGE_PSE));
++ pl1e = l2e_to_l1e(*pl2e);
++ }
++
++ pl1e += l1_table_offset(linear);
++
++ if ( l1e_get_flags(*pl1e) & _PAGE_PRESENT )
++ {
++ ASSERT(l1e_get_pfn(*pl1e) == pfn);
++ ASSERT(l1e_get_flags(*pl1e) == flags);
++ }
++ else
++ l1e_write(pl1e, l1e_from_pfn(pfn, flags));
++
++ return 0;
++}
++
++DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
++
++static int setup_cpu_root_pgt(unsigned int cpu)
++{
++ root_pgentry_t *rpt = alloc_xen_pagetable();
++ unsigned int off;
++ int rc;
++
++ if ( !rpt )
++ return -ENOMEM;
++
++ clear_page(rpt);
++ per_cpu(root_pgt, cpu) = rpt;
++
++ rpt[root_table_offset(RO_MPT_VIRT_START)] =
++ idle_pg_table[root_table_offset(RO_MPT_VIRT_START)];
++ /* SH_LINEAR_PT inserted together with guest mappings. */
++ /* PERDOMAIN inserted during context switch. */
++ rpt[root_table_offset(XEN_VIRT_START)] =
++ idle_pg_table[root_table_offset(XEN_VIRT_START)];
++
++ /* Install direct map page table entries for stack, IDT, and TSS. */
++ for ( off = rc = 0; !rc && off < STACK_SIZE; off += PAGE_SIZE )
++ rc = clone_mapping(__va(__pa(stack_base[cpu])) + off, rpt);
++
++ if ( !rc )
++ rc = clone_mapping(idt_tables[cpu], rpt);
++ if ( !rc )
++ rc = clone_mapping(&per_cpu(init_tss, cpu), rpt);
++
++ return rc;
++}
++
++static void cleanup_cpu_root_pgt(unsigned int cpu)
++{
++ root_pgentry_t *rpt = per_cpu(root_pgt, cpu);
++ unsigned int r;
++
++ if ( !rpt )
++ return;
++
++ per_cpu(root_pgt, cpu) = NULL;
++
++ for ( r = root_table_offset(DIRECTMAP_VIRT_START);
++ r < root_table_offset(HYPERVISOR_VIRT_END); ++r )
++ {
++ l3_pgentry_t *l3t;
++ unsigned int i3;
++
++ if ( !(root_get_flags(rpt[r]) & _PAGE_PRESENT) )
++ continue;
++
++ l3t = l4e_to_l3e(rpt[r]);
++
++ for ( i3 = 0; i3 < L3_PAGETABLE_ENTRIES; ++i3 )
++ {
++ l2_pgentry_t *l2t;
++ unsigned int i2;
++
++ if ( !(l3e_get_flags(l3t[i3]) & _PAGE_PRESENT) )
++ continue;
++
++ ASSERT(!(l3e_get_flags(l3t[i3]) & _PAGE_PSE));
++ l2t = l3e_to_l2e(l3t[i3]);
++
++ for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; ++i2 )
++ {
++ if ( !(l2e_get_flags(l2t[i2]) & _PAGE_PRESENT) )
++ continue;
++
++ ASSERT(!(l2e_get_flags(l2t[i2]) & _PAGE_PSE));
++ free_xen_pagetable(l2e_to_l1e(l2t[i2]));
++ }
++
++ free_xen_pagetable(l2t);
++ }
++
++ free_xen_pagetable(l3t);
++ }
++
++ free_xen_pagetable(rpt);
++}
++
+ static void cpu_smpboot_free(unsigned int cpu)
+ {
+ unsigned int order, socket = cpu_to_socket(cpu);
+@@ -664,6 +848,8 @@ static void cpu_smpboot_free(unsigned int cpu)
+ free_domheap_page(mfn_to_page(mfn));
+ }
+
++ cleanup_cpu_root_pgt(cpu);
++
+ order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
+ free_xenheap_pages(per_cpu(gdt_table, cpu), order);
+
+@@ -719,6 +905,9 @@ static int cpu_smpboot_alloc(unsigned int cpu)
+ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NONE);
+ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
+
++ if ( setup_cpu_root_pgt(cpu) )
++ goto oom;
++
+ for ( stub_page = 0, i = cpu & ~(STUBS_PER_PAGE - 1);
+ i < nr_cpu_ids && i <= (cpu | (STUBS_PER_PAGE - 1)); ++i )
+ if ( cpu_online(i) && cpu_to_node(i) == node )
+@@ -773,6 +962,8 @@ static struct notifier_block cpu_smpboot_nfb = {
+
+ void __init smp_prepare_cpus(unsigned int max_cpus)
+ {
++ int rc;
++
+ register_cpu_notifier(&cpu_smpboot_nfb);
+
+ mtrr_aps_sync_begin();
+@@ -786,6 +977,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+
+ stack_base[0] = stack_start;
+
++ rc = setup_cpu_root_pgt(0);
++ if ( rc )
++ panic("Error %d setting up PV root page table\n", rc);
++ get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
++
+ set_nr_sockets();
+
+ socket_cpumask = xzalloc_array(cpumask_t *, nr_sockets);
+@@ -850,6 +1046,8 @@ void __init smp_prepare_boot_cpu(void)
+ {
+ cpumask_set_cpu(smp_processor_id(), &cpu_online_map);
+ cpumask_set_cpu(smp_processor_id(), &cpu_present_map);
++
++ get_cpu_info()->xen_cr3 = 0;
+ }
+
+ static void
+diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
+index a3ae7a475f..4f2ba28520 100644
+--- a/xen/arch/x86/x86_64/asm-offsets.c
++++ b/xen/arch/x86/x86_64/asm-offsets.c
+@@ -137,6 +137,8 @@ void __dummy__(void)
+ OFFSET(CPUINFO_processor_id, struct cpu_info, processor_id);
+ OFFSET(CPUINFO_current_vcpu, struct cpu_info, current_vcpu);
+ OFFSET(CPUINFO_cr4, struct cpu_info, cr4);
++ OFFSET(CPUINFO_xen_cr3, struct cpu_info, xen_cr3);
++ OFFSET(CPUINFO_pv_cr3, struct cpu_info, pv_cr3);
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+ BLANK();
+
+diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
+index 7ee01597a3..f7e53fb3cb 100644
+--- a/xen/arch/x86/x86_64/compat/entry.S
++++ b/xen/arch/x86/x86_64/compat/entry.S
+@@ -270,6 +270,17 @@ ENTRY(cstar_enter)
+ pushq $0
+ movl $TRAP_syscall, 4(%rsp)
+ SAVE_ALL
++
++ GET_STACK_END(bx)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
++ neg %rcx
++ jz .Lcstar_cr3_okay
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++ neg %rcx
++ write_cr3 rcx, rdi, rsi
++ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++.Lcstar_cr3_okay:
++
+ GET_CURRENT(bx)
+ movq VCPU_domain(%rbx),%rcx
+ cmpb $0,DOMAIN_is_32bit_pv(%rcx)
+diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
+index cebb1e4f4f..d63e734bb3 100644
+--- a/xen/arch/x86/x86_64/entry.S
++++ b/xen/arch/x86/x86_64/entry.S
+@@ -36,6 +36,32 @@ ENTRY(switch_to_kernel)
+ /* %rbx: struct vcpu, interrupts disabled */
+ restore_all_guest:
+ ASSERT_INTERRUPTS_DISABLED
++
++ /* Copy guest mappings and switch to per-CPU root page table. */
++ mov %cr3, %r9
++ GET_STACK_END(dx)
++ mov STACK_CPUINFO_FIELD(pv_cr3)(%rdx), %rdi
++ movabs $PADDR_MASK & PAGE_MASK, %rsi
++ movabs $DIRECTMAP_VIRT_START, %rcx
++ mov %rdi, %rax
++ and %rsi, %rdi
++ and %r9, %rsi
++ add %rcx, %rdi
++ add %rcx, %rsi
++ mov $ROOT_PAGETABLE_FIRST_XEN_SLOT, %ecx
++ mov root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rsi), %r8
++ mov %r8, root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rdi)
++ rep movsq
++ mov $ROOT_PAGETABLE_ENTRIES - \
++ ROOT_PAGETABLE_LAST_XEN_SLOT - 1, %ecx
++ sub $(ROOT_PAGETABLE_FIRST_XEN_SLOT - \
++ ROOT_PAGETABLE_LAST_XEN_SLOT - 1) * 8, %rsi
++ sub $(ROOT_PAGETABLE_FIRST_XEN_SLOT - \
++ ROOT_PAGETABLE_LAST_XEN_SLOT - 1) * 8, %rdi
++ rep movsq
++ mov %r9, STACK_CPUINFO_FIELD(xen_cr3)(%rdx)
++ write_cr3 rax, rdi, rsi
++
+ RESTORE_ALL
+ testw $TRAP_syscall,4(%rsp)
+ jz iret_exit_to_guest
+@@ -70,6 +96,22 @@ iret_exit_to_guest:
+ ALIGN
+ /* No special register assumptions. */
+ restore_all_xen:
++ /*
++ * Check whether we need to switch to the per-CPU page tables, in
++ * case we return to late PV exit code (from an NMI or #MC).
++ */
++ GET_STACK_END(ax)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rax), %rdx
++ mov STACK_CPUINFO_FIELD(pv_cr3)(%rax), %rax
++ test %rdx, %rdx
++ /*
++ * Ideally the condition would be "nsz", but such doesn't exist,
++ * so "g" will have to do.
++ */
++UNLIKELY_START(g, exit_cr3)
++ write_cr3 rax, rdi, rsi
++UNLIKELY_END(exit_cr3)
++
+ RESTORE_ALL adj=8
+ iretq
+
+@@ -99,7 +141,18 @@ ENTRY(lstar_enter)
+ pushq $0
+ movl $TRAP_syscall, 4(%rsp)
+ SAVE_ALL
+- GET_CURRENT(bx)
++
++ GET_STACK_END(bx)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
++ neg %rcx
++ jz .Llstar_cr3_okay
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++ neg %rcx
++ write_cr3 rcx, r11, r12
++ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++.Llstar_cr3_okay:
++
++ __GET_CURRENT(bx)
+ testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
+ jz switch_to_kernel
+
+@@ -248,7 +301,18 @@ GLOBAL(sysenter_eflags_saved)
+ pushq $0
+ movl $TRAP_syscall, 4(%rsp)
+ SAVE_ALL
+- GET_CURRENT(bx)
++
++ GET_STACK_END(bx)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
++ neg %rcx
++ jz .Lsyse_cr3_okay
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++ neg %rcx
++ write_cr3 rcx, rdi, rsi
++ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++.Lsyse_cr3_okay:
++
++ __GET_CURRENT(bx)
+ cmpb $0,VCPU_sysenter_disables_events(%rbx)
+ movq VCPU_sysenter_addr(%rbx),%rax
+ setne %cl
+@@ -284,13 +348,23 @@ ENTRY(int80_direct_trap)
+ movl $0x80, 4(%rsp)
+ SAVE_ALL
+
++ GET_STACK_END(bx)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rcx
++ neg %rcx
++ jz .Lint80_cr3_okay
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++ neg %rcx
++ write_cr3 rcx, rdi, rsi
++ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%rbx)
++.Lint80_cr3_okay:
++
+ cmpb $0,untrusted_msi(%rip)
+ UNLIKELY_START(ne, msi_check)
+ movl $0x80,%edi
+ call check_for_unexpected_msi
+ UNLIKELY_END(msi_check)
+
+- GET_CURRENT(bx)
++ __GET_CURRENT(bx)
+
+ /* Check that the callback is non-null. */
+ leaq VCPU_int80_bounce(%rbx),%rdx
+@@ -441,9 +515,27 @@ ENTRY(dom_crash_sync_extable)
+
+ ENTRY(common_interrupt)
+ SAVE_ALL CLAC
++
++ GET_STACK_END(14)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
++ mov %rcx, %r15
++ neg %rcx
++ jz .Lintr_cr3_okay
++ jns .Lintr_cr3_load
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++ neg %rcx
++.Lintr_cr3_load:
++ write_cr3 rcx, rdi, rsi
++ xor %ecx, %ecx
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++ testb $3, UREGS_cs(%rsp)
++ cmovnz %rcx, %r15
++.Lintr_cr3_okay:
++
+ CR4_PV32_RESTORE
+ movq %rsp,%rdi
+ callq do_IRQ
++ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
+ jmp ret_from_intr
+
+ /* No special register assumptions. */
+@@ -461,6 +553,23 @@ ENTRY(page_fault)
+ /* No special register assumptions. */
+ GLOBAL(handle_exception)
+ SAVE_ALL CLAC
++
++ GET_STACK_END(14)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
++ mov %rcx, %r15
++ neg %rcx
++ jz .Lxcpt_cr3_okay
++ jns .Lxcpt_cr3_load
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++ neg %rcx
++.Lxcpt_cr3_load:
++ write_cr3 rcx, rdi, rsi
++ xor %ecx, %ecx
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++ testb $3, UREGS_cs(%rsp)
++ cmovnz %rcx, %r15
++.Lxcpt_cr3_okay:
++
+ handle_exception_saved:
+ GET_CURRENT(bx)
+ testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
+@@ -525,6 +634,7 @@ handle_exception_saved:
+ leaq exception_table(%rip),%rdx
+ PERFC_INCR(exceptions, %rax, %rbx)
+ callq *(%rdx,%rax,8)
++ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
+ testb $3,UREGS_cs(%rsp)
+ jz restore_all_xen
+ leaq VCPU_trap_bounce(%rbx),%rdx
+@@ -557,6 +667,7 @@ exception_with_ints_disabled:
+ rep; movsq # make room for ec/ev
+ 1: movq UREGS_error_code(%rsp),%rax # ec/ev
+ movq %rax,UREGS_kernel_sizeof(%rsp)
++ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
+ jmp restore_all_xen # return to fixup code
+
+ /* No special register assumptions. */
+@@ -634,6 +745,17 @@ ENTRY(double_fault)
+ movl $TRAP_double_fault,4(%rsp)
+ /* Set AC to reduce chance of further SMAP faults */
+ SAVE_ALL STAC
++
++ GET_STACK_END(bx)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%rbx), %rbx
++ test %rbx, %rbx
++ jz .Ldblf_cr3_okay
++ jns .Ldblf_cr3_load
++ neg %rbx
++.Ldblf_cr3_load:
++ write_cr3 rbx, rdi, rsi
++.Ldblf_cr3_okay:
++
+ movq %rsp,%rdi
+ call do_double_fault
+ BUG /* do_double_fault() shouldn't return. */
+@@ -652,10 +774,28 @@ ENTRY(nmi)
+ movl $TRAP_nmi,4(%rsp)
+ handle_ist_exception:
+ SAVE_ALL CLAC
++
++ GET_STACK_END(14)
++ mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx
++ mov %rcx, %r15
++ neg %rcx
++ jz .List_cr3_okay
++ jns .List_cr3_load
++ mov %rcx, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++ neg %rcx
++.List_cr3_load:
++ write_cr3 rcx, rdi, rsi
++ movq $0, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
++.List_cr3_okay:
++
+ CR4_PV32_RESTORE
+ testb $3,UREGS_cs(%rsp)
+ jz 1f
+- /* Interrupted guest context. Copy the context to stack bottom. */
++ /*
++ * Interrupted guest context. Clear the restore value for xen_cr3
++ * and copy the context to stack bottom.
++ */
++ xor %r15, %r15
+ GET_CPUINFO_FIELD(guest_cpu_user_regs,di)
+ movq %rsp,%rsi
+ movl $UREGS_kernel_sizeof/8,%ecx
+@@ -665,6 +805,7 @@ handle_ist_exception:
+ movzbl UREGS_entry_vector(%rsp),%eax
+ leaq exception_table(%rip),%rdx
+ callq *(%rdx,%rax,8)
++ mov %r15, STACK_CPUINFO_FIELD(xen_cr3)(%r14)
+ cmpb $TRAP_nmi,UREGS_entry_vector(%rsp)
+ jne ret_from_intr
+
+diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
+index 6e5c079ad8..6cfdaa1aa0 100644
+--- a/xen/include/asm-x86/asm_defns.h
++++ b/xen/include/asm-x86/asm_defns.h
+@@ -93,9 +93,30 @@ void ret_from_intr(void);
+ UNLIKELY_DONE(mp, tag); \
+ __UNLIKELY_END(tag)
+
++ .equ .Lrax, 0
++ .equ .Lrcx, 1
++ .equ .Lrdx, 2
++ .equ .Lrbx, 3
++ .equ .Lrsp, 4
++ .equ .Lrbp, 5
++ .equ .Lrsi, 6
++ .equ .Lrdi, 7
++ .equ .Lr8, 8
++ .equ .Lr9, 9
++ .equ .Lr10, 10
++ .equ .Lr11, 11
++ .equ .Lr12, 12
++ .equ .Lr13, 13
++ .equ .Lr14, 14
++ .equ .Lr15, 15
++
+ #define STACK_CPUINFO_FIELD(field) (1 - CPUINFO_sizeof + CPUINFO_##field)
+ #define GET_STACK_END(reg) \
++ .if .Lr##reg > 8; \
++ movq $STACK_SIZE-1, %r##reg; \
++ .else; \
+ movl $STACK_SIZE-1, %e##reg; \
++ .endif; \
+ orq %rsp, %r##reg
+
+ #define GET_CPUINFO_FIELD(field, reg) \
+@@ -177,6 +198,15 @@ void ret_from_intr(void);
+ #define ASM_STAC ASM_AC(STAC)
+ #define ASM_CLAC ASM_AC(CLAC)
+
++.macro write_cr3 val:req, tmp1:req, tmp2:req
++ mov %cr4, %\tmp1
++ mov %\tmp1, %\tmp2
++ and $~X86_CR4_PGE, %\tmp1
++ mov %\tmp1, %cr4
++ mov %\val, %cr3
++ mov %\tmp2, %cr4
++.endm
++
+ #define CR4_PV32_RESTORE \
+ 667: ASM_NOP5; \
+ .pushsection .altinstr_replacement, "ax"; \
+diff --git a/xen/include/asm-x86/current.h b/xen/include/asm-x86/current.h
+index e6587e684c..397fa4c38f 100644
+--- a/xen/include/asm-x86/current.h
++++ b/xen/include/asm-x86/current.h
+@@ -42,6 +42,18 @@ struct cpu_info {
+ struct vcpu *current_vcpu;
+ unsigned long per_cpu_offset;
+ unsigned long cr4;
++ /*
++ * Of the two following fields the latter is being set to the CR3 value
++ * to be used on the given pCPU for loading whenever 64-bit PV guest
++ * context is being entered. The value never changes once set.
++ * The former is the value to restore when re-entering Xen, if any. IOW
++ * its value being zero means there's nothing to restore. However, its
++ * value can also be negative, indicating to the exit-to-Xen code that
++ * restoring is not necessary, but allowing any nested entry code paths
++ * to still know the value to put back into CR3.
++ */
++ unsigned long xen_cr3;
++ unsigned long pv_cr3;
+ /* get_stack_bottom() must be 16-byte aligned */
+ };
+
+diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
+index ccd406a3fe..9906f38f2d 100644
+--- a/xen/include/asm-x86/processor.h
++++ b/xen/include/asm-x86/processor.h
+@@ -517,6 +517,7 @@ extern idt_entry_t idt_table[];
+ extern idt_entry_t *idt_tables[];
+
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
++DECLARE_PER_CPU(root_pgentry_t *, root_pgt);
+
+ extern void init_int80_direct_trap(struct vcpu *v);
+
+diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
+index 589f22552e..afc77c3237 100644
+--- a/xen/include/asm-x86/x86_64/page.h
++++ b/xen/include/asm-x86/x86_64/page.h
+@@ -25,8 +25,8 @@
+ /* These are architectural limits. Current CPUs support only 40-bit phys. */
+ #define PADDR_BITS 52
+ #define VADDR_BITS 48
+-#define PADDR_MASK ((1UL << PADDR_BITS)-1)
+-#define VADDR_MASK ((1UL << VADDR_BITS)-1)
++#define PADDR_MASK ((_AC(1,UL) << PADDR_BITS) - 1)
++#define VADDR_MASK ((_AC(1,UL) << VADDR_BITS) - 1)
+
+ #define is_canonical_address(x) (((long)(x) >> 47) == ((long)(x) >> 63))
+
+@@ -117,6 +117,7 @@ typedef l4_pgentry_t root_pgentry_t;
+ : (((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT) || \
+ ((_s) > ROOT_PAGETABLE_LAST_XEN_SLOT)))
+
++#define root_table_offset l4_table_offset
+ #define root_get_pfn l4e_get_pfn
+ #define root_get_flags l4e_get_flags
+ #define root_get_intpte l4e_get_intpte
+--
+2.15.1
+
Index: head/emulators/xen-kernel47/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
+++ head/emulators/xen-kernel47/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch
@@ -0,0 +1,76 @@
+From 58e028648e3bc831b1b60a39b7f1661538fa6a34 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 23 Jan 2018 16:05:17 +0000
+Subject: [PATCH] x86/compat: fix compilation errors with clang 6
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The following errors are generated when compiling Xen with clang 6:
+
+In file included from x86_64/asm-offsets.c:9:
+In file included from /root/src/xen/xen/include/xen/sched.h:8:
+In file included from /root/src/xen/xen/include/xen/shared.h:6:
+In file included from /root/src/xen/xen/include/compat/arch-x86/../xen.h:9:
+/root/src/xen/xen/include/compat/arch-x86/xen.h:10:10: error: the current #pragma pack aligment
+ value is modified in the included file [-Werror,-Wpragma-pack]
+#include "xen-x86_32.h"
+ ^
+/root/src/xen/xen/include/compat/arch-x86/xen-x86_32.h:40:9: note: previous '#pragma pack'
+ directive that modifies alignment is here
+#pragma pack()
+ ^
+In file included from x86_64/asm-offsets.c:9:
+In file included from /root/src/xen/xen/include/xen/sched.h:8:
+In file included from /root/src/xen/xen/include/xen/shared.h:6:
+/root/src/xen/xen/include/compat/arch-x86/../xen.h:9:10: error: the current #pragma pack aligment
+ value is modified in the included file [-Werror,-Wpragma-pack]
+#include "arch-x86/xen.h"
+ ^
+/root/src/xen/xen/include/compat/arch-x86/xen.h:71:9: note: previous '#pragma pack' directive that
+ modifies alignment is here
+#pragma pack()
+ ^
+2 errors generated.
+
+Fix this by using pragma push/pop in order to store the current pragma
+value in the compiler stack and later restoring it when using clang.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+---
+Cc: Andrew Cooper <andrew.cooper3@citrix.com>
+Cc: George Dunlap <George.Dunlap@eu.citrix.com>
+Cc: Ian Jackson <ian.jackson@eu.citrix.com>
+Cc: Jan Beulich <jbeulich@suse.com>
+Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Cc: Stefano Stabellini <sstabellini@kernel.org>
+Cc: Tim Deegan <tim@xen.org>
+Cc: Wei Liu <wei.liu2@citrix.com>
+---
+Changes since v1:
+ - Only use push/pop with clang.
+---
+ xen/include/Makefile | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/xen/include/Makefile b/xen/include/Makefile
+index 268bc9d6ba..eeae942903 100644
+--- a/xen/include/Makefile
++++ b/xen/include/Makefile
+@@ -34,8 +34,13 @@ cppflags-y := -include public/xen-compat.h
+ cppflags-$(CONFIG_X86) += -m32
+
+ # 8-byte types are 4-byte aligned on x86_32 ...
++ifeq ($(clang),y)
++prefix-$(CONFIG_X86) := \#pragma pack(push, 4)
++suffix-$(CONFIG_X86) := \#pragma pack(pop)
++else
+ prefix-$(CONFIG_X86) := \#pragma pack(4)
+ suffix-$(CONFIG_X86) := \#pragma pack()
++endif
+
+ endif
+
+--
+2.15.1
+
Index: head/emulators/xen-kernel47/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
+++ head/emulators/xen-kernel47/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
@@ -0,0 +1,27 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: don't allow MSI pIRQ mapping on unowned device
+
+MSI setup should be permitted only for existing devices owned by the
+respective guest (the operation may still be carried out by the domain
+controlling that guest).
+
+This is part of XSA-237.
+
+Reported-by: HW42 <hw42@ipsumj.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/irq.c
++++ b/xen/arch/x86/irq.c
+@@ -1964,7 +1964,10 @@ int map_domain_pirq(
+ if ( !cpu_has_apic )
+ goto done;
+
+- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
++ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
++ if ( !pdev )
++ goto done;
++
+ ret = pci_enable_msi(msi, &msi_desc);
+ if ( ret )
+ {
Index: head/emulators/xen-kernel47/files/0001-x86-drop-unneeded-__packed-attributes.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-drop-unneeded-__packed-attributes.patch
+++ head/emulators/xen-kernel47/files/0001-x86-drop-unneeded-__packed-attributes.patch
@@ -0,0 +1,122 @@
+From 7de7d07d47cc389bc341f5524ea8415c3c78e378 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
+Date: Fri, 10 Mar 2017 01:05:51 +0900
+Subject: [PATCH 1/2] x86: drop unneeded __packed attributes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There where a couple of unneeded packed attributes in several x86-specific
+structures, that are obviously aligned. The only non-trivial one is
+vmcb_struct, which has been checked to have the same layout with and without
+the packed attribute using pahole. In that case add a build-time size check to
+be on the safe side.
+
+No functional change is expected as a result of this commit.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+---
+ xen/arch/x86/hvm/svm/vmcb.c | 3 +++
+ xen/arch/x86/x86_emulate/x86_emulate.h | 4 ++--
+ xen/include/asm-x86/hvm/svm/vmcb.h | 12 ++++++------
+ 3 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
+index 9ea014f..f982fc9 100644
+--- a/xen/arch/x86/hvm/svm/vmcb.c
++++ b/xen/arch/x86/hvm/svm/vmcb.c
+@@ -72,6 +72,9 @@ static int construct_vmcb(struct vcpu *v)
+ struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
+ struct vmcb_struct *vmcb = arch_svm->vmcb;
+
++ /* Build-time check of the size of VMCB AMD structure. */
++ BUILD_BUG_ON(sizeof(*vmcb) != PAGE_SIZE);
++
+ vmcb->_general1_intercepts =
+ GENERAL1_INTERCEPT_INTR | GENERAL1_INTERCEPT_NMI |
+ GENERAL1_INTERCEPT_SMI | GENERAL1_INTERCEPT_INIT |
+diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
+index 17c86f3..bbdf16a 100644
+--- a/xen/arch/x86/x86_emulate/x86_emulate.h
++++ b/xen/arch/x86/x86_emulate/x86_emulate.h
+@@ -71,7 +71,7 @@ enum x86_swint_emulation {
+ * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
+ * segment descriptor. It happens to match the format of an AMD SVM VMCB.
+ */
+-typedef union __packed segment_attributes {
++typedef union segment_attributes {
+ uint16_t bytes;
+ struct
+ {
+@@ -91,7 +91,7 @@ typedef union __packed segment_attributes {
+ * Full state of a segment register (visible and hidden portions).
+ * Again, this happens to match the format of an AMD SVM VMCB.
+ */
+-struct __packed segment_register {
++struct segment_register {
+ uint16_t sel;
+ segment_attributes_t attr;
+ uint32_t limit;
+diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
+index bad2382..a3cd1b1 100644
+--- a/xen/include/asm-x86/hvm/svm/vmcb.h
++++ b/xen/include/asm-x86/hvm/svm/vmcb.h
+@@ -308,7 +308,7 @@ enum VMEXIT_EXITCODE
+ /* Definition of segment state is borrowed by the generic HVM code. */
+ typedef struct segment_register svm_segment_register_t;
+
+-typedef union __packed
++typedef union
+ {
+ u64 bytes;
+ struct
+@@ -322,7 +322,7 @@ typedef union __packed
+ } fields;
+ } eventinj_t;
+
+-typedef union __packed
++typedef union
+ {
+ u64 bytes;
+ struct
+@@ -340,7 +340,7 @@ typedef union __packed
+ } fields;
+ } vintr_t;
+
+-typedef union __packed
++typedef union
+ {
+ u64 bytes;
+ struct
+@@ -357,7 +357,7 @@ typedef union __packed
+ } fields;
+ } ioio_info_t;
+
+-typedef union __packed
++typedef union
+ {
+ u64 bytes;
+ struct
+@@ -366,7 +366,7 @@ typedef union __packed
+ } fields;
+ } lbrctrl_t;
+
+-typedef union __packed
++typedef union
+ {
+ uint32_t bytes;
+ struct
+@@ -401,7 +401,7 @@ typedef union __packed
+ #define IOPM_SIZE (12 * 1024)
+ #define MSRPM_SIZE (8 * 1024)
+
+-struct __packed vmcb_struct {
++struct vmcb_struct {
+ u32 _cr_intercepts; /* offset 0x00 - cleanbit 0 */
+ u32 _dr_intercepts; /* offset 0x04 - cleanbit 0 */
+ u32 _exception_intercepts; /* offset 0x08 - cleanbit 0 */
+--
+2.10.1 (Apple Git-78)
+
Index: head/emulators/xen-kernel47/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
+++ head/emulators/xen-kernel47/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
@@ -0,0 +1,399 @@
+From 0e6c6fc449000d97f9fa87ed1fbe23f0cf21406b Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Wed, 17 Jan 2018 17:22:34 +0100
+Subject: [PATCH] x86/entry: Remove support for partial cpu_user_regs frames
+
+Save all GPRs on entry to Xen.
+
+The entry_int82() path is via a DPL1 gate, only usable by 32bit PV guests, so
+can get away with only saving the 32bit registers. All other entrypoints can
+be reached from 32 or 64bit contexts.
+
+This is part of XSA-254.
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Wei Liu <wei.liu2@citrix.com>
+Acked-by: Jan Beulich <jbeulich@suse.com>
+master commit: f9eb74789af77e985ae653193f3622263499f674
+master date: 2018-01-05 19:57:07 +0000
+---
+ tools/tests/x86_emulator/x86_emulate.c | 1 -
+ xen/arch/x86/domain.c | 1 -
+ xen/arch/x86/traps.c | 2 -
+ xen/arch/x86/x86_64/compat/entry.S | 7 ++-
+ xen/arch/x86/x86_64/entry.S | 12 ++--
+ xen/arch/x86/x86_64/traps.c | 13 ++--
+ xen/arch/x86/x86_emulate.c | 1 -
+ xen/arch/x86/x86_emulate/x86_emulate.c | 8 +--
+ xen/common/wait.c | 1 -
+ xen/include/asm-x86/asm_defns.h | 107 +++------------------------------
+ 10 files changed, 26 insertions(+), 127 deletions(-)
+
+diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
+index 10e3f61baa..c12527a50b 100644
+--- a/tools/tests/x86_emulator/x86_emulate.c
++++ b/tools/tests/x86_emulator/x86_emulate.c
+@@ -24,7 +24,6 @@ typedef bool bool_t;
+ #endif
+
+ #define cpu_has_amd_erratum(nr) 0
+-#define mark_regs_dirty(r) ((void)(r))
+
+ #define __packed __attribute__((packed))
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index ceeadabbfd..6539b75fa7 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -148,7 +148,6 @@ static void noreturn continue_idle_domain(struct vcpu *v)
+ static void noreturn continue_nonidle_domain(struct vcpu *v)
+ {
+ check_wakeup_from_wait();
+- mark_regs_dirty(guest_cpu_user_regs());
+ reset_stack_and_jump(ret_from_intr);
+ }
+
+diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
+index 05b4b0811d..0928c9b235 100644
+--- a/xen/arch/x86/traps.c
++++ b/xen/arch/x86/traps.c
+@@ -2456,7 +2456,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
+ goto fail;
+ if ( admin_io_okay(port, op_bytes, currd) )
+ {
+- mark_regs_dirty(regs);
+ io_emul(regs);
+ }
+ else
+@@ -2486,7 +2485,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
+ goto fail;
+ if ( admin_io_okay(port, op_bytes, currd) )
+ {
+- mark_regs_dirty(regs);
+ io_emul(regs);
+ if ( (op_bytes == 1) && pv_post_outb_hook )
+ pv_post_outb_hook(port, regs->eax);
+diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
+index 794bb44266..7ee01597a3 100644
+--- a/xen/arch/x86/x86_64/compat/entry.S
++++ b/xen/arch/x86/x86_64/compat/entry.S
+@@ -15,7 +15,8 @@
+ ENTRY(compat_hypercall)
+ ASM_CLAC
+ pushq $0
+- SAVE_VOLATILE type=TRAP_syscall compat=1
++ movl $TRAP_syscall, 4(%rsp)
++ SAVE_ALL compat=1 /* DPL1 gate, restricted to 32bit PV guests only. */
+ CR4_PV32_RESTORE
+
+ cmpb $0,untrusted_msi(%rip)
+@@ -127,7 +128,6 @@ compat_test_guest_events:
+ /* %rbx: struct vcpu */
+ compat_process_softirqs:
+ sti
+- andl $~TRAP_regs_partial,UREGS_entry_vector(%rsp)
+ call do_softirq
+ jmp compat_test_all_events
+
+@@ -268,7 +268,8 @@ ENTRY(cstar_enter)
+ pushq $FLAT_USER_CS32
+ pushq %rcx
+ pushq $0
+- SAVE_VOLATILE TRAP_syscall
++ movl $TRAP_syscall, 4(%rsp)
++ SAVE_ALL
+ GET_CURRENT(bx)
+ movq VCPU_domain(%rbx),%rcx
+ cmpb $0,DOMAIN_is_32bit_pv(%rcx)
+diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
+index 708d9b9402..cebb1e4f4f 100644
+--- a/xen/arch/x86/x86_64/entry.S
++++ b/xen/arch/x86/x86_64/entry.S
+@@ -97,7 +97,8 @@ ENTRY(lstar_enter)
+ pushq $FLAT_KERNEL_CS64
+ pushq %rcx
+ pushq $0
+- SAVE_VOLATILE TRAP_syscall
++ movl $TRAP_syscall, 4(%rsp)
++ SAVE_ALL
+ GET_CURRENT(bx)
+ testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
+ jz switch_to_kernel
+@@ -192,7 +193,6 @@ test_guest_events:
+ /* %rbx: struct vcpu */
+ process_softirqs:
+ sti
+- SAVE_PRESERVED
+ call do_softirq
+ jmp test_all_events
+
+@@ -246,7 +246,8 @@ GLOBAL(sysenter_eflags_saved)
+ pushq $3 /* ring 3 null cs */
+ pushq $0 /* null rip */
+ pushq $0
+- SAVE_VOLATILE TRAP_syscall
++ movl $TRAP_syscall, 4(%rsp)
++ SAVE_ALL
+ GET_CURRENT(bx)
+ cmpb $0,VCPU_sysenter_disables_events(%rbx)
+ movq VCPU_sysenter_addr(%rbx),%rax
+@@ -263,7 +264,6 @@ UNLIKELY_END(sysenter_nt_set)
+ leal (,%rcx,TBF_INTERRUPT),%ecx
+ UNLIKELY_START(z, sysenter_gpf)
+ movq VCPU_trap_ctxt(%rbx),%rsi
+- SAVE_PRESERVED
+ movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+ movl %eax,TRAPBOUNCE_error_code(%rdx)
+ movq TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%rax
+@@ -281,7 +281,8 @@ UNLIKELY_END(sysenter_gpf)
+ ENTRY(int80_direct_trap)
+ ASM_CLAC
+ pushq $0
+- SAVE_VOLATILE 0x80
++ movl $0x80, 4(%rsp)
++ SAVE_ALL
+
+ cmpb $0,untrusted_msi(%rip)
+ UNLIKELY_START(ne, msi_check)
+@@ -309,7 +310,6 @@ int80_slow_path:
+ * IDT entry with DPL==0.
+ */
+ movl $((0x80 << 3) | X86_XEC_IDT),UREGS_error_code(%rsp)
+- SAVE_PRESERVED
+ movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+ /* A GPF wouldn't have incremented the instruction pointer. */
+ subq $2,UREGS_rip(%rsp)
+diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
+index 22816100fd..bf8dfcbdee 100644
+--- a/xen/arch/x86/x86_64/traps.c
++++ b/xen/arch/x86/x86_64/traps.c
+@@ -81,15 +81,10 @@ static void _show_registers(
+ regs->rbp, regs->rsp, regs->r8);
+ printk("r9: %016lx r10: %016lx r11: %016lx\n",
+ regs->r9, regs->r10, regs->r11);
+- if ( !(regs->entry_vector & TRAP_regs_partial) )
+- {
+- printk("r12: %016lx r13: %016lx r14: %016lx\n",
+- regs->r12, regs->r13, regs->r14);
+- printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
+- regs->r15, crs[0], crs[4]);
+- }
+- else
+- printk("cr0: %016lx cr4: %016lx\n", crs[0], crs[4]);
++ printk("r12: %016lx r13: %016lx r14: %016lx\n",
++ regs->r12, regs->r13, regs->r14);
++ printk("r15: %016lx cr0: %016lx cr4: %016lx\n",
++ regs->r15, crs[0], crs[4]);
+ printk("cr3: %016lx cr2: %016lx\n", crs[3], crs[2]);
+ printk("fsb: %016lx gsb: %016lx gss: %016lx\n",
+ crs[5], crs[6], crs[7]);
+diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
+index 28132b5dbc..43730026c2 100644
+--- a/xen/arch/x86/x86_emulate.c
++++ b/xen/arch/x86/x86_emulate.c
+@@ -11,7 +11,6 @@
+
+ #include <xen/domain_page.h>
+ #include <asm/x86_emulate.h>
+-#include <asm/asm_defns.h> /* mark_regs_dirty() */
+ #include <asm/processor.h> /* current_cpu_info */
+ #include <asm/amd.h> /* cpu_has_amd_erratum() */
+
+diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
+index 4ee3df9247..fcfe9f7de7 100644
+--- a/xen/arch/x86/x86_emulate/x86_emulate.c
++++ b/xen/arch/x86/x86_emulate/x86_emulate.c
+@@ -1424,10 +1424,10 @@ decode_register(
+ case 9: p = &regs->r9; break;
+ case 10: p = &regs->r10; break;
+ case 11: p = &regs->r11; break;
+- case 12: mark_regs_dirty(regs); p = &regs->r12; break;
+- case 13: mark_regs_dirty(regs); p = &regs->r13; break;
+- case 14: mark_regs_dirty(regs); p = &regs->r14; break;
+- case 15: mark_regs_dirty(regs); p = &regs->r15; break;
++ case 12: p = &regs->r12; break;
++ case 13: p = &regs->r13; break;
++ case 14: p = &regs->r14; break;
++ case 15: p = &regs->r15; break;
+ #endif
+ default: BUG(); p = NULL; break;
+ }
+diff --git a/xen/common/wait.c b/xen/common/wait.c
+index 4ac98c07fe..398f653174 100644
+--- a/xen/common/wait.c
++++ b/xen/common/wait.c
+@@ -128,7 +128,6 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
+ unsigned long dummy;
+ u32 entry_vector = cpu_info->guest_cpu_user_regs.entry_vector;
+
+- cpu_info->guest_cpu_user_regs.entry_vector &= ~TRAP_regs_partial;
+ ASSERT(wqv->esp == 0);
+
+ /* Save current VCPU affinity; force wakeup on *this* CPU only. */
+diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
+index 279d70298f..6e5c079ad8 100644
+--- a/xen/include/asm-x86/asm_defns.h
++++ b/xen/include/asm-x86/asm_defns.h
+@@ -17,15 +17,6 @@
+ void ret_from_intr(void);
+ #endif
+
+-#ifdef CONFIG_FRAME_POINTER
+-/* Indicate special exception stack frame by inverting the frame pointer. */
+-#define SETUP_EXCEPTION_FRAME_POINTER(offs) \
+- leaq offs(%rsp),%rbp; \
+- notq %rbp
+-#else
+-#define SETUP_EXCEPTION_FRAME_POINTER(offs)
+-#endif
+-
+ #ifndef NDEBUG
+ #define ASSERT_INTERRUPT_STATUS(x, msg) \
+ pushf; \
+@@ -42,31 +33,6 @@ void ret_from_intr(void);
+ #define ASSERT_INTERRUPTS_DISABLED \
+ ASSERT_INTERRUPT_STATUS(z, "INTERRUPTS DISABLED")
+
+-/*
+- * This flag is set in an exception frame when registers R12-R15 did not get
+- * saved.
+- */
+-#define _TRAP_regs_partial 16
+-#define TRAP_regs_partial (1 << _TRAP_regs_partial)
+-/*
+- * This flag gets set in an exception frame when registers R12-R15 possibly
+- * get modified from their originally saved values and hence need to be
+- * restored even if the normal call flow would restore register values.
+- *
+- * The flag being set implies _TRAP_regs_partial to be unset. Restoring
+- * R12-R15 thus is
+- * - required when this flag is set,
+- * - safe when _TRAP_regs_partial is unset.
+- */
+-#define _TRAP_regs_dirty 17
+-#define TRAP_regs_dirty (1 << _TRAP_regs_dirty)
+-
+-#define mark_regs_dirty(r) ({ \
+- struct cpu_user_regs *r__ = (r); \
+- ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
+- r__->entry_vector |= TRAP_regs_dirty; \
+-})
+-
+ #ifdef __ASSEMBLY__
+ # define _ASM_EX(p) p-.
+ #else
+@@ -236,7 +202,7 @@ static always_inline void stac(void)
+ #endif
+
+ #ifdef __ASSEMBLY__
+-.macro SAVE_ALL op
++.macro SAVE_ALL op, compat=0
+ .ifeqs "\op", "CLAC"
+ ASM_CLAC
+ .else
+@@ -255,40 +221,6 @@ static always_inline void stac(void)
+ movq %rdx,UREGS_rdx(%rsp)
+ movq %rcx,UREGS_rcx(%rsp)
+ movq %rax,UREGS_rax(%rsp)
+- movq %r8,UREGS_r8(%rsp)
+- movq %r9,UREGS_r9(%rsp)
+- movq %r10,UREGS_r10(%rsp)
+- movq %r11,UREGS_r11(%rsp)
+- movq %rbx,UREGS_rbx(%rsp)
+- movq %rbp,UREGS_rbp(%rsp)
+- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+- movq %r12,UREGS_r12(%rsp)
+- movq %r13,UREGS_r13(%rsp)
+- movq %r14,UREGS_r14(%rsp)
+- movq %r15,UREGS_r15(%rsp)
+-.endm
+-
+-/*
+- * Save all registers not preserved by C code or used in entry/exit code. Mark
+- * the frame as partial.
+- *
+- * @type: exception type
+- * @compat: R8-R15 don't need saving, and the frame nevertheless is complete
+- */
+-.macro SAVE_VOLATILE type compat=0
+-.if \compat
+- movl $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
+-.else
+- movl $\type|TRAP_regs_partial,\
+- UREGS_entry_vector-UREGS_error_code(%rsp)
+-.endif
+- addq $-(UREGS_error_code-UREGS_r15),%rsp
+- cld
+- movq %rdi,UREGS_rdi(%rsp)
+- movq %rsi,UREGS_rsi(%rsp)
+- movq %rdx,UREGS_rdx(%rsp)
+- movq %rcx,UREGS_rcx(%rsp)
+- movq %rax,UREGS_rax(%rsp)
+ .if !\compat
+ movq %r8,UREGS_r8(%rsp)
+ movq %r9,UREGS_r9(%rsp)
+@@ -297,20 +229,17 @@ static always_inline void stac(void)
+ .endif
+ movq %rbx,UREGS_rbx(%rsp)
+ movq %rbp,UREGS_rbp(%rsp)
+- SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+-.endm
+-
+-/*
+- * Complete a frame potentially only partially saved.
+- */
+-.macro SAVE_PRESERVED
+- btrl $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
+- jnc 987f
++#ifdef CONFIG_FRAME_POINTER
++/* Indicate special exception stack frame by inverting the frame pointer. */
++ leaq UREGS_rbp(%rsp), %rbp
++ notq %rbp
++#endif
++.if !\compat
+ movq %r12,UREGS_r12(%rsp)
+ movq %r13,UREGS_r13(%rsp)
+ movq %r14,UREGS_r14(%rsp)
+ movq %r15,UREGS_r15(%rsp)
+-987:
++.endif
+ .endm
+
+ #define LOAD_ONE_REG(reg, compat) \
+@@ -351,33 +280,13 @@ static always_inline void stac(void)
+ * @compat: R8-R15 don't need reloading
+ */
+ .macro RESTORE_ALL adj=0 compat=0
+-.if !\compat
+- testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
+-.endif
+ LOAD_C_CLOBBERED \compat
+ .if !\compat
+- jz 987f
+ movq UREGS_r15(%rsp),%r15
+ movq UREGS_r14(%rsp),%r14
+ movq UREGS_r13(%rsp),%r13
+ movq UREGS_r12(%rsp),%r12
+-#ifndef NDEBUG
+- .subsection 1
+-987: testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
+- jnz 987f
+- cmpq UREGS_r15(%rsp),%r15
+- jne 789f
+- cmpq UREGS_r14(%rsp),%r14
+- jne 789f
+- cmpq UREGS_r13(%rsp),%r13
+- jne 789f
+- cmpq UREGS_r12(%rsp),%r12
+- je 987f
+-789: BUG /* Corruption of partial register state. */
+- .subsection 0
+-#endif
+ .endif
+-987:
+ LOAD_ONE_REG(bp, \compat)
+ LOAD_ONE_REG(bx, \compat)
+ subq $-(UREGS_error_code-UREGS_r15+\adj), %rsp
+--
+2.15.1
+
Index: head/emulators/xen-kernel47/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
+++ head/emulators/xen-kernel47/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch
@@ -0,0 +1,494 @@
+From ea7513a3e3f28cfec59dda6e128b6b4968685762 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Thu, 28 Sep 2017 15:17:27 +0100
+Subject: [PATCH 1/2] x86: limit linear page table use to a single level
+
+That's the only way that they're meant to be used. Without such a
+restriction arbitrarily long chains of same-level page tables can be
+built, tearing down of which may then cause arbitrarily deep recursion,
+causing a stack overflow. To facilitate this restriction, a counter is
+being introduced to track both the number of same-level entries in a
+page table as well as the number of uses of a page table in another
+same-level one (counting into positive and negative direction
+respectively, utilizing the fact that both counts can't be non-zero at
+the same time).
+
+Note that the added accounting introduces a restriction on the number
+of times a page can be used in other same-level page tables - more than
+32k of such uses are no longer possible.
+
+Note also that some put_page_and_type[_preemptible]() calls are
+replaced with open-coded equivalents. This seemed preferrable to
+adding "parent_table" to the matrix of functions.
+
+Note further that cross-domain same-level page table references are no
+longer permitted (they probably never should have been).
+
+This is XSA-240.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+---
+ xen/arch/x86/domain.c | 1 +
+ xen/arch/x86/mm.c | 171 ++++++++++++++++++++++++++++++++++++++-----
+ xen/include/asm-x86/domain.h | 2 +
+ xen/include/asm-x86/mm.h | 25 +++++--
+ 4 files changed, 175 insertions(+), 24 deletions(-)
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index 452748dd5b..44ed2ccd0a 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -1237,6 +1237,7 @@ int arch_set_info_guest(
+ case -EINTR:
+ rc = -ERESTART;
+ case -ERESTART:
++ v->arch.old_guest_ptpg = NULL;
+ v->arch.old_guest_table =
+ pagetable_get_page(v->arch.guest_table);
+ v->arch.guest_table = pagetable_null();
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index e97ecccd93..e81a461b91 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -732,6 +732,61 @@ static void put_data_page(
+ put_page(page);
+ }
+
++static bool_t inc_linear_entries(struct page_info *pg)
++{
++ typeof(pg->linear_pt_count) nc = read_atomic(&pg->linear_pt_count), oc;
++
++ do {
++ /*
++ * The check below checks for the "linear use" count being non-zero
++ * as well as overflow. Signed integer overflow is undefined behavior
++ * according to the C spec. However, as long as linear_pt_count is
++ * smaller in size than 'int', the arithmetic operation of the
++ * increment below won't overflow; rather the result will be truncated
++ * when stored. Ensure that this is always true.
++ */
++ BUILD_BUG_ON(sizeof(nc) >= sizeof(int));
++ oc = nc++;
++ if ( nc <= 0 )
++ return 0;
++ nc = cmpxchg(&pg->linear_pt_count, oc, nc);
++ } while ( oc != nc );
++
++ return 1;
++}
++
++static void dec_linear_entries(struct page_info *pg)
++{
++ typeof(pg->linear_pt_count) oc;
++
++ oc = arch_fetch_and_add(&pg->linear_pt_count, -1);
++ ASSERT(oc > 0);
++}
++
++static bool_t inc_linear_uses(struct page_info *pg)
++{
++ typeof(pg->linear_pt_count) nc = read_atomic(&pg->linear_pt_count), oc;
++
++ do {
++ /* See the respective comment in inc_linear_entries(). */
++ BUILD_BUG_ON(sizeof(nc) >= sizeof(int));
++ oc = nc--;
++ if ( nc >= 0 )
++ return 0;
++ nc = cmpxchg(&pg->linear_pt_count, oc, nc);
++ } while ( oc != nc );
++
++ return 1;
++}
++
++static void dec_linear_uses(struct page_info *pg)
++{
++ typeof(pg->linear_pt_count) oc;
++
++ oc = arch_fetch_and_add(&pg->linear_pt_count, 1);
++ ASSERT(oc < 0);
++}
++
+ /*
+ * We allow root tables to map each other (a.k.a. linear page tables). It
+ * needs some special care with reference counts and access permissions:
+@@ -761,15 +816,35 @@ get_##level##_linear_pagetable( \
+ \
+ if ( (pfn = level##e_get_pfn(pde)) != pde_pfn ) \
+ { \
++ struct page_info *ptpg = mfn_to_page(pde_pfn); \
++ \
++ /* Make sure the page table belongs to the correct domain. */ \
++ if ( unlikely(page_get_owner(ptpg) != d) ) \
++ return 0; \
++ \
+ /* Make sure the mapped frame belongs to the correct domain. */ \
+ if ( unlikely(!get_page_from_pagenr(pfn, d)) ) \
+ return 0; \
+ \
+ /* \
+- * Ensure that the mapped frame is an already-validated page table. \
++ * Ensure that the mapped frame is an already-validated page table \
++ * and is not itself having linear entries, as well as that the \
++ * containing page table is not iself in use as a linear page table \
++ * elsewhere. \
+ * If so, atomically increment the count (checking for overflow). \
+ */ \
+ page = mfn_to_page(pfn); \
++ if ( !inc_linear_entries(ptpg) ) \
++ { \
++ put_page(page); \
++ return 0; \
++ } \
++ if ( !inc_linear_uses(page) ) \
++ { \
++ dec_linear_entries(ptpg); \
++ put_page(page); \
++ return 0; \
++ } \
+ y = page->u.inuse.type_info; \
+ do { \
+ x = y; \
+@@ -777,6 +852,8 @@ get_##level##_linear_pagetable( \
+ unlikely((x & (PGT_type_mask|PGT_validated)) != \
+ (PGT_##level##_page_table|PGT_validated)) ) \
+ { \
++ dec_linear_uses(page); \
++ dec_linear_entries(ptpg); \
+ put_page(page); \
+ return 0; \
+ } \
+@@ -1201,6 +1278,9 @@ get_page_from_l4e(
+ l3e_remove_flags((pl3e), _PAGE_USER|_PAGE_RW|_PAGE_ACCESSED); \
+ } while ( 0 )
+
++static int _put_page_type(struct page_info *page, bool_t preemptible,
++ struct page_info *ptpg);
++
+ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner)
+ {
+ unsigned long pfn = l1e_get_pfn(l1e);
+@@ -1270,17 +1350,22 @@ static int put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
+ if ( l2e_get_flags(l2e) & _PAGE_PSE )
+ put_superpage(l2e_get_pfn(l2e));
+ else
+- put_page_and_type(l2e_get_page(l2e));
++ {
++ struct page_info *pg = l2e_get_page(l2e);
++ int rc = _put_page_type(pg, 0, mfn_to_page(pfn));
++
++ ASSERT(!rc);
++ put_page(pg);
++ }
+
+ return 0;
+ }
+
+-static int __put_page_type(struct page_info *, int preemptible);
+-
+ static int put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn,
+ int partial, bool_t defer)
+ {
+ struct page_info *pg;
++ int rc;
+
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || (l3e_get_pfn(l3e) == pfn) )
+ return 1;
+@@ -1303,21 +1388,28 @@ static int put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn,
+ if ( unlikely(partial > 0) )
+ {
+ ASSERT(!defer);
+- return __put_page_type(pg, 1);
++ return _put_page_type(pg, 1, mfn_to_page(pfn));
+ }
+
+ if ( defer )
+ {
++ current->arch.old_guest_ptpg = mfn_to_page(pfn);
+ current->arch.old_guest_table = pg;
+ return 0;
+ }
+
+- return put_page_and_type_preemptible(pg);
++ rc = _put_page_type(pg, 1, mfn_to_page(pfn));
++ if ( likely(!rc) )
++ put_page(pg);
++
++ return rc;
+ }
+
+ static int put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn,
+ int partial, bool_t defer)
+ {
++ int rc = 1;
++
+ if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) &&
+ (l4e_get_pfn(l4e) != pfn) )
+ {
+@@ -1326,18 +1418,22 @@ static int put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn,
+ if ( unlikely(partial > 0) )
+ {
+ ASSERT(!defer);
+- return __put_page_type(pg, 1);
++ return _put_page_type(pg, 1, mfn_to_page(pfn));
+ }
+
+ if ( defer )
+ {
++ current->arch.old_guest_ptpg = mfn_to_page(pfn);
+ current->arch.old_guest_table = pg;
+ return 0;
+ }
+
+- return put_page_and_type_preemptible(pg);
++ rc = _put_page_type(pg, 1, mfn_to_page(pfn));
++ if ( likely(!rc) )
++ put_page(pg);
+ }
+- return 1;
++
++ return rc;
+ }
+
+ static int alloc_l1_table(struct page_info *page)
+@@ -1535,6 +1631,7 @@ static int alloc_l3_table(struct page_info *page)
+ {
+ page->nr_validated_ptes = i;
+ page->partial_pte = 0;
++ current->arch.old_guest_ptpg = NULL;
+ current->arch.old_guest_table = page;
+ }
+ while ( i-- > 0 )
+@@ -1627,6 +1724,7 @@ static int alloc_l4_table(struct page_info *page)
+ {
+ if ( current->arch.old_guest_table )
+ page->nr_validated_ptes++;
++ current->arch.old_guest_ptpg = NULL;
+ current->arch.old_guest_table = page;
+ }
+ }
+@@ -2369,14 +2467,20 @@ int free_page_type(struct page_info *pag
+ }
+
+
+-static int __put_final_page_type(
+- struct page_info *page, unsigned long type, int preemptible)
++static int _put_final_page_type(struct page_info *page, unsigned long type,
++ bool_t preemptible, struct page_info *ptpg)
+ {
+ int rc = free_page_type(page, type, preemptible);
+
+ /* No need for atomic update of type_info here: noone else updates it. */
+ if ( rc == 0 )
+ {
++ if ( ptpg && PGT_type_equal(type, ptpg->u.inuse.type_info) )
++ {
++ dec_linear_uses(page);
++ dec_linear_entries(ptpg);
++ }
++ ASSERT(!page->linear_pt_count || page_get_owner(page)->is_dying);
+ /*
+ * Record TLB information for flush later. We do not stamp page tables
+ * when running in shadow mode:
+@@ -2412,8 +2516,8 @@ static int __put_final_page_type(
+ }
+
+
+-static int __put_page_type(struct page_info *page,
+- int preemptible)
++static int _put_page_type(struct page_info *page, bool_t preemptible,
++ struct page_info *ptpg)
+ {
+ unsigned long nx, x, y = page->u.inuse.type_info;
+ int rc = 0;
+@@ -2440,12 +2544,28 @@ static int __put_page_type(struct page_info *page,
+ x, nx)) != x) )
+ continue;
+ /* We cleared the 'valid bit' so we do the clean up. */
+- rc = __put_final_page_type(page, x, preemptible);
++ rc = _put_final_page_type(page, x, preemptible, ptpg);
++ ptpg = NULL;
+ if ( x & PGT_partial )
+ put_page(page);
+ break;
+ }
+
++ if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
++ {
++ /*
++ * page_set_tlbflush_timestamp() accesses the same union
++ * linear_pt_count lives in. Unvalidated page table pages,
++ * however, should occur during domain destruction only
++ * anyway. Updating of linear_pt_count luckily is not
++ * necessary anymore for a dying domain.
++ */
++ ASSERT(page_get_owner(page)->is_dying);
++ ASSERT(page->linear_pt_count < 0);
++ ASSERT(ptpg->linear_pt_count > 0);
++ ptpg = NULL;
++ }
++
+ /*
+ * Record TLB information for flush later. We do not stamp page
+ * tables when running in shadow mode:
+@@ -2465,6 +2585,13 @@ static int __put_page_type(struct page_info *page,
+ return -EINTR;
+ }
+
++ if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
++ {
++ ASSERT(!rc);
++ dec_linear_uses(page);
++ dec_linear_entries(ptpg);
++ }
++
+ return rc;
+ }
+
+@@ -2599,6 +2726,7 @@ static int __get_page_type(struct page_info *page, unsigned long type,
+ page->nr_validated_ptes = 0;
+ page->partial_pte = 0;
+ }
++ page->linear_pt_count = 0;
+ rc = alloc_page_type(page, type, preemptible);
+ }
+
+@@ -2610,7 +2738,7 @@ static int __get_page_type(struct page_info *page, unsigned long type,
+
+ void put_page_type(struct page_info *page)
+ {
+- int rc = __put_page_type(page, 0);
++ int rc = _put_page_type(page, 0, NULL);
+ ASSERT(rc == 0);
+ (void)rc;
+ }
+@@ -2626,7 +2754,7 @@ int get_page_type(struct page_info *page, unsigned long type)
+
+ int put_page_type_preemptible(struct page_info *page)
+ {
+- return __put_page_type(page, 1);
++ return _put_page_type(page, 1, NULL);
+ }
+
+ int get_page_type_preemptible(struct page_info *page, unsigned long type)
+@@ -2832,11 +2960,14 @@ int put_old_guest_table(struct vcpu *v)
+ if ( !v->arch.old_guest_table )
+ return 0;
+
+- switch ( rc = put_page_and_type_preemptible(v->arch.old_guest_table) )
++ switch ( rc = _put_page_type(v->arch.old_guest_table, 1,
++ v->arch.old_guest_ptpg) )
+ {
+ case -EINTR:
+ case -ERESTART:
+ return -ERESTART;
++ case 0:
++ put_page(v->arch.old_guest_table);
+ }
+
+ v->arch.old_guest_table = NULL;
+@@ -2993,6 +3124,7 @@ int new_guest_cr3(unsigned long mfn)
+ rc = -ERESTART;
+ /* fallthrough */
+ case -ERESTART:
++ curr->arch.old_guest_ptpg = NULL;
+ curr->arch.old_guest_table = page;
+ break;
+ default:
+@@ -3260,7 +3392,10 @@ long do_mmuext_op(
+ if ( type == PGT_l1_page_table )
+ put_page_and_type(page);
+ else
++ {
++ curr->arch.old_guest_ptpg = NULL;
+ curr->arch.old_guest_table = page;
++ }
+ }
+ }
+
+@@ -3293,6 +3428,7 @@ long do_mmuext_op(
+ {
+ case -EINTR:
+ case -ERESTART:
++ curr->arch.old_guest_ptpg = NULL;
+ curr->arch.old_guest_table = page;
+ rc = 0;
+ break;
+@@ -3371,6 +3507,7 @@ long do_mmuext_op(
+ rc = -ERESTART;
+ /* fallthrough */
+ case -ERESTART:
++ curr->arch.old_guest_ptpg = NULL;
+ curr->arch.old_guest_table = page;
+ break;
+ default:
+diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
+index 165e533ab3..5ef761be8b 100644
+--- a/xen/include/asm-x86/domain.h
++++ b/xen/include/asm-x86/domain.h
+@@ -529,6 +529,8 @@ struct arch_vcpu
+ pagetable_t guest_table_user; /* (MFN) x86/64 user-space pagetable */
+ pagetable_t guest_table; /* (MFN) guest notion of cr3 */
+ struct page_info *old_guest_table; /* partially destructed pagetable */
++ struct page_info *old_guest_ptpg; /* containing page table of the */
++ /* former, if any */
+ /* guest_table holds a ref to the page, and also a type-count unless
+ * shadow refcounts are in use */
+ pagetable_t shadow_table[4]; /* (MFN) shadow(s) of guest */
+diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
+index a30e76db1e..905c7971f2 100644
+--- a/xen/include/asm-x86/mm.h
++++ b/xen/include/asm-x86/mm.h
+@@ -125,11 +125,11 @@ struct page_info
+ u32 tlbflush_timestamp;
+
+ /*
+- * When PGT_partial is true then this field is valid and indicates
+- * that PTEs in the range [0, @nr_validated_ptes) have been validated.
+- * An extra page reference must be acquired (or not dropped) whenever
+- * PGT_partial gets set, and it must be dropped when the flag gets
+- * cleared. This is so that a get() leaving a page in partially
++ * When PGT_partial is true then the first two fields are valid and
++ * indicate that PTEs in the range [0, @nr_validated_ptes) have been
++ * validated. An extra page reference must be acquired (or not dropped)
++ * whenever PGT_partial gets set, and it must be dropped when the flag
++ * gets cleared. This is so that a get() leaving a page in partially
+ * validated state (where the caller would drop the reference acquired
+ * due to the getting of the type [apparently] failing [-ERESTART])
+ * would not accidentally result in a page left with zero general
+@@ -153,10 +153,18 @@ struct page_info
+ * put_page_from_lNe() (due to the apparent failure), and hence it
+ * must be dropped when the put operation is resumed (and completes),
+ * but it must not be acquired if picking up the page for validation.
++ *
++ * The 3rd field, @linear_pt_count, indicates
++ * - by a positive value, how many same-level page table entries a page
++ * table has,
++ * - by a negative value, in how many same-level page tables a page is
++ * in use.
+ */
+ struct {
+- u16 nr_validated_ptes;
+- s8 partial_pte;
++ u16 nr_validated_ptes:PAGETABLE_ORDER + 1;
++ u16 :16 - PAGETABLE_ORDER - 1 - 2;
++ s16 partial_pte:2;
++ s16 linear_pt_count;
+ };
+
+ /*
+@@ -207,6 +215,9 @@ struct page_info
+ #define PGT_count_width PG_shift(9)
+ #define PGT_count_mask ((1UL<<PGT_count_width)-1)
+
++/* Are the 'type mask' bits identical? */
++#define PGT_type_equal(x, y) (!(((x) ^ (y)) & PGT_type_mask))
++
+ /* Cleared when the owning guest 'frees' this page. */
+ #define _PGC_allocated PG_shift(1)
+ #define PGC_allocated PG_mask(1, 1)
+--
+2.14.1
+
Index: head/emulators/xen-kernel47/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
+++ head/emulators/xen-kernel47/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
@@ -0,0 +1,45 @@
+From 9b76908e6e074d7efbeafe6bad066ecc5f3c3c43 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Wed, 17 Jan 2018 17:23:37 +0100
+Subject: [PATCH] x86/mm: Always set _PAGE_ACCESSED on L4e updates
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+master commit: bd61fe94bee0556bc2f64999a4a8315b93f90f21
+master date: 2018-01-15 13:53:16 +0000
+---
+ xen/arch/x86/mm.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index ada12c05c5..50f500c940 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -1296,11 +1296,23 @@ get_page_from_l4e(
+ _PAGE_USER|_PAGE_RW); \
+ } while ( 0 )
+
++/*
++ * When shadowing an L4 behind the guests back (e.g. for per-pcpu
++ * purposes), we cannot efficiently sync access bit updates from hardware
++ * (on the shadow tables) back into the guest view.
++ *
++ * We therefore unconditionally set _PAGE_ACCESSED even in the guests
++ * view. This will appear to the guest as a CPU which proactively pulls
++ * all valid L4e's into its TLB, which is compatible with the x86 ABI.
++ *
++ * At the time of writing, all PV guests set the access bit anyway, so
++ * this is no actual change in their behaviour.
++ */
+ #define adjust_guest_l4e(pl4e, d) \
+ do { \
+ if ( likely(l4e_get_flags((pl4e)) & _PAGE_PRESENT) && \
+ likely(!is_pv_32bit_domain(d)) ) \
+- l4e_add_flags((pl4e), _PAGE_USER); \
++ l4e_add_flags((pl4e), _PAGE_USER | _PAGE_ACCESSED); \
+ } while ( 0 )
+
+ #define unadjust_guest_l3e(pl3e, d) \
+--
+2.15.1
+
Index: head/emulators/xen-kernel47/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
===================================================================
--- head/emulators/xen-kernel47/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
+++ head/emulators/xen-kernel47/files/0001-xen-logdirty-prevent-preemption-if-finished.patch
@@ -0,0 +1,44 @@
+From 7a0ed7f3c2dcb1f104b6f70223d48d8826aec7f2 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 31 May 2016 16:07:26 +0200
+Subject: [PATCH 1/2] xen/logdirty: prevent preemption if finished
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+While working on PVH migration support I've realized that
+paging_log_dirty_op sometimes restarts with sc->pages == pages, which means
+there's no more work to do. Avoid this by adding a check in the preemption
+points of the function.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+---
+ xen/arch/x86/mm/paging.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
+index 8219bb6..ed94ff7 100644
+--- a/xen/arch/x86/mm/paging.c
++++ b/xen/arch/x86/mm/paging.c
+@@ -519,7 +519,8 @@ static int paging_log_dirty_op(struct domain *d,
+ if ( l2 )
+ unmap_domain_page(l2);
+
+- if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() )
++ if ( i3 < LOGDIRTY_NODE_ENTRIES - 1 && hypercall_preempt_check() &&
++ sc->pages != pages )
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4;
+ d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
+@@ -531,7 +532,7 @@ static int paging_log_dirty_op(struct domain *d,
+ unmap_domain_page(l3);
+
+ if ( !rv && i4 < LOGDIRTY_NODE_ENTRIES - 1 &&
+- hypercall_preempt_check() )
++ hypercall_preempt_check() && sc->pages != pages )
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
+ d->arch.paging.preempt.log_dirty.i3 = 0;
+--
+2.7.4 (Apple Git-66)
+
Index: head/emulators/xen-kernel47/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
+++ head/emulators/xen-kernel47/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch
@@ -0,0 +1,69 @@
+From e5a1bf46187b0d39ec7e8c46e11c42027840747c Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Fri, 10 Mar 2017 01:08:26 +0900
+Subject: [PATCH 2/2] build/clang: fix XSM dummy policy when using clang 4.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There seems to be some weird bug in clang 4.0 that prevents xsm_pmu_op from
+working as expected, and vpmu.o ends up with a reference to
+__xsm_action_mismatch_detected which makes the build fail:
+
+[...]
+ld -melf_x86_64_fbsd -T xen.lds -N prelink.o \
+ xen/common/symbols-dummy.o -o xen/.xen-syms.0
+prelink.o: In function `xsm_default_action':
+xen/include/xsm/dummy.h:80: undefined reference to `__xsm_action_mismatch_detected'
+xen/xen/include/xsm/dummy.h:80: relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__xsm_action_mismatch_detected'
+ld: xen/xen/.xen-syms.0: hidden symbol `__xsm_action_mismatch_detected' isn't defined
+
+Then doing a search in the objects files:
+
+# find xen/ -type f -name '*.o' -print0 | xargs -0 bash -c \
+ 'for filename; do nm "$filename" | \
+ grep -q __xsm_action_mismatch_detected && echo "$filename"; done' bash
+xen/arch/x86/prelink.o
+xen/arch/x86/cpu/vpmu.o
+xen/arch/x86/cpu/built_in.o
+xen/arch/x86/built_in.o
+
+The current patch is the only way I've found to fix this so far, by simply
+moving the XSM_PRIV check into the default case in xsm_pmu_op. This also fixes
+the behavior of do_xenpmu_op, which will now return -EINVAL for unknown
+XENPMU_* operations, instead of -EPERM when called by a privileged domain.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+---
+Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
+---
+ xen/include/xsm/dummy.h | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
+index abbe282..0039c39 100644
+--- a/xen/include/xsm/dummy.h
++++ b/xen/include/xsm/dummy.h
+@@ -711,18 +711,13 @@ static XSM_INLINE int xsm_pmu_op (XSM_DEFAULT_ARG struct domain *d, unsigned int
+ XSM_ASSERT_ACTION(XSM_OTHER);
+ switch ( op )
+ {
+- case XENPMU_mode_set:
+- case XENPMU_mode_get:
+- case XENPMU_feature_set:
+- case XENPMU_feature_get:
+- return xsm_default_action(XSM_PRIV, d, current->domain);
+ case XENPMU_init:
+ case XENPMU_finish:
+ case XENPMU_lvtpc_set:
+ case XENPMU_flush:
+ return xsm_default_action(XSM_HOOK, d, current->domain);
+ default:
+- return -EPERM;
++ return xsm_default_action(XSM_PRIV, d, current->domain);
+ }
+ }
+
+--
+2.10.1 (Apple Git-78)
+
Index: head/emulators/xen-kernel47/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
+++ head/emulators/xen-kernel47/files/0002-gnttab-fix-unmap-pin-accounting-race.patch
@@ -0,0 +1,102 @@
+From 2c146b4f763f47180a0effb8d8045b0ebb93652c Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Fri, 2 Jun 2017 12:22:42 +0100
+Subject: [PATCH 2/4] gnttab: fix unmap pin accounting race
+
+Once all {writable} mappings of a grant entry have been unmapped, the
+hypervisor informs the guest that the grant entry has been released by
+clearing the _GTF_{reading,writing} usage flags in the guest's grant
+table as appropriate.
+
+Unfortunately, at the moment, the code that updates the accounting
+happens in a different critical section than the one which updates the
+usage flags; this means that under the right circumstances, there may be
+a window in time after the hypervisor reported the grant as being free
+during which the grant referee still had access to the page.
+
+Move the grant accounting code into the same critical section as the
+reporting code to make sure this kind of race can't happen.
+
+This is part of XSA-218.
+
+Reported-by: Jann Horn <jannh.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 32 +++++++++++++++++---------------
+ 1 file changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index 8b22299..cfc483f 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -1150,15 +1150,8 @@ __gnttab_unmap_common(
+ PIN_FAIL(act_release_out, GNTST_general_error,
+ "Bad frame number doesn't match gntref. (%lx != %lx)\n",
+ op->frame, act->frame);
+- if ( op->flags & GNTMAP_device_map )
+- {
+- ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
+- op->map->flags &= ~GNTMAP_device_map;
+- if ( op->flags & GNTMAP_readonly )
+- act->pin -= GNTPIN_devr_inc;
+- else
+- act->pin -= GNTPIN_devw_inc;
+- }
++
++ op->map->flags &= ~GNTMAP_device_map;
+ }
+
+ if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
+@@ -1168,12 +1161,7 @@ __gnttab_unmap_common(
+ op->flags)) < 0 )
+ goto act_release_out;
+
+- ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
+ op->map->flags &= ~GNTMAP_host_map;
+- if ( op->flags & GNTMAP_readonly )
+- act->pin -= GNTPIN_hstr_inc;
+- else
+- act->pin -= GNTPIN_hstw_inc;
+ }
+
+ act_release_out:
+@@ -1266,6 +1254,12 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ else
+ put_page_and_type(pg);
+ }
++
++ ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
++ if ( op->flags & GNTMAP_readonly )
++ act->pin -= GNTPIN_devr_inc;
++ else
++ act->pin -= GNTPIN_devw_inc;
+ }
+
+ if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
+@@ -1274,7 +1268,9 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ {
+ /*
+ * Suggests that __gntab_unmap_common failed in
+- * replace_grant_host_mapping() so nothing further to do
++ * replace_grant_host_mapping() or IOMMU handling, so nothing
++ * further to do (short of re-establishing the mapping in the
++ * latter case).
+ */
+ goto act_release_out;
+ }
+@@ -1285,6 +1281,12 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ put_page_type(pg);
+ put_page(pg);
+ }
++
++ ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
++ if ( op->flags & GNTMAP_readonly )
++ act->pin -= GNTPIN_hstr_inc;
++ else
++ act->pin -= GNTPIN_hstw_inc;
+ }
+
+ if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
+++ head/emulators/xen-kernel47/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch
@@ -0,0 +1,42 @@
+From 8894a0c20d920aada305aade0591c1e77167b1db Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Fri, 2 Jun 2017 15:21:27 +0100
+Subject: [PATCH 2/4] gnttab: never create host mapping unless asked to
+
+We shouldn't create a host mapping unless asked to even in the case of
+mapping a granted MMIO page. In particular the mapping wouldn't be torn
+down when processing the matching unmap request.
+
+This is part of XSA-224.
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index 69cbdb6..452538e 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -911,10 +911,13 @@ __gnttab_map_grant_ref(
+ goto undo_out;
+ }
+
+- rc = create_grant_host_mapping(
+- op->host_addr, frame, op->flags, cache_flags);
+- if ( rc != GNTST_okay )
+- goto undo_out;
++ if ( op->flags & GNTMAP_host_map )
++ {
++ rc = create_grant_host_mapping(op->host_addr, frame, op->flags,
++ cache_flags);
++ if ( rc != GNTST_okay )
++ goto undo_out;
++ }
+ }
+ else if ( owner == rd || owner == dom_cow )
+ {
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
+++ head/emulators/xen-kernel47/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch
@@ -0,0 +1,109 @@
+From 01feeda5363dd8d2fea8395c2c435203751c8ba5 Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Fri, 10 Nov 2017 16:53:55 +0000
+Subject: [PATCH 2/2] p2m: Check return value of p2m_set_entry() when
+ decreasing reservation
+
+If the entire range specified to p2m_pod_decrease_reservation() is marked
+populate-on-demand, then it will make a single p2m_set_entry() call,
+reducing its PoD entry count.
+
+Unfortunately, in the right circumstances, this p2m_set_entry() call
+may fail. It that case, repeated calls to decrease_reservation() may
+cause p2m->pod.entry_count to fall below zero, potentially tripping
+over BUG_ON()s to the contrary.
+
+Instead, check to see if the entry succeeded, and return false if not.
+The caller will then call guest_remove_page() on the gfns, which will
+return -EINVAL upon finding no valid memory there to return.
+
+Unfortunately if the order > 0, the entry may have partially changed.
+A domain_crash() is probably the safest thing in that case.
+
+Other p2m_set_entry() calls in the same function should be fine,
+because they are writing the entry at its current order. Nonetheless,
+check the return value and crash if our assumption turns otu to be
+wrong.
+
+This is part of XSA-247.
+
+Reported-by: George Dunlap <george.dunlap.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+v2: Crash the domain if we're not sure it's safe (or if we think it
+can't happen)
+---
+ xen/arch/x86/mm/p2m-pod.c | 42 +++++++++++++++++++++++++++++++++---------
+ 1 file changed, 33 insertions(+), 9 deletions(-)
+
+diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
+index 5ec8a37949..91d309647e 100644
+--- a/xen/arch/x86/mm/p2m-pod.c
++++ b/xen/arch/x86/mm/p2m-pod.c
+@@ -557,11 +557,23 @@ p2m_pod_decrease_reservation(struct domain *d,
+
+ if ( !nonpod )
+ {
+- /* All PoD: Mark the whole region invalid and tell caller
+- * we're done. */
+- p2m_set_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid,
+- p2m->default_access);
+- p2m->pod.entry_count-=(1<<order);
++ /*
++ * All PoD: Mark the whole region invalid and tell caller
++ * we're done.
++ */
++ if ( p2m_set_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid,
++ p2m->default_access) )
++ {
++ /*
++ * If this fails, we can't tell how much of the range was changed.
++ * Best to crash the domain unless we're sure a partial change is
++ * impossible.
++ */
++ if ( order != 0 )
++ domain_crash(d);
++ goto out_unlock;
++ }
++ p2m->pod.entry_count -= 1UL << order;
+ BUG_ON(p2m->pod.entry_count < 0);
+ ret = 1;
+ goto out_entry_check;
+@@ -602,8 +614,14 @@ p2m_pod_decrease_reservation(struct domain *d,
+ n = 1UL << cur_order;
+ if ( t == p2m_populate_on_demand )
+ {
+- p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
+- p2m_invalid, p2m->default_access);
++ /* This shouldn't be able to fail */
++ if ( p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
++ p2m_invalid, p2m->default_access) )
++ {
++ ASSERT_UNREACHABLE();
++ domain_crash(d);
++ goto out_unlock;
++ }
+ p2m->pod.entry_count -= n;
+ BUG_ON(p2m->pod.entry_count < 0);
+ pod -= n;
+@@ -624,8 +642,14 @@ p2m_pod_decrease_reservation(struct domain *d,
+
+ page = mfn_to_page(mfn);
+
+- p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
+- p2m_invalid, p2m->default_access);
++ /* This shouldn't be able to fail */
++ if ( p2m_set_entry(p2m, gpfn + i, _mfn(INVALID_MFN), cur_order,
++ p2m_invalid, p2m->default_access) )
++ {
++ ASSERT_UNREACHABLE();
++ domain_crash(d);
++ goto out_unlock;
++ }
+ p2m_tlb_flush_sync(p2m);
+ for ( j = 0; j < n; ++j )
+ set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
+--
+2.15.0
+
Index: head/emulators/xen-kernel47/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
+++ head/emulators/xen-kernel47/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch
@@ -0,0 +1,163 @@
+From e19d0af4ee2ae9e42a85db639fd6848e72f5658b Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Wed, 17 Jan 2018 17:24:59 +0100
+Subject: [PATCH 2/2] x86: allow Meltdown band-aid to be disabled
+
+First of all we don't need it on AMD systems. Additionally allow its use
+to be controlled by command line option. For best backportability, this
+intentionally doesn't use alternative instruction patching to achieve
+the intended effect - while we likely want it, this will be later
+follow-up.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+master commit: e871e80c38547d9faefc6604532ba3e985e65873
+master date: 2018-01-16 17:50:59 +0100
+---
+ docs/misc/xen-command-line.markdown | 12 ++++++++++++
+ xen/arch/x86/domain.c | 7 +++++--
+ xen/arch/x86/mm.c | 2 +-
+ xen/arch/x86/smpboot.c | 17 ++++++++++++++---
+ xen/arch/x86/x86_64/entry.S | 2 ++
+ 5 files changed, 34 insertions(+), 6 deletions(-)
+
+diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
+index 2dacb5d073..aecf9fd49d 100644
+--- a/docs/misc/xen-command-line.markdown
++++ b/docs/misc/xen-command-line.markdown
+@@ -1621,6 +1621,18 @@ In the case that x2apic is in use, this option switches between physical and
+ clustered mode. The default, given no hint from the **FADT**, is cluster
+ mode.
+
++### xpti
++> `= <boolean>`
++
++> Default: `false` on AMD hardware
++> Default: `true` everywhere else
++
++Override default selection of whether to isolate 64-bit PV guest page
++tables.
++
++** WARNING: Not yet a complete isolation implementation, but better than
++nothing. **
++
+ ### xsave
+ > `= <boolean>`
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index 3cf18f95b7..a1bda5e12d 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -1945,12 +1945,15 @@ static void paravirt_ctxt_switch_from(struct vcpu *v)
+
+ static void paravirt_ctxt_switch_to(struct vcpu *v)
+ {
++ root_pgentry_t *root_pgt = this_cpu(root_pgt);
+ unsigned long cr4;
+
+ switch_kernel_stack(v);
+
+- this_cpu(root_pgt)[root_table_offset(PERDOMAIN_VIRT_START)] =
+- l4e_from_page(v->domain->arch.perdomain_l3_pg, __PAGE_HYPERVISOR_RW);
++ if ( root_pgt )
++ root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
++ l4e_from_page(v->domain->arch.perdomain_l3_pg,
++ __PAGE_HYPERVISOR_RW);
+
+ cr4 = pv_guest_cr4_to_real_cr4(v);
+ if ( unlikely(cr4 != read_cr4()) )
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index c9e4003989..07015e3160 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4007,7 +4007,7 @@ long do_mmu_update(
+ rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
+ cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
+ if ( !rc )
+- sync_guest = 1;
++ sync_guest = !!this_cpu(root_pgt);
+ break;
+ case PGT_writable_page:
+ perfc_incr(writable_mmu_updates);
+diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
+index eaeec5acf0..f2f47f612a 100644
+--- a/xen/arch/x86/smpboot.c
++++ b/xen/arch/x86/smpboot.c
+@@ -320,7 +320,7 @@ void start_secondary(void *unused)
+ spin_debug_disable();
+
+ get_cpu_info()->xen_cr3 = 0;
+- get_cpu_info()->pv_cr3 = __pa(this_cpu(root_pgt));
++ get_cpu_info()->pv_cr3 = this_cpu(root_pgt) ? __pa(this_cpu(root_pgt)) : 0;
+
+ load_system_tables();
+
+@@ -729,14 +729,20 @@ static int clone_mapping(const void *ptr, root_pgentry_t *rpt)
+ return 0;
+ }
+
++static __read_mostly int8_t opt_xpti = -1;
++boolean_param("xpti", opt_xpti);
+ DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
+
+ static int setup_cpu_root_pgt(unsigned int cpu)
+ {
+- root_pgentry_t *rpt = alloc_xen_pagetable();
++ root_pgentry_t *rpt;
+ unsigned int off;
+ int rc;
+
++ if ( !opt_xpti )
++ return 0;
++
++ rpt = alloc_xen_pagetable();
+ if ( !rpt )
+ return -ENOMEM;
+
+@@ -977,10 +983,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+
+ stack_base[0] = stack_start;
+
++ if ( opt_xpti < 0 )
++ opt_xpti = boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
++
+ rc = setup_cpu_root_pgt(0);
+ if ( rc )
+ panic("Error %d setting up PV root page table\n", rc);
+- get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
++ if ( per_cpu(root_pgt, 0) )
++ get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
+
+ set_nr_sockets();
+
+@@ -1048,6 +1058,7 @@ void __init smp_prepare_boot_cpu(void)
+ cpumask_set_cpu(smp_processor_id(), &cpu_present_map);
+
+ get_cpu_info()->xen_cr3 = 0;
++ get_cpu_info()->pv_cr3 = 0;
+ }
+
+ static void
+diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
+index d63e734bb3..2a569952e3 100644
+--- a/xen/arch/x86/x86_64/entry.S
++++ b/xen/arch/x86/x86_64/entry.S
+@@ -45,6 +45,7 @@ restore_all_guest:
+ movabs $DIRECTMAP_VIRT_START, %rcx
+ mov %rdi, %rax
+ and %rsi, %rdi
++ jz .Lrag_keep_cr3
+ and %r9, %rsi
+ add %rcx, %rdi
+ add %rcx, %rsi
+@@ -61,6 +62,7 @@ restore_all_guest:
+ rep movsq
+ mov %r9, STACK_CPUINFO_FIELD(xen_cr3)(%rdx)
+ write_cr3 rax, rdi, rsi
++.Lrag_keep_cr3:
+
+ RESTORE_ALL
+ testw $TRAP_syscall,4(%rsp)
+--
+2.15.1
+
Index: head/emulators/xen-kernel47/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
+++ head/emulators/xen-kernel47/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
@@ -0,0 +1,66 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
+
+(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
+actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
+This in turn requires bypassing the XSM check in physdev_unmap_pirq()
+for the HVM emuirq case just like is being done in physdev_map_pirq().
+The primary goal security wise, however, is to no longer allow HVM
+guests, by specifying their own domain ID instead of DOMID_SELF, to
+enter code paths intended for PV guest and the control domains of HVM
+guests only.
+
+This is part of XSA-237.
+
+Reported-by: HW42 <hw42@ipsumj.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/x86/physdev.c
++++ b/xen/arch/x86/physdev.c
+@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
+ if ( d == NULL )
+ return -ESRCH;
+
+- ret = xsm_map_domain_pirq(XSM_TARGET, d);
++ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
+ if ( ret )
+ goto free_domain;
+
+@@ -255,13 +255,14 @@ int physdev_map_pirq(domid_t domid, int
+ int physdev_unmap_pirq(domid_t domid, int pirq)
+ {
+ struct domain *d;
+- int ret;
++ int ret = 0;
+
+ d = rcu_lock_domain_by_any_id(domid);
+ if ( d == NULL )
+ return -ESRCH;
+
+- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
++ if ( domid != DOMID_SELF || !is_hvm_domain(d) )
++ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
+ if ( ret )
+ goto free_domain;
+
+--- a/xen/include/xsm/dummy.h
++++ b/xen/include/xsm/dummy.h
+@@ -453,7 +453,7 @@ static XSM_INLINE char *xsm_show_irq_sid
+
+ static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
+ {
+- XSM_ASSERT_ACTION(XSM_TARGET);
++ XSM_ASSERT_ACTION(XSM_DM_PRIV);
+ return xsm_default_action(action, current->domain, d);
+ }
+
+@@ -465,7 +465,7 @@ static XSM_INLINE int xsm_map_domain_irq
+
+ static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
+ {
+- XSM_ASSERT_ACTION(XSM_TARGET);
++ XSM_ASSERT_ACTION(XSM_DM_PRIV);
+ return xsm_default_action(action, current->domain, d);
+ }
+
Index: head/emulators/xen-kernel47/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
+++ head/emulators/xen-kernel47/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch
@@ -0,0 +1,82 @@
+From 9a4b34729f1bb92eea1e1efe52e6face9f0b17ae Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Fri, 22 Sep 2017 11:46:55 +0100
+Subject: [PATCH 2/2] x86/mm: Disable PV linear pagetables by default
+
+Allowing pagetables to point to other pagetables of the same level
+(often called 'linear pagetables') has been included in Xen since its
+inception. But it is not used by the most common PV guests (Linux,
+NetBSD, minios), and has been the source of a number of subtle
+reference-counting bugs.
+
+Add a command-line option to control whether PV linear pagetables are
+allowed (disabled by default).
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+---
+Changes since v2:
+- s/_/-/; in command-line option
+- Added __read_mostly
+---
+ docs/misc/xen-command-line.markdown | 15 +++++++++++++++
+ xen/arch/x86/mm.c | 9 +++++++++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
+index 73f5265fc6..061aff5edc 100644
+--- a/docs/misc/xen-command-line.markdown
++++ b/docs/misc/xen-command-line.markdown
+@@ -1280,6 +1280,21 @@ The following resources are available:
+ CDP, one COS will corespond two CBMs other than one with CAT, due to the
+ sum of CBMs is fixed, that means actual `cos_max` in use will automatically
+ reduce to half when CDP is enabled.
++
++### pv-linear-pt
++> `= <boolean>`
++
++> Default: `false`
++
++Allow PV guests to have pagetable entries pointing to other pagetables
++of the same level (i.e., allowing L2 PTEs to point to other L2 pages).
++This technique is often called "linear pagetables", and is sometimes
++used to allow operating systems a simple way to consistently map the
++current process's pagetables into its own virtual address space.
++
++None of the most common PV operating systems (Linux, NetBSD, MiniOS)
++use this technique, but there may be custom operating systems which
++do.
+
+ ### reboot
+ > `= t[riple] | k[bd] | a[cpi] | p[ci] | P[ower] | e[fi] | n[o] [, [w]arm | [c]old]`
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index e81a461b91..f748d4a221 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -799,6 +799,9 @@ static void dec_linear_uses(struct page_info *pg)
+ * frame if it is mapped by a different root table. This is sufficient and
+ * also necessary to allow validation of a root table mapping itself.
+ */
++static bool_t __read_mostly pv_linear_pt_enable = 0;
++boolean_param("pv-linear-pt", pv_linear_pt_enable);
++
+ #define define_get_linear_pagetable(level) \
+ static int \
+ get_##level##_linear_pagetable( \
+@@ -808,6 +811,12 @@ get_##level##_linear_pagetable( \
+ struct page_info *page; \
+ unsigned long pfn; \
+ \
++ if ( !pv_linear_pt_enable ) \
++ { \
++ MEM_LOG("Attempt to create linear p.t. (feature disabled)"); \
++ return 0; \
++ } \
++ \
+ if ( (level##e_get_flags(pde) & _PAGE_RW) ) \
+ { \
+ MEM_LOG("Attempt to create linear p.t. with write perms"); \
+--
+2.14.1
+
Index: head/emulators/xen-kernel47/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
===================================================================
--- head/emulators/xen-kernel47/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
+++ head/emulators/xen-kernel47/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch
@@ -0,0 +1,244 @@
+From e253a2e2fb45197273cee7a7fa2b77f7a87cb67f Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 31 May 2016 16:07:26 +0200
+Subject: [PATCH 2/2] xen: rework paging_log_dirty_op to work with hvm guests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When the caller of paging_log_dirty_op is a hvm guest Xen would choke when
+trying to copy the dirty bitmap to the guest because the paging lock is
+already held.
+
+Fix this by independently mapping each page of the guest bitmap as needed
+without the paging lock held.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Cc: Tim Deegan <tim@xen.org>
+Cc: Jan Beulich <jbeulich@suse.com>
+Cc: Andrew Cooper <andrew.cooper3@citrix.com>
+---
+Changes since v6:
+ - Move the again label to the start of the function.
+ - Set all the preempt fields if we need to map a new page (just like on the
+ preempt case).
+
+Changes since v4:
+ - Indent again label.
+ - Replace bogus paddr_t cast with proper type.
+ - Update preempt.log_dirty before dropping the paging lock.
+
+Changes since v3:
+ - Drop last parameter from map_dirty_bitmap.
+ - Drop pointless initializers in paging_log_dirty_op.
+ - Add a new field to paging_domain in order to copy i2 position.
+ - Move the again case up to make sure we don't hold cached values of the
+ contents of log_dirty.
+ - Replace the BUG_ON in paging_log_dirty_op with an ASSERT.
+
+Changes since v2:
+ - Add checks for p2m_is_ram and p2m_is_discard_write when mapping a guest
+ page.
+ - Remove error checking from memset/memcpy, they unconditionally return
+ dst.
+---
+ xen/arch/x86/mm/paging.c | 97 +++++++++++++++++++++++++++++++++++++++-----
+ xen/include/asm-x86/domain.h | 1 +
+ 2 files changed, 87 insertions(+), 11 deletions(-)
+
+diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
+index ed94ff7..595c9d6 100644
+--- a/xen/arch/x86/mm/paging.c
++++ b/xen/arch/x86/mm/paging.c
+@@ -406,6 +406,51 @@ int paging_mfn_is_dirty(struct domain *d, mfn_t gmfn)
+ return rv;
+ }
+
++static inline void *map_dirty_bitmap(XEN_GUEST_HANDLE_64(uint8) dirty_bitmap,
++ unsigned long pages,
++ struct page_info **page)
++{
++ uint32_t pfec = PFEC_page_present | PFEC_write_access;
++ unsigned long gfn;
++ p2m_type_t p2mt;
++
++ gfn = paging_gva_to_gfn(current,
++ (unsigned long)(dirty_bitmap.p + (pages >> 3)),
++ &pfec);
++ if ( gfn == INVALID_GFN )
++ return NULL;
++
++ *page = get_page_from_gfn(current->domain, gfn, &p2mt, P2M_UNSHARE);
++
++ if ( !p2m_is_ram(p2mt) )
++ {
++ put_page(*page);
++ return NULL;
++ }
++ if ( p2m_is_paging(p2mt) )
++ {
++ put_page(*page);
++ p2m_mem_paging_populate(current->domain, gfn);
++ return NULL;
++ }
++ if ( p2m_is_shared(p2mt) || p2m_is_discard_write(p2mt) )
++ {
++ put_page(*page);
++ return NULL;
++ }
++
++ return __map_domain_page(*page);
++}
++
++static inline void unmap_dirty_bitmap(void *addr, struct page_info *page)
++{
++ if ( addr != NULL )
++ {
++ unmap_domain_page(addr);
++ put_page(page);
++ }
++}
++
+
+ /* Read a domain's log-dirty bitmap and stats. If the operation is a CLEAN,
+ * clear the bitmap and stats as well. */
+@@ -418,7 +463,11 @@ static int paging_log_dirty_op(struct domain *d,
+ mfn_t *l4 = NULL, *l3 = NULL, *l2 = NULL;
+ unsigned long *l1 = NULL;
+ int i4, i3, i2;
++ uint8_t *dirty_bitmap;
++ struct page_info *page;
++ unsigned long index_mapped;
+
++ again:
+ if ( !resuming )
+ {
+ /*
+@@ -439,6 +488,14 @@ static int paging_log_dirty_op(struct domain *d,
+ p2m_flush_hardware_cached_dirty(d);
+ }
+
++ index_mapped = resuming ? d->arch.paging.preempt.log_dirty.done : 0;
++ dirty_bitmap = map_dirty_bitmap(sc->dirty_bitmap, index_mapped, &page);
++ if ( dirty_bitmap == NULL )
++ {
++ domain_unpause(d);
++ return -EFAULT;
++ }
++
+ paging_lock(d);
+
+ if ( !d->arch.paging.preempt.dom )
+@@ -478,18 +535,18 @@ static int paging_log_dirty_op(struct domain *d,
+ l4 = paging_map_log_dirty_bitmap(d);
+ i4 = d->arch.paging.preempt.log_dirty.i4;
+ i3 = d->arch.paging.preempt.log_dirty.i3;
++ i2 = d->arch.paging.preempt.log_dirty.i2;
+ pages = d->arch.paging.preempt.log_dirty.done;
+
+ for ( ; (pages < sc->pages) && (i4 < LOGDIRTY_NODE_ENTRIES); i4++, i3 = 0 )
+ {
+ l3 = (l4 && mfn_valid(l4[i4])) ? map_domain_page(l4[i4]) : NULL;
+- for ( ; (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES); i3++ )
++ for ( ; (pages < sc->pages) && (i3 < LOGDIRTY_NODE_ENTRIES);
++ i3++, i2 = 0 )
+ {
+ l2 = ((l3 && mfn_valid(l3[i3])) ?
+ map_domain_page(l3[i3]) : NULL);
+- for ( i2 = 0;
+- (pages < sc->pages) && (i2 < LOGDIRTY_NODE_ENTRIES);
+- i2++ )
++ for ( ; (pages < sc->pages) && (i2 < LOGDIRTY_NODE_ENTRIES); i2++ )
+ {
+ unsigned int bytes = PAGE_SIZE;
+ l1 = ((l2 && mfn_valid(l2[i2])) ?
+@@ -498,15 +555,28 @@ static int paging_log_dirty_op(struct domain *d,
+ bytes = (unsigned int)((sc->pages - pages + 7) >> 3);
+ if ( likely(peek) )
+ {
+- if ( (l1 ? copy_to_guest_offset(sc->dirty_bitmap,
+- pages >> 3, (uint8_t *)l1,
+- bytes)
+- : clear_guest_offset(sc->dirty_bitmap,
+- pages >> 3, bytes)) != 0 )
++ if ( pages >> (3 + PAGE_SHIFT) !=
++ index_mapped >> (3 + PAGE_SHIFT) )
+ {
+- rv = -EFAULT;
+- goto out;
++ /* We need to map next page */
++ d->arch.paging.preempt.log_dirty.i4 = i4;
++ d->arch.paging.preempt.log_dirty.i3 = i3;
++ d->arch.paging.preempt.log_dirty.i2 = i2;
++ d->arch.paging.preempt.log_dirty.done = pages;
++ d->arch.paging.preempt.dom = current->domain;
++ d->arch.paging.preempt.op = sc->op;
++ resuming = 1;
++ paging_unlock(d);
++ unmap_dirty_bitmap(dirty_bitmap, page);
++ goto again;
+ }
++ ASSERT(((pages >> 3) % PAGE_SIZE) + bytes <= PAGE_SIZE);
++ if ( l1 )
++ memcpy(dirty_bitmap + ((pages >> 3) % PAGE_SIZE), l1,
++ bytes);
++ else
++ memset(dirty_bitmap + ((pages >> 3) % PAGE_SIZE), 0,
++ bytes);
+ }
+ pages += bytes << 3;
+ if ( l1 )
+@@ -524,6 +594,7 @@ static int paging_log_dirty_op(struct domain *d,
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4;
+ d->arch.paging.preempt.log_dirty.i3 = i3 + 1;
++ d->arch.paging.preempt.log_dirty.i2 = 0;
+ rv = -ERESTART;
+ break;
+ }
+@@ -536,6 +607,7 @@ static int paging_log_dirty_op(struct domain *d,
+ {
+ d->arch.paging.preempt.log_dirty.i4 = i4 + 1;
+ d->arch.paging.preempt.log_dirty.i3 = 0;
++ d->arch.paging.preempt.log_dirty.i2 = 0;
+ rv = -ERESTART;
+ }
+ if ( rv )
+@@ -565,6 +637,7 @@ static int paging_log_dirty_op(struct domain *d,
+ if ( rv )
+ {
+ /* Never leave the domain paused on real errors. */
++ unmap_dirty_bitmap(dirty_bitmap, page);
+ ASSERT(rv == -ERESTART);
+ return rv;
+ }
+@@ -577,12 +650,14 @@ static int paging_log_dirty_op(struct domain *d,
+ * paging modes (shadow or hap). Safe because the domain is paused. */
+ d->arch.paging.log_dirty.clean_dirty_bitmap(d);
+ }
++ unmap_dirty_bitmap(dirty_bitmap, page);
+ domain_unpause(d);
+ return rv;
+
+ out:
+ d->arch.paging.preempt.dom = NULL;
+ paging_unlock(d);
++ unmap_dirty_bitmap(dirty_bitmap, page);
+ domain_unpause(d);
+
+ if ( l1 )
+diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
+index 165e533..0dc1ed8 100644
+--- a/xen/include/asm-x86/domain.h
++++ b/xen/include/asm-x86/domain.h
+@@ -206,6 +206,7 @@ struct paging_domain {
+ unsigned long done:PADDR_BITS - PAGE_SHIFT;
+ unsigned long i4:PAGETABLE_ORDER;
+ unsigned long i3:PAGETABLE_ORDER;
++ unsigned long i2:PAGETABLE_ORDER;
+ } log_dirty;
+ };
+ } preempt;
+--
+2.7.4 (Apple Git-66)
+
Index: head/emulators/xen-kernel47/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
===================================================================
--- head/emulators/xen-kernel47/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
+++ head/emulators/xen-kernel47/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch
@@ -0,0 +1,232 @@
+From 39b704785a8d330c02e8e2d2368c80dbaf679bc0 Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Thu, 15 Jun 2017 12:05:14 +0100
+Subject: [PATCH 3/4] gnttab: Avoid potential double-put of maptrack entry
+
+Each grant mapping for a particular domain is tracked by an in-Xen
+"maptrack" entry. This entry is is referenced by a "handle", which is
+given to the guest when it calls gnttab_map_grant_ref().
+
+There are two types of mapping a particular handle can refer to:
+GNTMAP_host_map and GNTMAP_device_map. A given
+gnttab_unmap_grant_ref() call can remove either only one or both of
+these entries. When a particular handle has no entries left, it must
+be freed.
+
+gnttab_unmap_grant_ref() loops through its grant unmap request list
+twice. It first removes entries from any host pagetables and (if
+appropraite) iommus; then it does a single domain TLB flush; then it
+does the clean-up, including telling the granter that entries are no
+longer being used (if appropriate).
+
+At the moment, it's during the first pass that the maptrack flags are
+cleared, but the second pass that the maptrack entry is freed.
+
+Unfortunately this allows the following race, which results in a
+double-free:
+
+ A: (pass 1) clear host_map
+ B: (pass 1) clear device_map
+ A: (pass 2) See that maptrack entry has no mappings, free it
+ B: (pass 2) See that maptrack entry has no mappings, free it #
+
+Unfortunately, unlike the active entry pinning update, we can't simply
+move the maptrack flag changes to the second half, because the
+maptrack flags are used to determine if iommu entries need to be
+added: a domain's iommu must never have fewer permissions than the
+maptrack flags indicate, or a subsequent map_grant_ref() might fail to
+add the necessary iommu entries.
+
+Instead, free the maptrack entry in the first pass if there are no
+further mappings.
+
+This is part of XSA-218.
+
+Reported-by: Jan Beulich <jbeulich.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 79 +++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 54 insertions(+), 25 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index cfc483f..81a1a8b 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -98,8 +98,8 @@ struct gnttab_unmap_common {
+ /* Shared state beteen *_unmap and *_unmap_complete */
+ u16 flags;
+ unsigned long frame;
+- struct grant_mapping *map;
+ struct domain *rd;
++ grant_ref_t ref;
+ };
+
+ /* Number of unmap operations that are done between each tlb flush */
+@@ -1079,6 +1079,8 @@ __gnttab_unmap_common(
+ struct grant_table *lgt, *rgt;
+ struct active_grant_entry *act;
+ s16 rc = 0;
++ struct grant_mapping *map;
++ bool_t put_handle = 0;
+
+ ld = current->domain;
+ lgt = ld->grant_table;
+@@ -1092,11 +1094,11 @@ __gnttab_unmap_common(
+ return;
+ }
+
+- op->map = &maptrack_entry(lgt, op->handle);
++ map = &maptrack_entry(lgt, op->handle);
+
+ grant_read_lock(lgt);
+
+- if ( unlikely(!read_atomic(&op->map->flags)) )
++ if ( unlikely(!read_atomic(&map->flags)) )
+ {
+ grant_read_unlock(lgt);
+ gdprintk(XENLOG_INFO, "Zero flags for handle (%d).\n", op->handle);
+@@ -1104,7 +1106,7 @@ __gnttab_unmap_common(
+ return;
+ }
+
+- dom = op->map->domid;
++ dom = map->domid;
+ grant_read_unlock(lgt);
+
+ if ( unlikely((rd = rcu_lock_domain_by_id(dom)) == NULL) )
+@@ -1129,16 +1131,43 @@ __gnttab_unmap_common(
+
+ grant_read_lock(rgt);
+
+- op->flags = read_atomic(&op->map->flags);
+- if ( unlikely(!op->flags) || unlikely(op->map->domid != dom) )
++ op->rd = rd;
++ op->ref = map->ref;
++
++ /*
++ * We can't assume there was no racing unmap for this maptrack entry,
++ * and hence we can't assume map->ref is valid for rd. While the checks
++ * below (with the active entry lock held) will reject any such racing
++ * requests, we still need to make sure we don't attempt to acquire an
++ * invalid lock.
++ */
++ smp_rmb();
++ if ( unlikely(op->ref >= nr_grant_entries(rgt)) )
+ {
+- gdprintk(XENLOG_WARNING, "Unstable handle %u\n", op->handle);
++ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
+ rc = GNTST_bad_handle;
+- goto unmap_out;
++ goto unlock_out;
+ }
+
+- op->rd = rd;
+- act = active_entry_acquire(rgt, op->map->ref);
++ act = active_entry_acquire(rgt, op->ref);
++
++ /*
++ * Note that we (ab)use the active entry lock here to protect against
++ * multiple unmaps of the same mapping here. We don't want to hold lgt's
++ * lock, and we only hold rgt's lock for reading (but the latter wouldn't
++ * be the right one anyway). Hence the easiest is to rely on a lock we
++ * hold anyway; see docs/misc/grant-tables.txt's "Locking" section.
++ */
++
++ op->flags = read_atomic(&map->flags);
++ smp_rmb();
++ if ( unlikely(!op->flags) || unlikely(map->domid != dom) ||
++ unlikely(map->ref != op->ref) )
++ {
++ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
++ rc = GNTST_bad_handle;
++ goto act_release_out;
++ }
+
+ if ( op->frame == 0 )
+ {
+@@ -1151,7 +1180,7 @@ __gnttab_unmap_common(
+ "Bad frame number doesn't match gntref. (%lx != %lx)\n",
+ op->frame, act->frame);
+
+- op->map->flags &= ~GNTMAP_device_map;
++ map->flags &= ~GNTMAP_device_map;
+ }
+
+ if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
+@@ -1161,14 +1190,23 @@ __gnttab_unmap_common(
+ op->flags)) < 0 )
+ goto act_release_out;
+
+- op->map->flags &= ~GNTMAP_host_map;
++ map->flags &= ~GNTMAP_host_map;
++ }
++
++ if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
++ {
++ map->flags = 0;
++ put_handle = 1;
+ }
+
+ act_release_out:
+ active_entry_release(act);
+- unmap_out:
++ unlock_out:
+ grant_read_unlock(rgt);
+
++ if ( put_handle )
++ put_maptrack_handle(lgt, op->handle);
++
+ if ( rc == GNTST_okay && gnttab_need_iommu_mapping(ld) )
+ {
+ unsigned int kind;
+@@ -1205,7 +1243,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ grant_entry_header_t *sha;
+ struct page_info *pg;
+ uint16_t *status;
+- bool_t put_handle = 0;
+
+ if ( rd == NULL )
+ {
+@@ -1226,13 +1263,13 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ if ( rgt->gt_version == 0 )
+ goto unlock_out;
+
+- act = active_entry_acquire(rgt, op->map->ref);
+- sha = shared_entry_header(rgt, op->map->ref);
++ act = active_entry_acquire(rgt, op->ref);
++ sha = shared_entry_header(rgt, op->ref);
+
+ if ( rgt->gt_version == 1 )
+ status = &sha->flags;
+ else
+- status = &status_entry(rgt, op->map->ref);
++ status = &status_entry(rgt, op->ref);
+
+ if ( unlikely(op->frame != act->frame) )
+ {
+@@ -1289,9 +1326,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ act->pin -= GNTPIN_hstw_inc;
+ }
+
+- if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
+- put_handle = 1;
+-
+ if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
+ !(op->flags & GNTMAP_readonly) )
+ gnttab_clear_flag(_GTF_writing, status);
+@@ -1304,11 +1338,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ unlock_out:
+ grant_read_unlock(rgt);
+
+- if ( put_handle )
+- {
+- op->map->flags = 0;
+- put_maptrack_handle(ld->grant_table, op->handle);
+- }
+ rcu_unlock_domain(rd);
+ }
+
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
===================================================================
--- head/emulators/xen-kernel47/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
+++ head/emulators/xen-kernel47/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch
@@ -0,0 +1,186 @@
+From 5d491e3cf32ff03552db9d66e842964fec06dcd4 Mon Sep 17 00:00:00 2001
+From: George Dunlap <george.dunlap@citrix.com>
+Date: Fri, 2 Jun 2017 15:21:27 +0100
+Subject: [PATCH 3/4] gnttab: correct logic to get page references during map
+ requests
+
+The rules for reference counting are somewhat complicated:
+
+* Each of GNTTAB_host_map and GNTTAB_device_map need their own
+reference count
+
+* If the mapping is writeable:
+ - GNTTAB_host_map needs a type count under only some conditions
+ - GNTTAB_device_map always needs a type count
+
+If the mapping succeeds, we need to keep all of these; if the mapping
+fails, we need to release whatever references we have acquired so far.
+
+Additionally, the code that does a lot of this calculation "inherits"
+a reference as part of the process of finding out who the owner is.
+
+Finally, if the grant is mapped as writeable (without the
+GNTMAP_readonly flag), but the hypervisor cannot grab a
+PGT_writeable_page type, the entire operation should fail.
+
+Unfortunately, the current code has several logic holes:
+
+* If a grant is mapped only GNTTAB_device_map, and with a writeable
+ mapping, but in conditions where a *host* type count is not
+ necessary, the code will fail to grab the necessary type count.
+
+* If a grant is mapped both GNTTAB_device_map and GNTTAB_host_map,
+ with a writeable mapping, in conditions where the host type count is
+ not necessary, *and* where the page cannot be changed to type
+ PGT_writeable, the condition will not be detected.
+
+In both cases, this means that on success, the type count will be
+erroneously reduced when the grant is unmapped. In the second case,
+the type count will be erroneously reduced on the failure path as
+well. (In the first case the failure path logic has the same hole
+as the reference grabbing logic.)
+
+Additionally, the return value of get_page() is not checked; but this
+may fail even if the first get_page() succeeded due to a reference
+counting overflow.
+
+First of all, simplify the restoration logic by explicitly counting
+the reference and type references acquired.
+
+Consider each mapping type separately, explicitly marking the
+'incoming' reference as used so we know when we need to grab a second
+one.
+
+Finally, always check the return value of get_page[_type]() and go to
+the failure path if appropriate.
+
+This is part of XSA-224.
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 58 +++++++++++++++++++++++++++---------------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index 452538e..5e92e2c 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -758,12 +758,12 @@ __gnttab_map_grant_ref(
+ struct grant_table *lgt, *rgt;
+ struct vcpu *led;
+ int handle;
+- unsigned long frame = 0, nr_gets = 0;
++ unsigned long frame = 0;
+ struct page_info *pg = NULL;
+ int rc = GNTST_okay;
+ u32 old_pin;
+ u32 act_pin;
+- unsigned int cache_flags;
++ unsigned int cache_flags, refcnt = 0, typecnt = 0;
+ struct active_grant_entry *act = NULL;
+ struct grant_mapping *mt;
+ grant_entry_header_t *shah;
+@@ -889,11 +889,17 @@ __gnttab_map_grant_ref(
+ else
+ owner = page_get_owner(pg);
+
++ if ( owner )
++ refcnt++;
++
+ if ( !pg || (owner == dom_io) )
+ {
+ /* Only needed the reference to confirm dom_io ownership. */
+ if ( pg )
++ {
+ put_page(pg);
++ refcnt--;
++ }
+
+ if ( paging_mode_external(ld) )
+ {
+@@ -921,27 +927,38 @@ __gnttab_map_grant_ref(
+ }
+ else if ( owner == rd || owner == dom_cow )
+ {
+- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
++ if ( (op->flags & GNTMAP_device_map) && !(op->flags & GNTMAP_readonly) )
+ {
+ if ( (owner == dom_cow) ||
+ !get_page_type(pg, PGT_writable_page) )
+ goto could_not_pin;
++ typecnt++;
+ }
+
+- nr_gets++;
+ if ( op->flags & GNTMAP_host_map )
+ {
+- rc = create_grant_host_mapping(op->host_addr, frame, op->flags, 0);
+- if ( rc != GNTST_okay )
+- goto undo_out;
+-
++ /*
++ * Only need to grab another reference if device_map claimed
++ * the other one.
++ */
+ if ( op->flags & GNTMAP_device_map )
+ {
+- nr_gets++;
+- (void)get_page(pg, rd);
+- if ( !(op->flags & GNTMAP_readonly) )
+- get_page_type(pg, PGT_writable_page);
++ if ( !get_page(pg, rd) )
++ goto could_not_pin;
++ refcnt++;
++ }
++
++ if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
++ {
++ if ( (owner == dom_cow) ||
++ !get_page_type(pg, PGT_writable_page) )
++ goto could_not_pin;
++ typecnt++;
+ }
++
++ rc = create_grant_host_mapping(op->host_addr, frame, op->flags, 0);
++ if ( rc != GNTST_okay )
++ goto undo_out;
+ }
+ }
+ else
+@@ -950,8 +967,6 @@ __gnttab_map_grant_ref(
+ if ( !rd->is_dying )
+ gdprintk(XENLOG_WARNING, "Could not pin grant frame %lx\n",
+ frame);
+- if ( owner != NULL )
+- put_page(pg);
+ rc = GNTST_general_error;
+ goto undo_out;
+ }
+@@ -1014,18 +1029,11 @@ __gnttab_map_grant_ref(
+ return;
+
+ undo_out:
+- if ( nr_gets > 1 )
+- {
+- if ( !(op->flags & GNTMAP_readonly) )
+- put_page_type(pg);
+- put_page(pg);
+- }
+- if ( nr_gets > 0 )
+- {
+- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
+- put_page_type(pg);
++ while ( typecnt-- )
++ put_page_type(pg);
++
++ while ( refcnt-- )
+ put_page(pg);
+- }
+
+ grant_read_lock(rgt);
+
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0003-x86-MSI-disallow-redundant-enabling.patch
===================================================================
--- head/emulators/xen-kernel47/files/0003-x86-MSI-disallow-redundant-enabling.patch
+++ head/emulators/xen-kernel47/files/0003-x86-MSI-disallow-redundant-enabling.patch
@@ -0,0 +1,55 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/MSI: disallow redundant enabling
+
+At the moment, Xen attempts to allow redundant enabling of MSI by
+having pci_enable_msi() return 0, and point to the existing MSI
+descriptor, when the msi already exists.
+
+Unfortunately, if subsequent errors are encountered, the cleanup
+paths assume pci_enable_msi() had done full initialization, and
+hence undo everything that was assumed to be done by that
+function without also undoing other setup that would normally
+occur only after that function was called (in map_domain_pirq()
+itself).
+
+Rather than try to make the redundant enabling case work properly, just
+forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
+is already set up.
+
+This is part of XSA-237.
+
+Reported-by: HW42 <hw42@ipsumj.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/x86/msi.c
++++ b/xen/arch/x86/msi.c
+@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
+ old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
+ if ( old_desc )
+ {
+- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
++ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ msi->irq, msi->seg, msi->bus,
+ PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
+- *desc = old_desc;
+- return 0;
++ return -EEXIST;
+ }
+
+ old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
+@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
+ old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
+ if ( old_desc )
+ {
+- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
++ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ msi->irq, msi->seg, msi->bus,
+ PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
+- *desc = old_desc;
+- return 0;
++ return -EEXIST;
+ }
+
+ old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
Index: head/emulators/xen-kernel47/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
===================================================================
--- head/emulators/xen-kernel47/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
+++ head/emulators/xen-kernel47/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch
@@ -0,0 +1,319 @@
+From 3ad26b95cd9bacedad5ba503515cf6e618162be1 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Thu, 15 Jun 2017 16:25:27 +0100
+Subject: [PATCH 4/4] gnttab: __gnttab_unmap_common_complete() is
+ all-or-nothing
+
+All failures have to be detected in __gnttab_unmap_common(), the
+completion function must not skip part of its processing. In particular
+the GNTMAP_device_map related putting of page references and adjustment
+of pin count must not occur if __gnttab_unmap_common() signaled an
+error. Furthermore the function must not make adjustments to global
+state (here: clearing GNTTAB_device_map) before all possibly failing
+operations have been performed.
+
+There's one exception for IOMMU related failures: As IOMMU manipulation
+occurs after GNTMAP_*_map have been cleared already, the related page
+reference and pin count adjustments need to be done nevertheless. A
+fundamental requirement for the correctness of this is that
+iommu_{,un}map_page() crash any affected DomU in case of failure.
+
+The version check appears to be pointless (or could perhaps be a
+BUG_ON() or ASSERT()), but for the moment also move it.
+
+This is part of XSA-224.
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/common/grant_table.c | 108 ++++++++++++++++++--------------------
+ xen/include/asm-arm/grant_table.h | 2 +-
+ xen/include/asm-x86/grant_table.h | 5 +-
+ 3 files changed, 55 insertions(+), 60 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index 5e92e2c..025aad0 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -96,7 +96,7 @@ struct gnttab_unmap_common {
+ int16_t status;
+
+ /* Shared state beteen *_unmap and *_unmap_complete */
+- u16 flags;
++ u16 done;
+ unsigned long frame;
+ struct domain *rd;
+ grant_ref_t ref;
+@@ -948,7 +948,8 @@ __gnttab_map_grant_ref(
+ refcnt++;
+ }
+
+- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
++ if ( gnttab_host_mapping_get_page_type(op->flags & GNTMAP_readonly,
++ ld, rd) )
+ {
+ if ( (owner == dom_cow) ||
+ !get_page_type(pg, PGT_writable_page) )
+@@ -1095,6 +1096,7 @@ __gnttab_unmap_common(
+ struct active_grant_entry *act;
+ s16 rc = 0;
+ struct grant_mapping *map;
++ unsigned int flags;
+ bool_t put_handle = 0;
+
+ ld = current->domain;
+@@ -1145,6 +1147,20 @@ __gnttab_unmap_common(
+
+ grant_read_lock(rgt);
+
++ if ( rgt->gt_version == 0 )
++ {
++ /*
++ * This ought to be impossible, as such a mapping should not have
++ * been established (see the nr_grant_entries(rgt) bounds check in
++ * __gnttab_map_grant_ref()). Doing this check only in
++ * __gnttab_unmap_common_complete() - as it used to be done - would,
++ * however, be too late.
++ */
++ rc = GNTST_bad_gntref;
++ flags = 0;
++ goto unlock_out;
++ }
++
+ op->rd = rd;
+ op->ref = map->ref;
+
+@@ -1160,6 +1176,7 @@ __gnttab_unmap_common(
+ {
+ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
+ rc = GNTST_bad_handle;
++ flags = 0;
+ goto unlock_out;
+ }
+
+@@ -1173,9 +1190,9 @@ __gnttab_unmap_common(
+ * hold anyway; see docs/misc/grant-tables.txt's "Locking" section.
+ */
+
+- op->flags = read_atomic(&map->flags);
++ flags = read_atomic(&map->flags);
+ smp_rmb();
+- if ( unlikely(!op->flags) || unlikely(map->domid != dom) ||
++ if ( unlikely(!flags) || unlikely(map->domid != dom) ||
+ unlikely(map->ref != op->ref) )
+ {
+ gdprintk(XENLOG_WARNING, "Unstable handle %#x\n", op->handle);
+@@ -1185,24 +1202,27 @@ __gnttab_unmap_common(
+
+ op->frame = act->frame;
+
+- if ( op->dev_bus_addr )
+- {
+- if ( unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
+- PIN_FAIL(act_release_out, GNTST_general_error,
+- "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
+- op->dev_bus_addr, pfn_to_paddr(act->frame));
+-
+- map->flags &= ~GNTMAP_device_map;
+- }
++ if ( op->dev_bus_addr &&
++ unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
++ PIN_FAIL(act_release_out, GNTST_general_error,
++ "Bus address doesn't match gntref (%"PRIx64" != %"PRIpaddr")\n",
++ op->dev_bus_addr, pfn_to_paddr(act->frame));
+
+- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
++ if ( op->host_addr && (flags & GNTMAP_host_map) )
+ {
+ if ( (rc = replace_grant_host_mapping(op->host_addr,
+ op->frame, op->new_addr,
+- op->flags)) < 0 )
++ flags)) < 0 )
+ goto act_release_out;
+
+ map->flags &= ~GNTMAP_host_map;
++ op->done |= GNTMAP_host_map | (flags & GNTMAP_readonly);
++ }
++
++ if ( op->dev_bus_addr && (flags & GNTMAP_device_map) )
++ {
++ map->flags &= ~GNTMAP_device_map;
++ op->done |= GNTMAP_device_map | (flags & GNTMAP_readonly);
+ }
+
+ if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
+@@ -1239,7 +1259,7 @@ __gnttab_unmap_common(
+ }
+
+ /* If just unmapped a writable mapping, mark as dirtied */
+- if ( rc == GNTST_okay && !(op->flags & GNTMAP_readonly) )
++ if ( rc == GNTST_okay && !(flags & GNTMAP_readonly) )
+ gnttab_mark_dirty(rd, op->frame);
+
+ op->status = rc;
+@@ -1256,13 +1276,9 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ struct page_info *pg;
+ uint16_t *status;
+
+- if ( rd == NULL )
++ if ( !op->done )
+ {
+- /*
+- * Suggests that __gntab_unmap_common failed in
+- * rcu_lock_domain_by_id() or earlier, and so we have nothing
+- * to complete
+- */
++ /* __gntab_unmap_common() didn't do anything - nothing to complete. */
+ return;
+ }
+
+@@ -1272,8 +1288,6 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ rgt = rd->grant_table;
+
+ grant_read_lock(rgt);
+- if ( rgt->gt_version == 0 )
+- goto unlock_out;
+
+ act = active_entry_acquire(rgt, op->ref);
+ sha = shared_entry_header(rgt, op->ref);
+@@ -1283,72 +1297,50 @@ __gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+ else
+ status = &status_entry(rgt, op->ref);
+
+- if ( op->dev_bus_addr &&
+- unlikely(op->dev_bus_addr != pfn_to_paddr(act->frame)) )
+- {
+- /*
+- * Suggests that __gntab_unmap_common failed early and so
+- * nothing further to do
+- */
+- goto act_release_out;
+- }
+-
+ pg = mfn_to_page(op->frame);
+
+- if ( op->dev_bus_addr && (op->flags & GNTMAP_device_map) )
++ if ( op->done & GNTMAP_device_map )
+ {
+ if ( !is_iomem_page(act->frame) )
+ {
+- if ( op->flags & GNTMAP_readonly )
++ if ( op->done & GNTMAP_readonly )
+ put_page(pg);
+ else
+ put_page_and_type(pg);
+ }
+
+ ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
+- if ( op->flags & GNTMAP_readonly )
++ if ( op->done & GNTMAP_readonly )
+ act->pin -= GNTPIN_devr_inc;
+ else
+ act->pin -= GNTPIN_devw_inc;
+ }
+
+- if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
++ if ( op->done & GNTMAP_host_map )
+ {
+- if ( op->status != 0 )
++ if ( !is_iomem_page(op->frame) )
+ {
+- /*
+- * Suggests that __gntab_unmap_common failed in
+- * replace_grant_host_mapping() or IOMMU handling, so nothing
+- * further to do (short of re-establishing the mapping in the
+- * latter case).
+- */
+- goto act_release_out;
+- }
+-
+- if ( !is_iomem_page(op->frame) )
+- {
+- if ( gnttab_host_mapping_get_page_type(op, ld, rd) )
++ if ( gnttab_host_mapping_get_page_type(op->done & GNTMAP_readonly,
++ ld, rd) )
+ put_page_type(pg);
+ put_page(pg);
+ }
+
+ ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
+- if ( op->flags & GNTMAP_readonly )
++ if ( op->done & GNTMAP_readonly )
+ act->pin -= GNTPIN_hstr_inc;
+ else
+ act->pin -= GNTPIN_hstw_inc;
+ }
+
+ if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
+- !(op->flags & GNTMAP_readonly) )
++ !(op->done & GNTMAP_readonly) )
+ gnttab_clear_flag(_GTF_writing, status);
+
+ if ( act->pin == 0 )
+ gnttab_clear_flag(_GTF_reading, status);
+
+- act_release_out:
+ active_entry_release(act);
+- unlock_out:
+ grant_read_unlock(rgt);
+
+ rcu_unlock_domain(rd);
+@@ -1364,6 +1356,7 @@ __gnttab_unmap_grant_ref(
+ common->handle = op->handle;
+
+ /* Intialise these in case common contains old state */
++ common->done = 0;
+ common->new_addr = 0;
+ common->rd = NULL;
+ common->frame = 0;
+@@ -1429,6 +1422,7 @@ __gnttab_unmap_and_replace(
+ common->handle = op->handle;
+
+ /* Intialise these in case common contains old state */
++ common->done = 0;
+ common->dev_bus_addr = 0;
+ common->rd = NULL;
+ common->frame = 0;
+@@ -3389,7 +3383,9 @@ gnttab_release_mappings(
+ if ( gnttab_release_host_mappings(d) &&
+ !is_iomem_page(act->frame) )
+ {
+- if ( gnttab_host_mapping_get_page_type(map, d, rd) )
++ if ( gnttab_host_mapping_get_page_type((map->flags &
++ GNTMAP_readonly),
++ d, rd) )
+ put_page_type(pg);
+ put_page(pg);
+ }
+diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
+index 5e076cc..d76c7c7 100644
+--- a/xen/include/asm-arm/grant_table.h
++++ b/xen/include/asm-arm/grant_table.h
+@@ -9,7 +9,7 @@ void gnttab_clear_flag(unsigned long nr, uint16_t *addr);
+ int create_grant_host_mapping(unsigned long gpaddr,
+ unsigned long mfn, unsigned int flags, unsigned int
+ cache_flags);
+-#define gnttab_host_mapping_get_page_type(op, d, rd) (0)
++#define gnttab_host_mapping_get_page_type(ro, ld, rd) (0)
+ int replace_grant_host_mapping(unsigned long gpaddr, unsigned long mfn,
+ unsigned long new_gpaddr, unsigned int flags);
+ void gnttab_mark_dirty(struct domain *d, unsigned long l);
+diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
+index 8c9bbcf..9ca631c 100644
+--- a/xen/include/asm-x86/grant_table.h
++++ b/xen/include/asm-x86/grant_table.h
+@@ -58,9 +58,8 @@ static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
+ }
+
+ /* Foreign mappings of HHVM-guest pages do not modify the type count. */
+-#define gnttab_host_mapping_get_page_type(op, ld, rd) \
+- (!((op)->flags & GNTMAP_readonly) && \
+- (((ld) == (rd)) || !paging_mode_external(rd)))
++#define gnttab_host_mapping_get_page_type(ro, ld, rd) \
++ (!(ro) && (((ld) == (rd)) || !paging_mode_external(rd)))
+
+ /* Done implicitly when page tables are destroyed. */
+ #define gnttab_release_host_mappings(domain) ( paging_mode_external(domain) )
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0004-gnttab-correct-maptrack-table-accesses.patch
===================================================================
--- head/emulators/xen-kernel47/files/0004-gnttab-correct-maptrack-table-accesses.patch
+++ head/emulators/xen-kernel47/files/0004-gnttab-correct-maptrack-table-accesses.patch
@@ -0,0 +1,84 @@
+From bb765f7863e5d19eebcfb29c117e2909bce241e7 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Thu, 15 Jun 2017 12:05:29 +0100
+Subject: [PATCH 4/4] gnttab: correct maptrack table accesses
+
+In order to observe a consistent (limit,pointer-table) pair, the reader
+needs to either hold the maptrack lock (in line with documentation) or
+both sides need to order their accesses suitably (the writer side
+barrier was removed by commit dff515dfea ["gnttab: use per-VCPU
+maptrack free lists"], and a read side barrier has never been there).
+
+Make the writer publish a new table page before limit (for bounds
+checks to work), and new list head last (for racing maptrack_entry()
+invocations to work). At the same time add read barriers to lockless
+readers.
+
+Additionally get_maptrack_handle() must not assume ->maptrack_head to
+not change behind its back: Another handle may be put (updating only
+->maptrack_tail) and then got or stolen (updating ->maptrack_head).
+
+This is part of XSA-218.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+---
+ xen/common/grant_table.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index 81a1a8b..c4d73af 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -395,7 +395,7 @@ get_maptrack_handle(
+ struct grant_table *lgt)
+ {
+ struct vcpu *curr = current;
+- int i;
++ unsigned int i, head;
+ grant_handle_t handle;
+ struct grant_mapping *new_mt;
+
+@@ -451,17 +451,20 @@ get_maptrack_handle(
+ new_mt[i].ref = handle + i + 1;
+ new_mt[i].vcpu = curr->vcpu_id;
+ }
+- new_mt[i - 1].ref = curr->maptrack_head;
+
+ /* Set tail directly if this is the first page for this VCPU. */
+ if ( curr->maptrack_tail == MAPTRACK_TAIL )
+ curr->maptrack_tail = handle + MAPTRACK_PER_PAGE - 1;
+
+- write_atomic(&curr->maptrack_head, handle + 1);
+-
+ lgt->maptrack[nr_maptrack_frames(lgt)] = new_mt;
++ smp_wmb();
+ lgt->maptrack_limit += MAPTRACK_PER_PAGE;
+
++ do {
++ new_mt[i - 1].ref = read_atomic(&curr->maptrack_head);
++ head = cmpxchg(&curr->maptrack_head, new_mt[i - 1].ref, handle + 1);
++ } while ( head != new_mt[i - 1].ref );
++
+ spin_unlock(&lgt->maptrack_lock);
+
+ return handle;
+@@ -727,6 +730,7 @@ static unsigned int mapkind(
+ for ( handle = 0; !(kind & MAPKIND_WRITE) &&
+ handle < lgt->maptrack_limit; handle++ )
+ {
++ smp_rmb();
+ map = &maptrack_entry(lgt, handle);
+ if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) ||
+ map->domid != rd->domain_id )
+@@ -1094,6 +1098,7 @@ __gnttab_unmap_common(
+ return;
+ }
+
++ smp_rmb();
+ map = &maptrack_entry(lgt, op->handle);
+
+ grant_read_lock(lgt);
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
===================================================================
--- head/emulators/xen-kernel47/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
+++ head/emulators/xen-kernel47/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
@@ -0,0 +1,124 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
+
+Mappings that had been set up before should not be torn down when
+handling unrelated errors.
+
+This is part of XSA-237.
+
+Reported-by: HW42 <hw42@ipsumj.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/x86/irq.c
++++ b/xen/arch/x86/irq.c
+@@ -1252,7 +1252,8 @@ static int prepare_domain_irq_pirq(struc
+ return -ENOMEM;
+ }
+ *pinfo = info;
+- return 0;
++
++ return !!err;
+ }
+
+ static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
+@@ -1295,7 +1296,10 @@ int init_domain_irq_mapping(struct domai
+ continue;
+ err = prepare_domain_irq_pirq(d, i, i, &info);
+ if ( err )
++ {
++ ASSERT(err < 0);
+ break;
++ }
+ set_domain_irq_pirq(d, i, info);
+ }
+
+@@ -1903,6 +1907,7 @@ int map_domain_pirq(
+ struct pirq *info;
+ struct irq_desc *desc;
+ unsigned long flags;
++ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
+
+ ASSERT(spin_is_locked(&d->event_lock));
+
+@@ -1946,8 +1951,10 @@ int map_domain_pirq(
+ }
+
+ ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
+- if ( ret )
++ if ( ret < 0 )
+ goto revoke;
++ if ( !ret )
++ __set_bit(0, prepared);
+
+ desc = irq_to_desc(irq);
+
+@@ -2019,8 +2026,10 @@ int map_domain_pirq(
+ irq = create_irq(NUMA_NO_NODE);
+ ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
+ : irq;
+- if ( ret )
++ if ( ret < 0 )
+ break;
++ if ( !ret )
++ __set_bit(nr, prepared);
+ msi_desc[nr].irq = irq;
+
+ if ( irq_permit_access(d, irq) != 0 )
+@@ -2053,15 +2062,15 @@ int map_domain_pirq(
+ desc->msi_desc = NULL;
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+- while ( nr-- )
++ while ( nr )
+ {
+ if ( irq >= 0 && irq_deny_access(d, irq) )
+ printk(XENLOG_G_ERR
+ "dom%d: could not revoke access to IRQ%d (pirq %d)\n",
+ d->domain_id, irq, pirq);
+- if ( info )
++ if ( info && test_bit(nr, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
+- info = pirq_info(d, pirq + nr);
++ info = pirq_info(d, pirq + --nr);
+ irq = info->arch.irq;
+ }
+ msi_desc->irq = -1;
+@@ -2077,12 +2086,14 @@ int map_domain_pirq(
+ spin_lock_irqsave(&desc->lock, flags);
+ set_domain_irq_pirq(d, irq, info);
+ spin_unlock_irqrestore(&desc->lock, flags);
++ ret = 0;
+ }
+
+ done:
+ if ( ret )
+ {
+- cleanup_domain_irq_pirq(d, irq, info);
++ if ( test_bit(0, prepared) )
++ cleanup_domain_irq_pirq(d, irq, info);
+ revoke:
+ if ( irq_deny_access(d, irq) )
+ printk(XENLOG_G_ERR
+--- a/xen/arch/x86/physdev.c
++++ b/xen/arch/x86/physdev.c
+@@ -185,7 +185,7 @@ int physdev_map_pirq(domid_t domid, int
+ }
+ else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
+ {
+- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
++ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
+ ret = -EDOM;
+ else if ( msi->entry_nr != 1 && !iommu_intremap )
+ ret = -EOPNOTSUPP;
+--- a/xen/include/asm-x86/msi.h
++++ b/xen/include/asm-x86/msi.h
+@@ -55,6 +55,8 @@
+ /* MAX fixed pages reserved for mapping MSIX tables. */
+ #define FIX_MSIX_MAX_PAGES 512
+
++#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
++
+ struct msi_info {
+ u16 seg;
+ u8 bus;
Index: head/emulators/xen-kernel47/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
===================================================================
--- head/emulators/xen-kernel47/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
+++ head/emulators/xen-kernel47/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
@@ -0,0 +1,37 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
+
+The caller and the FLASK implementation of xsm_unmap_domain_irq()
+disagreed about what the "data" argument points to in the MSI case:
+Change both sides to pass/take a PCI device.
+
+This is part of XSA-237.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/irq.c
++++ b/xen/arch/x86/irq.c
+@@ -2144,7 +2144,8 @@ int unmap_domain_pirq(struct domain *d,
+ nr = msi_desc->msi.nvec;
+ }
+
+- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
++ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
++ msi_desc ? msi_desc->dev : NULL);
+ if ( ret )
+ goto done;
+
+--- a/xen/xsm/flask/hooks.c
++++ b/xen/xsm/flask/hooks.c
+@@ -915,8 +915,8 @@ static int flask_unmap_domain_msi (struc
+ u32 *sid, struct avc_audit_data *ad)
+ {
+ #ifdef CONFIG_HAS_PCI
+- struct msi_info *msi = data;
+- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
++ const struct pci_dev *pdev = data;
++ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
+
+ AVC_AUDIT_DATA_INIT(ad, DEV);
+ ad->device = machine_bdf;
Index: head/emulators/xen-kernel47/files/kconf_arch.patch
===================================================================
--- head/emulators/xen-kernel47/files/kconf_arch.patch
+++ head/emulators/xen-kernel47/files/kconf_arch.patch
@@ -0,0 +1,33 @@
+diff --git a/xen/Makefile b/xen/Makefile
+index 0d5f240..f232d01 100644
+--- a/xen/Makefile
++++ b/xen/Makefile
+@@ -21,8 +21,8 @@ MAKEFLAGS += -rR
+
+ EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi
+
+-ARCH=$(XEN_TARGET_ARCH)
+-SRCARCH=$(shell echo $(ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
++KCONF_ARCH=$(XEN_TARGET_ARCH)
++KCONF_SRCARCH=$(shell echo $(KCONF_ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
+
+ # Don't break if the build process wasn't called from the top level
+ # we need XEN_TARGET_ARCH to generate the proper config
+@@ -246,14 +246,14 @@ kconfig := silentoldconfig oldconfig config menuconfig defconfig \
+ randconfig
+ .PHONY: $(kconfig)
+ $(kconfig):
+- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" $@
++ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" $@
+
+ include/config/%.conf: include/config/auto.conf.cmd $(KCONFIG_CONFIG)
+- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" silentoldconfig
++ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" silentoldconfig
+
+ # Allow people to just run `make` as before and not force them to configure
+ $(KCONFIG_CONFIG):
+- $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" defconfig
++ $(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(KCONF_ARCH) SRCARCH=$(KCONF_SRCARCH) HOSTCC="$(HOSTCC)" HOSTCXX="$(HOSTCXX)" defconfig
+
+ # Break the dependency chain for the first run
+ include/config/auto.conf.cmd: ;
Index: head/emulators/xen-kernel47/files/xen.4th
===================================================================
--- head/emulators/xen-kernel47/files/xen.4th
+++ head/emulators/xen-kernel47/files/xen.4th
@@ -0,0 +1,99 @@
+\ Copyright (c) 2015 Devin Teske <dteske@FreeBSD.org>
+\ All rights reserved.
+\
+\ Redistribution and use in source and binary forms, with or without
+\ modification, are permitted provided that the following conditions
+\ are met:
+\ 1. Redistributions of source code must retain the above copyright
+\ notice, this list of conditions and the following disclaimer.
+\ 2. Redistributions in binary form must reproduce the above copyright
+\ notice, this list of conditions and the following disclaimer in the
+\ documentation and/or other materials provided with the distribution.
+\
+\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+\ SUCH DAMAGE.
+\
+\ $FreeBSD$
+
+create xenkerndefault 64 allot
+0 xenkerndefault c!
+
+also menu-command-helpers
+also menu-namespace
+
+: init_xen_active ( N -- N )
+ s" [X]en Kernel.. off" 2 pick menu_caption[x] setenv
+ s" [X]en Kernel.. On" 2 pick toggled_text[x] setenv
+ s" toggle_xen" 2 pick menu_command[x] setenv
+ s" 120" 2 pick menu_keycode[x] setenv
+ s" ^[1mX^[men Kernel.. ^[34;1mOff^[m" 2 pick ansi_caption[x] setenv
+ s" ^[1mX^[men Kernel.. ^[32;7mOn^[m" 2 pick toggled_ansi[x] setenv
+;
+
+: init_xen_inactive ( N -- N )
+ s" Xen Kernel.. N/A" 2dup
+ 4 pick menu_caption[x] setenv
+ 2 pick ansi_caption[x] setenv
+ s" true" 2 pick menu_command[x] setenv
+;
+
+: init_xen ( -- )
+ s" optionsmenu_options" getenv 0> if
+ c@ dup [char] 0 > over [char] 9 < and false = if
+ drop [char] 0
+ then
+ 1+
+ else
+ [char] 1
+ then
+ begin
+ dup [char] 8 > if
+ false ( break )
+ else
+ dup s" optionsmenu_caption[x]" 20 +c! getenv -1 = if
+ false ( break )
+ else
+ drop true
+ then
+ then
+ while
+ 1+
+ repeat
+
+ s" xen_kernel" getenv dup -1 <> over 0> and if
+ xenkerndefault 1+ 0 2swap strcat swap 1- c!
+ init_xen_active ( n -- n )
+ toggle_menuitem ( n -- n )
+ else
+ drop
+ xenkerndefault c@ 0<> if
+ init_xen_active ( n -- n )
+ else
+ init_xen_inactive ( n -- n )
+ then
+ then
+;
+
+: toggle_xen ( N -- N TRUE )
+ toggle_menuitem ( n -- n )
+ menu-redraw
+
+ dup toggle_stateN @ 0= if
+ s" xen_kernel" unsetenv
+ else
+ xenkerndefault count s" xen_kernel" setenv
+ then
+
+ TRUE \ loop menu again
+;
+
+set optionsmenu_init="$optionsmenu_init init_xen"
Index: head/emulators/xen-kernel47/files/xsa212.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa212.patch
+++ head/emulators/xen-kernel47/files/xsa212.patch
@@ -0,0 +1,87 @@
+memory: properly check guest memory ranges in XENMEM_exchange handling
+
+The use of guest_handle_okay() here (as introduced by the XSA-29 fix)
+is insufficient here, guest_handle_subrange_okay() needs to be used
+instead.
+
+Note that the uses are okay in
+- XENMEM_add_to_physmap_batch handling due to the size field being only
+ 16 bits wide,
+- livepatch_list() due to the limit of 1024 enforced on the
+ number-of-entries input (leaving aside the fact that this can be
+ called by a privileged domain only anyway),
+- compat mode handling due to counts there being limited to 32 bits,
+- everywhere else due to guest arrays being accessed sequentially from
+ index zero.
+
+This is XSA-212.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -436,8 +436,8 @@ static long memory_exchange(XEN_GUEST_HA
+ goto fail_early;
+ }
+
+- if ( !guest_handle_okay(exch.in.extent_start, exch.in.nr_extents) ||
+- !guest_handle_okay(exch.out.extent_start, exch.out.nr_extents) )
++ if ( !guest_handle_subrange_okay(exch.in.extent_start, exch.nr_exchanged,
++ exch.in.nr_extents - 1) )
+ {
+ rc = -EFAULT;
+ goto fail_early;
+@@ -447,11 +447,27 @@ static long memory_exchange(XEN_GUEST_HA
+ {
+ in_chunk_order = exch.out.extent_order - exch.in.extent_order;
+ out_chunk_order = 0;
++
++ if ( !guest_handle_subrange_okay(exch.out.extent_start,
++ exch.nr_exchanged >> in_chunk_order,
++ exch.out.nr_extents - 1) )
++ {
++ rc = -EFAULT;
++ goto fail_early;
++ }
+ }
+ else
+ {
+ in_chunk_order = 0;
+ out_chunk_order = exch.in.extent_order - exch.out.extent_order;
++
++ if ( !guest_handle_subrange_okay(exch.out.extent_start,
++ exch.nr_exchanged << out_chunk_order,
++ exch.out.nr_extents - 1) )
++ {
++ rc = -EFAULT;
++ goto fail_early;
++ }
+ }
+
+ d = rcu_lock_domain_by_any_id(exch.in.domid);
+--- a/xen/include/asm-x86/x86_64/uaccess.h
++++ b/xen/include/asm-x86/x86_64/uaccess.h
+@@ -29,8 +29,9 @@ extern void *xlat_malloc(unsigned long *
+ /*
+ * Valid if in +ve half of 48-bit address space, or above Xen-reserved area.
+ * This is also valid for range checks (addr, addr+size). As long as the
+- * start address is outside the Xen-reserved area then we will access a
+- * non-canonical address (and thus fault) before ever reaching VIRT_START.
++ * start address is outside the Xen-reserved area, sequential accesses
++ * (starting at addr) will hit a non-canonical address (and thus fault)
++ * before ever reaching VIRT_START.
+ */
+ #define __addr_ok(addr) \
+ (((unsigned long)(addr) < (1UL<<47)) || \
+@@ -40,7 +41,8 @@ extern void *xlat_malloc(unsigned long *
+ (__addr_ok(addr) || is_compat_arg_xlat_range(addr, size))
+
+ #define array_access_ok(addr, count, size) \
+- (access_ok(addr, (count)*(size)))
++ (likely(((count) ?: 0UL) < (~0UL / (size))) && \
++ access_ok(addr, (count) * (size)))
+
+ #define __compat_addr_ok(d, addr) \
+ ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(d))
Index: head/emulators/xen-kernel47/files/xsa213-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa213-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa213-4.7.patch
@@ -0,0 +1,173 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: multicall: deal with early exit conditions
+
+In particular changes to guest privilege level require the multicall
+sequence to be aborted, as hypercalls are permitted from kernel mode
+only. While likely not very useful in a multicall, also properly handle
+the return value in the HYPERVISOR_iret case (which should be the guest
+specified value).
+
+This is XSA-213.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Acked-by: Julien Grall <julien.grall@arm.com>
+
+--- a/xen/arch/arm/traps.c
++++ b/xen/arch/arm/traps.c
+@@ -1529,30 +1529,33 @@ static bool_t check_multicall_32bit_clea
+ return true;
+ }
+
+-void do_multicall_call(struct multicall_entry *multi)
++enum mc_disposition do_multicall_call(struct multicall_entry *multi)
+ {
+ arm_hypercall_fn_t call = NULL;
+
+ if ( multi->op >= ARRAY_SIZE(arm_hypercall_table) )
+ {
+ multi->result = -ENOSYS;
+- return;
++ return mc_continue;
+ }
+
+ call = arm_hypercall_table[multi->op].fn;
+ if ( call == NULL )
+ {
+ multi->result = -ENOSYS;
+- return;
++ return mc_continue;
+ }
+
+ if ( is_32bit_domain(current->domain) &&
+ !check_multicall_32bit_clean(multi) )
+- return;
++ return mc_continue;
+
+ multi->result = call(multi->args[0], multi->args[1],
+ multi->args[2], multi->args[3],
+ multi->args[4]);
++
++ return likely(!psr_mode_is_user(guest_cpu_user_regs()))
++ ? mc_continue : mc_preempt;
+ }
+
+ /*
+--- a/xen/common/multicall.c
++++ b/xen/common/multicall.c
+@@ -40,6 +40,7 @@ do_multicall(
+ struct mc_state *mcs = &current->mc_state;
+ uint32_t i;
+ int rc = 0;
++ enum mc_disposition disp = mc_continue;
+
+ if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
+ {
+@@ -50,7 +51,7 @@ do_multicall(
+ if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
+ rc = -EFAULT;
+
+- for ( i = 0; !rc && i < nr_calls; i++ )
++ for ( i = 0; !rc && disp == mc_continue && i < nr_calls; i++ )
+ {
+ if ( i && hypercall_preempt_check() )
+ goto preempted;
+@@ -63,7 +64,7 @@ do_multicall(
+
+ trace_multicall_call(&mcs->call);
+
+- do_multicall_call(&mcs->call);
++ disp = do_multicall_call(&mcs->call);
+
+ #ifndef NDEBUG
+ {
+@@ -77,7 +78,14 @@ do_multicall(
+ }
+ #endif
+
+- if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
++ if ( unlikely(disp == mc_exit) )
++ {
++ if ( __copy_field_to_guest(call_list, &mcs->call, result) )
++ /* nothing, best effort only */;
++ rc = mcs->call.result;
++ }
++ else if ( unlikely(__copy_field_to_guest(call_list, &mcs->call,
++ result)) )
+ rc = -EFAULT;
+ else if ( mcs->flags & MCSF_call_preempted )
+ {
+@@ -93,6 +101,9 @@ do_multicall(
+ guest_handle_add_offset(call_list, 1);
+ }
+
++ if ( unlikely(disp == mc_preempt) && i < nr_calls )
++ goto preempted;
++
+ perfc_incr(calls_to_multicall);
+ perfc_add(calls_from_multicall, i);
+ mcs->flags = 0;
+--- a/xen/include/asm-arm/multicall.h
++++ b/xen/include/asm-arm/multicall.h
+@@ -1,7 +1,11 @@
+ #ifndef __ASM_ARM_MULTICALL_H__
+ #define __ASM_ARM_MULTICALL_H__
+
+-extern void do_multicall_call(struct multicall_entry *call);
++extern enum mc_disposition {
++ mc_continue,
++ mc_exit,
++ mc_preempt,
++} do_multicall_call(struct multicall_entry *call);
+
+ #endif /* __ASM_ARM_MULTICALL_H__ */
+ /*
+--- a/xen/include/asm-x86/multicall.h
++++ b/xen/include/asm-x86/multicall.h
+@@ -7,8 +7,21 @@
+
+ #include <xen/errno.h>
+
++enum mc_disposition {
++ mc_continue,
++ mc_exit,
++ mc_preempt,
++};
++
++#define multicall_ret(call) \
++ (unlikely((call)->op == __HYPERVISOR_iret) \
++ ? mc_exit \
++ : likely(guest_kernel_mode(current, \
++ guest_cpu_user_regs())) \
++ ? mc_continue : mc_preempt)
++
+ #define do_multicall_call(_call) \
+- do { \
++ ({ \
+ __asm__ __volatile__ ( \
+ " movq %c1(%0),%%rax; " \
+ " leaq hypercall_table(%%rip),%%rdi; " \
+@@ -37,9 +50,11 @@
+ /* all the caller-saves registers */ \
+ : "rax", "rcx", "rdx", "rsi", "rdi", \
+ "r8", "r9", "r10", "r11" ); \
+- } while ( 0 )
++ multicall_ret(_call); \
++ })
+
+ #define compat_multicall_call(_call) \
++ ({ \
+ __asm__ __volatile__ ( \
+ " movl %c1(%0),%%eax; " \
+ " leaq compat_hypercall_table(%%rip),%%rdi; "\
+@@ -67,6 +82,8 @@
+ "i" (-ENOSYS) \
+ /* all the caller-saves registers */ \
+ : "rax", "rcx", "rdx", "rsi", "rdi", \
+- "r8", "r9", "r10", "r11" ) \
++ "r8", "r9", "r10", "r11" ); \
++ multicall_ret(_call); \
++ })
+
+ #endif /* __ASM_X86_MULTICALL_H__ */
Index: head/emulators/xen-kernel47/files/xsa214.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa214.patch
+++ head/emulators/xen-kernel47/files/xsa214.patch
@@ -0,0 +1,41 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: discard type information when stealing pages
+
+While a page having just a single general reference left necessarily
+has a zero type reference count too, its type may still be valid (and
+in validated state; at present this is only possible and relevant for
+PGT_seg_desc_page, as page tables have their type forcibly zapped when
+their type reference count drops to zero, and
+PGT_{writable,shared}_page pages don't require any validation). In
+such a case when the page is being re-used with the same type again,
+validation is being skipped. As validation criteria differ between
+32- and 64-bit guests, pages to be transferred between guests need to
+have their validation indicator zapped (and with it we zap all other
+type information at once).
+
+This is XSA-214.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4466,6 +4466,17 @@ int steal_page(
+ y = cmpxchg(&page->count_info, x, x & ~PGC_count_mask);
+ } while ( y != x );
+
++ /*
++ * With the sole reference dropped temporarily, no-one can update type
++ * information. Type count also needs to be zero in this case, but e.g.
++ * PGT_seg_desc_page may still have PGT_validated set, which we need to
++ * clear before transferring ownership (as validation criteria vary
++ * depending on domain type).
++ */
++ BUG_ON(page->u.inuse.type_info & (PGT_count_mask | PGT_locked |
++ PGT_pinned));
++ page->u.inuse.type_info = 0;
++
+ /* Swizzle the owner then reinstate the PGC_allocated reference. */
+ page_set_owner(page, NULL);
+ y = page->count_info;
Index: head/emulators/xen-kernel47/files/xsa215.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa215.patch
+++ head/emulators/xen-kernel47/files/xsa215.patch
@@ -0,0 +1,37 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: correct create_bounce_frame
+
+We may push up to 96 bytes on the guest (kernel) stack, so we should
+also cover as much in the early range check. Note that this is the
+simplest possible patch, which has the theoretical potential of
+breaking a guest: We only really push 96 bytes when invoking the
+failsafe callback, ordinary exceptions only have 56 or 64 bytes pushed
+(without / with error code respectively). There is, however, no PV OS
+known to place a kernel stack there.
+
+This is XSA-215.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/x86_64/entry.S
++++ b/xen/arch/x86/x86_64/entry.S
+@@ -347,7 +347,7 @@ int80_slow_path:
+ jmp handle_exception_saved
+
+ /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
+-/* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
++/* { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
+ /* %rdx: trap_bounce, %rbx: struct vcpu */
+ /* On return only %rbx and %rdx are guaranteed non-clobbered. */
+ create_bounce_frame:
+@@ -367,7 +367,7 @@ create_bounce_frame:
+ 2: andq $~0xf,%rsi # Stack frames are 16-byte aligned.
+ movq $HYPERVISOR_VIRT_START,%rax
+ cmpq %rax,%rsi
+- movq $HYPERVISOR_VIRT_END+60,%rax
++ movq $HYPERVISOR_VIRT_END+12*8,%rax
+ sbb %ecx,%ecx # In +ve address space? Then okay.
+ cmpq %rax,%rsi
+ adc %ecx,%ecx # Above Xen private area? Then okay.
Index: head/emulators/xen-kernel47/files/xsa217.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa217.patch
+++ head/emulators/xen-kernel47/files/xsa217.patch
@@ -0,0 +1,41 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/mm: disallow page stealing from HVM domains
+
+The operation's success can't be controlled by the guest, as the device
+model may have an active mapping of the page. If we nevertheless
+permitted this operation, we'd have to add further TLB flushing to
+prevent scenarios like
+
+"Domains A (HVM), B (PV), C (PV); B->target==A
+ Steps:
+ 1. B maps page X from A as writable
+ 2. B unmaps page X without a TLB flush
+ 3. A sends page X to C via GNTTABOP_transfer
+ 4. C maps page X as pagetable (potentially causing a TLB flush in C,
+ but not in B)
+
+ At this point, X would be mapped as a pagetable in C while being
+ writable through a stale TLB entry in B."
+
+A similar scenario could be constructed for A using XENMEM_exchange and
+some arbitrary PV domain C then having this page allocated.
+
+This is XSA-217.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Acked-by: George Dunlap <george.dunlap@citrix.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4449,6 +4449,9 @@ int steal_page(
+ bool_t drop_dom_ref = 0;
+ const struct domain *owner = dom_xen;
+
++ if ( paging_mode_external(d) )
++ return -1;
++
+ spin_lock(&d->page_alloc_lock);
+
+ if ( is_xen_heap_page(page) || ((owner = page_get_owner(page)) != d) )
Index: head/emulators/xen-kernel47/files/xsa219-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa219-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa219-4.8.patch
@@ -0,0 +1,151 @@
+From 3986b845e87c3f963227ece86bb633450761ec18 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Thu, 11 May 2017 14:47:00 +0100
+Subject: [PATCH] x86/shadow: Hold references for the duration of emulated
+ writes
+
+The (misnamed) emulate_gva_to_mfn() function translates a linear address to an
+mfn, but releases its page reference before returning the mfn to its caller.
+
+sh_emulate_map_dest() uses the results of one or two translations to construct
+a virtual mapping to the underlying frames, completes an emulated
+write/cmpxchg, then unmaps the virtual mappings.
+
+The page references need holding until the mappings are unmapped, or the
+frames can change ownership before the writes occurs.
+
+This is XSA-219
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Tim Deegan <tim@xen.org>
+---
+ xen/arch/x86/mm/shadow/common.c | 54 +++++++++++++++++++++++++++--------------
+ 1 file changed, 36 insertions(+), 18 deletions(-)
+
+diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
+index ced2313..13305d2 100644
+--- a/xen/arch/x86/mm/shadow/common.c
++++ b/xen/arch/x86/mm/shadow/common.c
+@@ -1703,7 +1703,10 @@ static unsigned int shadow_get_allocation(struct domain *d)
+ /**************************************************************************/
+ /* Handling guest writes to pagetables. */
+
+-/* Translate a VA to an MFN, injecting a page-fault if we fail. */
++/*
++ * Translate a VA to an MFN, injecting a page-fault if we fail. If the
++ * mapping succeeds, a reference will be held on the underlying page.
++ */
+ #define BAD_GVA_TO_GFN (~0UL)
+ #define BAD_GFN_TO_MFN (~1UL)
+ #define READONLY_GFN (~2UL)
+@@ -1751,16 +1754,15 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v, unsigned long vaddr,
+ ASSERT(mfn_valid(mfn));
+
+ v->arch.paging.last_write_was_pt = !!sh_mfn_is_a_page_table(mfn);
+- /*
+- * Note shadow cannot page out or unshare this mfn, so the map won't
+- * disappear. Otherwise, caller must hold onto page until done.
+- */
+- put_page(page);
+
+ return mfn;
+ }
+
+-/* Check that the user is allowed to perform this write. */
++/*
++ * Check that the user is allowed to perform this write. If a mapping is
++ * returned, page references will be held on sh_ctxt->mfn[0] and
++ * sh_ctxt->mfn[1] iff !INVALID_MFN.
++ */
+ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
+ unsigned int bytes,
+ struct sh_emulate_ctxt *sh_ctxt)
+@@ -1768,13 +1770,6 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
+ struct domain *d = v->domain;
+ void *map;
+
+- sh_ctxt->mfn[0] = emulate_gva_to_mfn(v, vaddr, sh_ctxt);
+- if ( !mfn_valid(sh_ctxt->mfn[0]) )
+- return ((mfn_x(sh_ctxt->mfn[0]) == BAD_GVA_TO_GFN) ?
+- MAPPING_EXCEPTION :
+- (mfn_x(sh_ctxt->mfn[0]) == READONLY_GFN) ?
+- MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE);
+-
+ #ifndef NDEBUG
+ /* We don't emulate user-mode writes to page tables. */
+ if ( has_hvm_container_domain(d)
+@@ -1787,6 +1782,17 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
+ }
+ #endif
+
++ sh_ctxt->mfn[0] = emulate_gva_to_mfn(v, vaddr, sh_ctxt);
++ if ( !mfn_valid(sh_ctxt->mfn[0]) )
++ {
++ switch ( mfn_x(sh_ctxt->mfn[0]) )
++ {
++ case BAD_GVA_TO_GFN: return MAPPING_EXCEPTION;
++ case READONLY_GFN: return MAPPING_SILENT_FAIL;
++ default: return MAPPING_UNHANDLEABLE;
++ }
++ }
++
+ /* Unaligned writes mean probably this isn't a pagetable. */
+ if ( vaddr & (bytes - 1) )
+ sh_remove_shadows(d, sh_ctxt->mfn[0], 0, 0 /* Slow, can fail. */ );
+@@ -1803,6 +1809,7 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
+ * Cross-page emulated writes are only supported for HVM guests;
+ * PV guests ought to know better.
+ */
++ put_page(mfn_to_page(sh_ctxt->mfn[0]));
+ return MAPPING_UNHANDLEABLE;
+ }
+ else
+@@ -1810,17 +1817,26 @@ void *sh_emulate_map_dest(struct vcpu *v, unsigned long vaddr,
+ /* This write crosses a page boundary. Translate the second page. */
+ sh_ctxt->mfn[1] = emulate_gva_to_mfn(v, vaddr + bytes - 1, sh_ctxt);
+ if ( !mfn_valid(sh_ctxt->mfn[1]) )
+- return ((mfn_x(sh_ctxt->mfn[1]) == BAD_GVA_TO_GFN) ?
+- MAPPING_EXCEPTION :
+- (mfn_x(sh_ctxt->mfn[1]) == READONLY_GFN) ?
+- MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE);
++ {
++ put_page(mfn_to_page(sh_ctxt->mfn[0]));
++ switch ( mfn_x(sh_ctxt->mfn[1]) )
++ {
++ case BAD_GVA_TO_GFN: return MAPPING_EXCEPTION;
++ case READONLY_GFN: return MAPPING_SILENT_FAIL;
++ default: return MAPPING_UNHANDLEABLE;
++ }
++ }
+
+ /* Cross-page writes mean probably not a pagetable. */
+ sh_remove_shadows(d, sh_ctxt->mfn[1], 0, 0 /* Slow, can fail. */ );
+
+ map = vmap(sh_ctxt->mfn, 2);
+ if ( !map )
++ {
++ put_page(mfn_to_page(sh_ctxt->mfn[0]));
++ put_page(mfn_to_page(sh_ctxt->mfn[1]));
+ return MAPPING_UNHANDLEABLE;
++ }
+ map += (vaddr & ~PAGE_MASK);
+ }
+
+@@ -1890,10 +1906,12 @@ void sh_emulate_unmap_dest(struct vcpu *v, void *addr, unsigned int bytes,
+ }
+
+ paging_mark_dirty(v->domain, mfn_x(sh_ctxt->mfn[0]));
++ put_page(mfn_to_page(sh_ctxt->mfn[0]));
+
+ if ( unlikely(mfn_valid(sh_ctxt->mfn[1])) )
+ {
+ paging_mark_dirty(v->domain, mfn_x(sh_ctxt->mfn[1]));
++ put_page(mfn_to_page(sh_ctxt->mfn[1]));
+ vunmap((void *)((unsigned long)addr & PAGE_MASK));
+ }
+ else
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/xsa220-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa220-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa220-4.7.patch
@@ -0,0 +1,133 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: avoid leaking PKRU and BND* between vCPU-s
+
+PKRU is explicitly "XSAVE-managed but not XSAVE-enabled", so guests
+might access the register (via {RD,WR}PKRU) without setting XCR0.PKRU.
+Force context switching as well as migrating the register as soon as
+CR4.PKE is being set the first time.
+
+For MPX (BND<n>, BNDCFGU, and BNDSTATUS) the situation is less clear,
+and the SDM has not entirely consistent information for that case.
+While experimentally the instructions don't change register state as
+long as the two XCR0 bits aren't both 1, be on the safe side and enable
+both if BNDCFGS.EN is being set the first time.
+
+This is XSA-220.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/hvm/hvm.c
++++ b/xen/arch/x86/hvm/hvm.c
+@@ -2452,6 +2452,27 @@ int hvm_set_cr4(unsigned long value, boo
+ paging_update_paging_modes(v);
+ }
+
++ /*
++ * {RD,WR}PKRU are not gated on XCR0.PKRU and hence an oddly behaving
++ * guest may enable the feature in CR4 without enabling it in XCR0. We
++ * need to context switch / migrate PKRU nevertheless.
++ */
++ if ( (value & X86_CR4_PKE) && !(v->arch.xcr0_accum & XSTATE_PKRU) )
++ {
++ int rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ get_xcr0() | XSTATE_PKRU);
++
++ if ( rc )
++ {
++ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.PKRU: %d", rc);
++ goto gpf;
++ }
++
++ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ get_xcr0() & ~XSTATE_PKRU) )
++ /* nothing, best effort only */;
++ }
++
+ return X86EMUL_OKAY;
+
+ gpf:
+--- a/xen/arch/x86/hvm/vmx/vmx.c
++++ b/xen/arch/x86/hvm/vmx/vmx.c
+@@ -31,6 +31,7 @@
+ #include <asm/regs.h>
+ #include <asm/cpufeature.h>
+ #include <asm/processor.h>
++#include <asm/xstate.h>
+ #include <asm/guest_access.h>
+ #include <asm/debugreg.h>
+ #include <asm/msr.h>
+@@ -783,6 +784,45 @@ static int vmx_load_vmcs_ctxt(struct vcp
+ return 0;
+ }
+
++static bool_t vmx_set_guest_bndcfgs(struct vcpu *v, u64 val)
++{
++ if ( !cpu_has_mpx || !cpu_has_vmx_mpx ||
++ !is_canonical_address(val) ||
++ (val & IA32_BNDCFGS_RESERVED) )
++ return 0;
++
++ /*
++ * While MPX instructions are supposed to be gated on XCR0.BND*, let's
++ * nevertheless force the relevant XCR0 bits on when the feature is being
++ * enabled in BNDCFGS.
++ */
++ if ( (val & IA32_BNDCFGS_ENABLE) &&
++ !(v->arch.xcr0_accum & (XSTATE_BNDREGS | XSTATE_BNDCSR)) )
++ {
++ uint64_t xcr0 = get_xcr0();
++ int rc;
++
++ if ( v != current )
++ return 0;
++
++ rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ xcr0 | XSTATE_BNDREGS | XSTATE_BNDCSR);
++
++ if ( rc )
++ {
++ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.BND*: %d", rc);
++ return 0;
++ }
++
++ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK, xcr0) )
++ /* nothing, best effort only */;
++ }
++
++ __vmwrite(GUEST_BNDCFGS, val);
++
++ return 1;
++}
++
+ static unsigned int __init vmx_init_msr(void)
+ {
+ return (cpu_has_mpx && cpu_has_vmx_mpx) +
+@@ -822,11 +862,8 @@ static int vmx_load_msr(struct vcpu *v,
+ switch ( ctxt->msr[i].index )
+ {
+ case MSR_IA32_BNDCFGS:
+- if ( cpu_has_mpx && cpu_has_vmx_mpx &&
+- is_canonical_address(ctxt->msr[i].val) &&
+- !(ctxt->msr[i].val & IA32_BNDCFGS_RESERVED) )
+- __vmwrite(GUEST_BNDCFGS, ctxt->msr[i].val);
+- else if ( ctxt->msr[i].val )
++ if ( !vmx_set_guest_bndcfgs(v, ctxt->msr[i].val) &&
++ ctxt->msr[i].val )
+ err = -ENXIO;
+ break;
+ case MSR_IA32_XSS:
+@@ -2878,11 +2915,8 @@ static int vmx_msr_write_intercept(unsig
+ break;
+ }
+ case MSR_IA32_BNDCFGS:
+- if ( !cpu_has_mpx || !cpu_has_vmx_mpx ||
+- !is_canonical_address(msr_content) ||
+- (msr_content & IA32_BNDCFGS_RESERVED) )
++ if ( !vmx_set_guest_bndcfgs(v, msr_content) )
+ goto gp_fault;
+- __vmwrite(GUEST_BNDCFGS, msr_content);
+ break;
+ case IA32_FEATURE_CONTROL_MSR:
+ case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS:
Index: head/emulators/xen-kernel47/files/xsa221.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa221.patch
+++ head/emulators/xen-kernel47/files/xsa221.patch
@@ -0,0 +1,194 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: evtchn: avoid NULL derefs
+
+Commit fbbd5009e6 ("evtchn: refactor low-level event channel port ops")
+added a de-reference of the struct evtchn pointer for a port without
+first making sure the bucket pointer is non-NULL. This de-reference is
+actually entirely unnecessary, as all relevant callers (beyond the
+problematic do_poll()) already hold the port number in their hands, and
+the actual leaf functions need nothing else.
+
+For FIFO event channels there's a second problem in that the ordering
+of reads and updates to ->num_evtchns and ->event_array[] was so far
+undefined (the read side isn't always holding the domain's event lock).
+Add respective barriers.
+
+This is XSA-221.
+
+Reported-by: Ankur Arora <ankur.a.arora@oracle.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/irq.c
++++ b/xen/arch/x86/irq.c
+@@ -1486,7 +1486,7 @@ int pirq_guest_unmask(struct domain *d)
+ {
+ pirq = pirqs[i]->pirq;
+ if ( pirqs[i]->masked &&
+- !evtchn_port_is_masked(d, evtchn_from_port(d, pirqs[i]->evtchn)) )
++ !evtchn_port_is_masked(d, pirqs[i]->evtchn) )
+ pirq_guest_eoi(pirqs[i]);
+ }
+ } while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
+@@ -2244,7 +2244,6 @@ static void dump_irqs(unsigned char key)
+ int i, irq, pirq;
+ struct irq_desc *desc;
+ irq_guest_action_t *action;
+- struct evtchn *evtchn;
+ struct domain *d;
+ const struct pirq *info;
+ unsigned long flags;
+@@ -2287,11 +2286,10 @@ static void dump_irqs(unsigned char key)
+ d = action->guest[i];
+ pirq = domain_irq_to_pirq(d, irq);
+ info = pirq_info(d, pirq);
+- evtchn = evtchn_from_port(d, info->evtchn);
+ printk("%u:%3d(%c%c%c)",
+ d->domain_id, pirq,
+- (evtchn_port_is_pending(d, evtchn) ? 'P' : '-'),
+- (evtchn_port_is_masked(d, evtchn) ? 'M' : '-'),
++ evtchn_port_is_pending(d, info->evtchn) ? 'P' : '-',
++ evtchn_port_is_masked(d, info->evtchn) ? 'M' : '-',
+ (info->masked ? 'M' : '-'));
+ if ( i != action->nr_guests )
+ printk(",");
+--- a/xen/common/event_2l.c
++++ b/xen/common/event_2l.c
+@@ -61,16 +61,20 @@ static void evtchn_2l_unmask(struct doma
+ }
+ }
+
+-static bool_t evtchn_2l_is_pending(struct domain *d,
+- const struct evtchn *evtchn)
++static bool_t evtchn_2l_is_pending(struct domain *d, evtchn_port_t port)
+ {
+- return test_bit(evtchn->port, &shared_info(d, evtchn_pending));
++ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
++
++ ASSERT(port < max_ports);
++ return port < max_ports && test_bit(port, &shared_info(d, evtchn_pending));
+ }
+
+-static bool_t evtchn_2l_is_masked(struct domain *d,
+- const struct evtchn *evtchn)
++static bool_t evtchn_2l_is_masked(struct domain *d, evtchn_port_t port)
+ {
+- return test_bit(evtchn->port, &shared_info(d, evtchn_mask));
++ unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
++
++ ASSERT(port < max_ports);
++ return port >= max_ports || test_bit(port, &shared_info(d, evtchn_mask));
+ }
+
+ static void evtchn_2l_print_state(struct domain *d,
+--- a/xen/common/event_channel.c
++++ b/xen/common/event_channel.c
+@@ -1380,8 +1380,8 @@ static void domain_dump_evtchn_info(stru
+
+ printk(" %4u [%d/%d/",
+ port,
+- !!evtchn_port_is_pending(d, chn),
+- !!evtchn_port_is_masked(d, chn));
++ evtchn_port_is_pending(d, port),
++ evtchn_port_is_masked(d, port));
+ evtchn_port_print_state(d, chn);
+ printk("]: s=%d n=%d x=%d",
+ chn->state, chn->notify_vcpu_id, chn->xen_consumer);
+--- a/xen/common/event_fifo.c
++++ b/xen/common/event_fifo.c
+@@ -27,6 +27,12 @@ static inline event_word_t *evtchn_fifo_
+ if ( unlikely(port >= d->evtchn_fifo->num_evtchns) )
+ return NULL;
+
++ /*
++ * Callers aren't required to hold d->event_lock, so we need to synchronize
++ * with add_page_to_event_array().
++ */
++ smp_rmb();
++
+ p = port / EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
+ w = port % EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
+
+@@ -287,24 +293,22 @@ static void evtchn_fifo_unmask(struct do
+ evtchn_fifo_set_pending(v, evtchn);
+ }
+
+-static bool_t evtchn_fifo_is_pending(struct domain *d,
+- const struct evtchn *evtchn)
++static bool_t evtchn_fifo_is_pending(struct domain *d, evtchn_port_t port)
+ {
+ event_word_t *word;
+
+- word = evtchn_fifo_word_from_port(d, evtchn->port);
++ word = evtchn_fifo_word_from_port(d, port);
+ if ( unlikely(!word) )
+ return 0;
+
+ return test_bit(EVTCHN_FIFO_PENDING, word);
+ }
+
+-static bool_t evtchn_fifo_is_masked(struct domain *d,
+- const struct evtchn *evtchn)
++static bool_t evtchn_fifo_is_masked(struct domain *d, evtchn_port_t port)
+ {
+ event_word_t *word;
+
+- word = evtchn_fifo_word_from_port(d, evtchn->port);
++ word = evtchn_fifo_word_from_port(d, port);
+ if ( unlikely(!word) )
+ return 1;
+
+@@ -593,6 +597,10 @@ static int add_page_to_event_array(struc
+ return rc;
+
+ d->evtchn_fifo->event_array[slot] = virt;
++
++ /* Synchronize with evtchn_fifo_word_from_port(). */
++ smp_wmb();
++
+ d->evtchn_fifo->num_evtchns += EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
+
+ /*
+--- a/xen/common/schedule.c
++++ b/xen/common/schedule.c
+@@ -965,7 +965,7 @@ static long do_poll(struct sched_poll *s
+ goto out;
+
+ rc = 0;
+- if ( evtchn_port_is_pending(d, evtchn_from_port(d, port)) )
++ if ( evtchn_port_is_pending(d, port) )
+ goto out;
+ }
+
+--- a/xen/include/xen/event.h
++++ b/xen/include/xen/event.h
+@@ -137,8 +137,8 @@ struct evtchn_port_ops {
+ void (*set_pending)(struct vcpu *v, struct evtchn *evtchn);
+ void (*clear_pending)(struct domain *d, struct evtchn *evtchn);
+ void (*unmask)(struct domain *d, struct evtchn *evtchn);
+- bool_t (*is_pending)(struct domain *d, const struct evtchn *evtchn);
+- bool_t (*is_masked)(struct domain *d, const struct evtchn *evtchn);
++ bool_t (*is_pending)(struct domain *d, evtchn_port_t port);
++ bool_t (*is_masked)(struct domain *d, evtchn_port_t port);
+ /*
+ * Is the port unavailable because it's still being cleaned up
+ * after being closed?
+@@ -175,15 +175,15 @@ static inline void evtchn_port_unmask(st
+ }
+
+ static inline bool_t evtchn_port_is_pending(struct domain *d,
+- const struct evtchn *evtchn)
++ evtchn_port_t port)
+ {
+- return d->evtchn_port_ops->is_pending(d, evtchn);
++ return d->evtchn_port_ops->is_pending(d, port);
+ }
+
+ static inline bool_t evtchn_port_is_masked(struct domain *d,
+- const struct evtchn *evtchn)
++ evtchn_port_t port)
+ {
+- return d->evtchn_port_ops->is_masked(d, evtchn);
++ return d->evtchn_port_ops->is_masked(d, port);
+ }
+
+ static inline bool_t evtchn_port_is_busy(struct domain *d, evtchn_port_t port)
Index: head/emulators/xen-kernel47/files/xsa222-1-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa222-1-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa222-1-4.7.patch
@@ -0,0 +1,119 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: xen/memory: Fix return value handing of guest_remove_page()
+
+Despite the description in mm.h, guest_remove_page() previously returned 0 for
+paging errors.
+
+Switch guest_remove_page() to having regular 0/-error semantics, and propagate
+the return values from clear_mmio_p2m_entry() and mem_sharing_unshare_page()
+to the callers (although decrease_reservation() is the only caller which
+currently cares).
+
+This is part of XSA-222.
+
+Reported-by: Julien Grall <julien.grall@arm.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -244,6 +244,7 @@ int guest_remove_page(struct domain *d,
+ p2m_type_t p2mt;
+ #endif
+ unsigned long mfn;
++ int rc;
+
+ #ifdef CONFIG_X86
+ mfn = mfn_x(get_gfn_query(d, gmfn, &p2mt));
+@@ -261,13 +262,15 @@ int guest_remove_page(struct domain *d,
+ put_page(page);
+ }
+ p2m_mem_paging_drop_page(d, gmfn, p2mt);
+- return 1;
++
++ return 0;
+ }
+ if ( p2mt == p2m_mmio_direct )
+ {
+- clear_mmio_p2m_entry(d, gmfn, _mfn(mfn), 0);
++ rc = clear_mmio_p2m_entry(d, gmfn, _mfn(mfn), PAGE_ORDER_4K);
+ put_gfn(d, gmfn);
+- return 1;
++
++ return rc;
+ }
+ #else
+ mfn = gmfn_to_mfn(d, gmfn);
+@@ -277,21 +280,25 @@ int guest_remove_page(struct domain *d,
+ put_gfn(d, gmfn);
+ gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
+ d->domain_id, gmfn);
+- return 0;
++
++ return -EINVAL;
+ }
+
+ #ifdef CONFIG_X86
+ if ( p2m_is_shared(p2mt) )
+ {
+- /* Unshare the page, bail out on error. We unshare because
+- * we might be the only one using this shared page, and we
+- * need to trigger proper cleanup. Once done, this is
+- * like any other page. */
+- if ( mem_sharing_unshare_page(d, gmfn, 0) )
++ /*
++ * Unshare the page, bail out on error. We unshare because we
++ * might be the only one using this shared page, and we need to
++ * trigger proper cleanup. Once done, this is like any other page.
++ */
++ rc = mem_sharing_unshare_page(d, gmfn, 0);
++ if ( rc )
+ {
+ put_gfn(d, gmfn);
+ (void)mem_sharing_notify_enomem(d, gmfn, 0);
+- return 0;
++
++ return rc;
+ }
+ /* Maybe the mfn changed */
+ mfn = mfn_x(get_gfn_query_unlocked(d, gmfn, &p2mt));
+@@ -304,7 +311,8 @@ int guest_remove_page(struct domain *d,
+ {
+ put_gfn(d, gmfn);
+ gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
+- return 0;
++
++ return -ENXIO;
+ }
+
+ if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+@@ -327,7 +335,7 @@ int guest_remove_page(struct domain *d,
+ put_page(page);
+ put_gfn(d, gmfn);
+
+- return 1;
++ return 0;
+ }
+
+ static void decrease_reservation(struct memop_args *a)
+@@ -371,7 +379,7 @@ static void decrease_reservation(struct
+ continue;
+
+ for ( j = 0; j < (1 << a->extent_order); j++ )
+- if ( !guest_remove_page(a->domain, gmfn + j) )
++ if ( guest_remove_page(a->domain, gmfn + j) )
+ goto out;
+ }
+
+--- a/xen/include/xen/mm.h
++++ b/xen/include/xen/mm.h
+@@ -509,8 +509,7 @@ int xenmem_add_to_physmap_one(struct dom
+ union xen_add_to_physmap_batch_extra extra,
+ unsigned long idx, xen_pfn_t gpfn);
+
+-/* Returns 1 on success, 0 on error, negative if the ring
+- * for event propagation is full in the presence of paging */
++/* Returns 0 on success, or negative on error. */
+ int guest_remove_page(struct domain *d, unsigned long gmfn);
+
+ #define RAM_TYPE_CONVENTIONAL 0x00000001
Index: head/emulators/xen-kernel47/files/xsa222-2-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa222-2-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa222-2-4.7.patch
@@ -0,0 +1,412 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: guest_physmap_remove_page() needs its return value checked
+
+Callers, namely such subsequently freeing the page, must not blindly
+assume success - the function may namely fail when needing to shatter a
+super page, but there not being memory available for the then needed
+intermediate page table.
+
+As it happens, guest_remove_page() callers now also all check the
+return value.
+
+Furthermore a missed put_gfn() on an error path in gnttab_transfer() is
+also being taken care of.
+
+This is part of XSA-222.
+
+Reported-by: Julien Grall <julien.grall@arm.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Julien Grall <julien.grall@arm.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/arm/mm.c
++++ b/xen/arch/arm/mm.c
+@@ -1299,13 +1299,14 @@ int replace_grant_host_mapping(unsigned
+ {
+ unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
+ struct domain *d = current->domain;
++ int rc;
+
+ if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
+ return GNTST_general_error;
+
+- guest_physmap_remove_page(d, gfn, mfn, 0);
++ rc = guest_physmap_remove_page(d, gfn, mfn, 0);
+
+- return GNTST_okay;
++ return rc ? GNTST_general_error : GNTST_okay;
+ }
+
+ int is_iomem_page(unsigned long mfn)
+--- a/xen/arch/arm/p2m.c
++++ b/xen/arch/arm/p2m.c
+@@ -1313,15 +1313,14 @@ int guest_physmap_add_entry(struct domai
+ d->arch.p2m.default_access);
+ }
+
+-void guest_physmap_remove_page(struct domain *d,
+- unsigned long gpfn,
+- unsigned long mfn, unsigned int page_order)
++int guest_physmap_remove_page(struct domain *d, unsigned long gfn,
++ unsigned long mfn, unsigned int page_order)
+ {
+- apply_p2m_changes(d, REMOVE,
+- pfn_to_paddr(gpfn),
+- pfn_to_paddr(gpfn + (1<<page_order)),
+- pfn_to_paddr(mfn), MATTR_MEM, 0, p2m_invalid,
+- d->arch.p2m.default_access);
++ return apply_p2m_changes(d, REMOVE,
++ pfn_to_paddr(gfn),
++ pfn_to_paddr(gfn + (1 << page_order)),
++ pfn_to_paddr(mfn), MATTR_MEM, 0, p2m_invalid,
++ d->arch.p2m.default_access);
+ }
+
+ int p2m_alloc_table(struct domain *d)
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -802,7 +802,15 @@ int arch_domain_soft_reset(struct domain
+ ret = -ENOMEM;
+ goto exit_put_gfn;
+ }
+- guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
++
++ ret = guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
++ if ( ret )
++ {
++ printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame %lx\n",
++ d->domain_id, gfn);
++ free_domheap_page(new_page);
++ goto exit_put_gfn;
++ }
+
+ ret = guest_physmap_add_page(d, gfn, page_to_mfn(new_page), PAGE_ORDER_4K);
+ if ( ret )
+--- a/xen/arch/x86/domain_build.c
++++ b/xen/arch/x86/domain_build.c
+@@ -427,7 +427,9 @@ static __init void pvh_add_mem_mapping(s
+ if ( !iomem_access_permitted(d, mfn + i, mfn + i) )
+ {
+ omfn = get_gfn_query_unlocked(d, gfn + i, &t);
+- guest_physmap_remove_page(d, gfn + i, mfn_x(omfn), PAGE_ORDER_4K);
++ if ( guest_physmap_remove_page(d, gfn + i, mfn_x(omfn),
++ PAGE_ORDER_4K) )
++ /* nothing, best effort only */;
+ continue;
+ }
+
+--- a/xen/arch/x86/hvm/ioreq.c
++++ b/xen/arch/x86/hvm/ioreq.c
+@@ -267,8 +267,9 @@ bool_t is_ioreq_server_page(struct domai
+ static void hvm_remove_ioreq_gmfn(
+ struct domain *d, struct hvm_ioreq_page *iorp)
+ {
+- guest_physmap_remove_page(d, iorp->gmfn,
+- page_to_mfn(iorp->page), 0);
++ if ( guest_physmap_remove_page(d, iorp->gmfn,
++ page_to_mfn(iorp->page), 0) )
++ domain_crash(d);
+ clear_page(iorp->va);
+ }
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4271,7 +4271,11 @@ static int replace_grant_p2m_mapping(
+ type, mfn_x(old_mfn), frame);
+ return GNTST_general_error;
+ }
+- guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K);
++ if ( guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K) )
++ {
++ put_gfn(d, gfn);
++ return GNTST_general_error;
++ }
+
+ put_gfn(d, gfn);
+ return GNTST_okay;
+@@ -4793,7 +4797,7 @@ int xenmem_add_to_physmap_one(
+ struct page_info *page = NULL;
+ unsigned long gfn = 0; /* gcc ... */
+ unsigned long prev_mfn, mfn = 0, old_gpfn;
+- int rc;
++ int rc = 0;
+ p2m_type_t p2mt;
+
+ switch ( space )
+@@ -4867,25 +4871,30 @@ int xenmem_add_to_physmap_one(
+ {
+ if ( is_xen_heap_mfn(prev_mfn) )
+ /* Xen heap frames are simply unhooked from this phys slot. */
+- guest_physmap_remove_page(d, gpfn, prev_mfn, PAGE_ORDER_4K);
++ rc = guest_physmap_remove_page(d, gpfn, prev_mfn, PAGE_ORDER_4K);
+ else
+ /* Normal domain memory is freed, to avoid leaking memory. */
+- guest_remove_page(d, gpfn);
++ rc = guest_remove_page(d, gpfn);
+ }
+ /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page. */
+ put_gfn(d, gpfn);
+
++ if ( rc )
++ goto put_both;
++
+ /* Unmap from old location, if any. */
+ old_gpfn = get_gpfn_from_mfn(mfn);
+ ASSERT( old_gpfn != SHARED_M2P_ENTRY );
+ if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range )
+ ASSERT( old_gpfn == gfn );
+ if ( old_gpfn != INVALID_M2P_ENTRY )
+- guest_physmap_remove_page(d, old_gpfn, mfn, PAGE_ORDER_4K);
++ rc = guest_physmap_remove_page(d, old_gpfn, mfn, PAGE_ORDER_4K);
+
+ /* Map at new location. */
+- rc = guest_physmap_add_page(d, gpfn, mfn, PAGE_ORDER_4K);
++ if ( !rc )
++ rc = guest_physmap_add_page(d, gpfn, mfn, PAGE_ORDER_4K);
+
++ put_both:
+ /* In the XENMAPSPACE_gmfn, we took a ref of the gfn at the top */
+ if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range )
+ put_gfn(d, gfn);
+--- a/xen/arch/x86/mm/p2m.c
++++ b/xen/arch/x86/mm/p2m.c
+@@ -2837,10 +2837,12 @@ int p2m_add_foreign(struct domain *tdom,
+ {
+ if ( is_xen_heap_mfn(prev_mfn) )
+ /* Xen heap frames are simply unhooked from this phys slot */
+- guest_physmap_remove_page(tdom, gpfn, prev_mfn, 0);
++ rc = guest_physmap_remove_page(tdom, gpfn, prev_mfn, 0);
+ else
+ /* Normal domain memory is freed, to avoid leaking memory. */
+- guest_remove_page(tdom, gpfn);
++ rc = guest_remove_page(tdom, gpfn);
++ if ( rc )
++ goto put_both;
+ }
+ /*
+ * Create the new mapping. Can't use guest_physmap_add_page() because it
+@@ -2853,6 +2855,7 @@ int p2m_add_foreign(struct domain *tdom,
+ "gpfn:%lx mfn:%lx fgfn:%lx td:%d fd:%d\n",
+ gpfn, mfn, fgfn, tdom->domain_id, fdom->domain_id);
+
++ put_both:
+ put_page(page);
+
+ /*
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -1768,6 +1768,7 @@ gnttab_transfer(
+ for ( i = 0; i < count; i++ )
+ {
+ bool_t okay;
++ int rc;
+
+ if (i && hypercall_preempt_check())
+ return i;
+@@ -1818,27 +1819,33 @@ gnttab_transfer(
+ goto copyback;
+ }
+
+- guest_physmap_remove_page(d, gop.mfn, mfn, 0);
++ rc = guest_physmap_remove_page(d, gop.mfn, mfn, 0);
+ gnttab_flush_tlb(d);
++ if ( rc )
++ {
++ gdprintk(XENLOG_INFO,
++ "gnttab_transfer: can't remove GFN %"PRI_xen_pfn" (MFN %lx)\n",
++ gop.mfn, mfn);
++ gop.status = GNTST_general_error;
++ goto put_gfn_and_copyback;
++ }
+
+ /* Find the target domain. */
+ if ( unlikely((e = rcu_lock_domain_by_id(gop.domid)) == NULL) )
+ {
+- put_gfn(d, gop.mfn);
+ gdprintk(XENLOG_INFO, "gnttab_transfer: can't find domain %d\n",
+ gop.domid);
+- page->count_info &= ~(PGC_count_mask|PGC_allocated);
+- free_domheap_page(page);
+ gop.status = GNTST_bad_domain;
+- goto copyback;
++ goto put_gfn_and_copyback;
+ }
+
+ if ( xsm_grant_transfer(XSM_HOOK, d, e) )
+ {
+- put_gfn(d, gop.mfn);
+ gop.status = GNTST_permission_denied;
+ unlock_and_copyback:
+ rcu_unlock_domain(e);
++ put_gfn_and_copyback:
++ put_gfn(d, gop.mfn);
+ page->count_info &= ~(PGC_count_mask|PGC_allocated);
+ free_domheap_page(page);
+ goto copyback;
+@@ -1887,12 +1894,8 @@ gnttab_transfer(
+ "Transferee (d%d) has no headroom (tot %u, max %u)\n",
+ e->domain_id, e->tot_pages, e->max_pages);
+
+- rcu_unlock_domain(e);
+- put_gfn(d, gop.mfn);
+- page->count_info &= ~(PGC_count_mask|PGC_allocated);
+- free_domheap_page(page);
+ gop.status = GNTST_general_error;
+- goto copyback;
++ goto unlock_and_copyback;
+ }
+
+ /* Okay, add the page to 'e'. */
+@@ -1921,13 +1924,8 @@ gnttab_transfer(
+
+ if ( drop_dom_ref )
+ put_domain(e);
+- rcu_unlock_domain(e);
+-
+- put_gfn(d, gop.mfn);
+- page->count_info &= ~(PGC_count_mask|PGC_allocated);
+- free_domheap_page(page);
+ gop.status = GNTST_general_error;
+- goto copyback;
++ goto unlock_and_copyback;
+ }
+
+ page_list_add_tail(page, &e->page_list);
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -250,8 +250,12 @@ int guest_remove_page(struct domain *d,
+ mfn = mfn_x(get_gfn_query(d, gmfn, &p2mt));
+ if ( unlikely(p2m_is_paging(p2mt)) )
+ {
+- guest_physmap_remove_page(d, gmfn, mfn, 0);
++ rc = guest_physmap_remove_page(d, gmfn, mfn, 0);
+ put_gfn(d, gmfn);
++
++ if ( rc )
++ return rc;
++
+ /* If the page hasn't yet been paged out, there is an
+ * actual page that needs to be released. */
+ if ( p2mt == p2m_ram_paging_out )
+@@ -315,7 +319,9 @@ int guest_remove_page(struct domain *d,
+ return -ENXIO;
+ }
+
+- if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
++ rc = guest_physmap_remove_page(d, gmfn, mfn, 0);
++
++ if ( !rc && test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+ put_page_and_type(page);
+
+ /*
+@@ -326,16 +332,14 @@ int guest_remove_page(struct domain *d,
+ * For this purpose (and to match populate_physmap() behavior), the page
+ * is kept allocated.
+ */
+- if ( !is_domain_direct_mapped(d) &&
++ if ( !rc && !is_domain_direct_mapped(d) &&
+ test_and_clear_bit(_PGC_allocated, &page->count_info) )
+ put_page(page);
+
+- guest_physmap_remove_page(d, gmfn, mfn, 0);
+-
+ put_page(page);
+ put_gfn(d, gmfn);
+
+- return 0;
++ return rc;
+ }
+
+ static void decrease_reservation(struct memop_args *a)
+@@ -570,7 +574,8 @@ static long memory_exchange(XEN_GUEST_HA
+ gfn = mfn_to_gmfn(d, mfn);
+ /* Pages were unshared above */
+ BUG_ON(SHARED_M2P(gfn));
+- guest_physmap_remove_page(d, gfn, mfn, 0);
++ if ( guest_physmap_remove_page(d, gfn, mfn, 0) )
++ domain_crash(d);
+ put_page(page);
+ }
+
+@@ -1120,7 +1125,7 @@ long do_memory_op(unsigned long cmd, XEN
+ page = get_page_from_gfn(d, xrfp.gpfn, NULL, P2M_ALLOC);
+ if ( page )
+ {
+- guest_physmap_remove_page(d, xrfp.gpfn, page_to_mfn(page), 0);
++ rc = guest_physmap_remove_page(d, xrfp.gpfn, page_to_mfn(page), 0);
+ put_page(page);
+ }
+ else
+--- a/xen/drivers/passthrough/arm/smmu.c
++++ b/xen/drivers/passthrough/arm/smmu.c
+@@ -2783,9 +2783,7 @@ static int arm_smmu_unmap_page(struct do
+ if ( !is_domain_direct_mapped(d) )
+ return -EINVAL;
+
+- guest_physmap_remove_page(d, gfn, gfn, 0);
+-
+- return 0;
++ return guest_physmap_remove_page(d, gfn, gfn, 0);
+ }
+
+ static const struct iommu_ops arm_smmu_iommu_ops = {
+--- a/xen/include/asm-arm/p2m.h
++++ b/xen/include/asm-arm/p2m.h
+@@ -177,10 +177,6 @@ static inline int guest_physmap_add_page
+ return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
+ }
+
+-void guest_physmap_remove_page(struct domain *d,
+- unsigned long gpfn,
+- unsigned long mfn, unsigned int page_order);
+-
+ unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn);
+
+ /*
+--- a/xen/include/asm-x86/p2m.h
++++ b/xen/include/asm-x86/p2m.h
+@@ -558,11 +558,6 @@ static inline int guest_physmap_add_page
+ return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
+ }
+
+-/* Remove a page from a domain's p2m table */
+-int guest_physmap_remove_page(struct domain *d,
+- unsigned long gfn,
+- unsigned long mfn, unsigned int page_order);
+-
+ /* Set a p2m range as populate-on-demand */
+ int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
+ unsigned int order);
+--- a/xen/include/xen/p2m-common.h
++++ b/xen/include/xen/p2m-common.h
+@@ -1,6 +1,7 @@
+ #ifndef _XEN_P2M_COMMON_H
+ #define _XEN_P2M_COMMON_H
+
++#include <xen/mm.h>
+ #include <public/vm_event.h>
+
+ /*
+@@ -33,6 +34,11 @@ typedef enum {
+ /* NOTE: Assumed to be only 4 bits right now on x86. */
+ } p2m_access_t;
+
++/* Remove a page from a domain's p2m table */
++int __must_check
++guest_physmap_remove_page(struct domain *d, unsigned long gfn,
++ unsigned long mfn, unsigned int page_order);
++
+ /* Map MMIO regions in the p2m: start_gfn and nr describe the range in
+ * * the guest physical address space to map, starting from the machine
+ * * frame number mfn. */
+--- a/xen/include/xen/mm.h
++++ b/xen/include/xen/mm.h
+@@ -510,7 +510,7 @@ int xenmem_add_to_physmap_one(struct dom
+ unsigned long idx, xen_pfn_t gpfn);
+
+ /* Returns 0 on success, or negative on error. */
+-int guest_remove_page(struct domain *d, unsigned long gmfn);
++int __must_check guest_remove_page(struct domain *d, unsigned long gmfn);
+
+ #define RAM_TYPE_CONVENTIONAL 0x00000001
+ #define RAM_TYPE_RESERVED 0x00000002
Index: head/emulators/xen-kernel47/files/xsa226-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa226-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa226-4.7.patch
@@ -0,0 +1,133 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: grant_table: Default to v1, and disallow transitive grants
+
+The reference counting and locking discipline for transitive grants is broken.
+Their use is therefore declared out of security support.
+
+This is XSA-226.
+
+Transitive grants are expected to be unconditionally available with grant
+table v2. Hiding transitive grants alone is an ABI breakage for the guest.
+Modern versions of Linux and the Windows PV drivers use grant table v1, but
+older versions did use v2.
+
+In principle, disabling gnttab v2 entirely is the safer way to cause guests to
+avoid using transitive grants. However, some older guests which defaulted to
+using gnttab v2 don't tolerate falling back from v2 to v1 over migrate.
+
+This patch introduces a new command line option to control grant table
+behaviour. One suboption allows a choice of the maximum grant table version
+Xen will allow the guest to use, and defaults to v2. A different suboption
+independently controls whether transitive grants can be used.
+
+The default case is:
+
+ gnttab=max_ver:2
+
+To disable gnttab v2 entirely, use:
+
+ gnttab=max_ver:1
+
+To allow gnttab v2 and transitive grants, use:
+
+ gnttab=max_ver:2,transitive
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
+index 73f5265..b792abf 100644
+--- a/docs/misc/xen-command-line.markdown
++++ b/docs/misc/xen-command-line.markdown
+@@ -758,6 +758,22 @@ Controls EPT related features.
+
+ Specify which console gdbstub should use. See **console**.
+
++### gnttab
++> `= List of [ max_ver:<integer>, transitive ]`
++
++> Default: `gnttab=max_ver:2,no-transitive`
++
++Control various aspects of the grant table behaviour available to guests.
++
++* `max_ver` Select the maximum grant table version to offer to guests. Valid
++version are 1 and 2.
++* `transitive` Permit or disallow the use of transitive grants. Note that the
++use of grant table v2 without transitive grants is an ABI breakage from the
++guests point of view.
++
++*Warning:*
++Due to XSA-226, the use of transitive grants is outside of security support.
++
+ ### gnttab\_max\_frames
+ > `= <integer>`
+
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index f06b664..109c552 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -50,6 +50,42 @@ integer_param("gnttab_max_nr_frames", max_nr_grant_frames);
+ unsigned int __read_mostly max_grant_frames;
+ integer_param("gnttab_max_frames", max_grant_frames);
+
++static unsigned int __read_mostly opt_gnttab_max_version = 2;
++static bool_t __read_mostly opt_transitive_grants;
++
++static void __init parse_gnttab(char *s)
++{
++ char *ss;
++
++ do {
++ ss = strchr(s, ',');
++ if ( ss )
++ *ss = '\0';
++
++ if ( !strncmp(s, "max_ver:", 8) )
++ {
++ long ver = simple_strtol(s + 8, NULL, 10);
++
++ if ( ver >= 1 && ver <= 2 )
++ opt_gnttab_max_version = ver;
++ }
++ else
++ {
++ bool_t val = !!strncmp(s, "no-", 3);
++
++ if ( !val )
++ s += 3;
++
++ if ( !strcmp(s, "transitive") )
++ opt_transitive_grants = val;
++ }
++
++ s = ss + 1;
++ } while ( ss );
++}
++
++custom_param("gnttab", parse_gnttab);
++
+ /* The maximum number of grant mappings is defined as a multiplier of the
+ * maximum number of grant table entries. This defines the multiplier used.
+ * Pretty arbitrary. [POLICY]
+@@ -2188,6 +2224,10 @@ __acquire_grant_for_copy(
+ }
+ else if ( (shah->flags & GTF_type_mask) == GTF_transitive )
+ {
++ if ( !opt_transitive_grants )
++ PIN_FAIL(unlock_out_clear, GNTST_general_error,
++ "transitive grant disallowed by policy\n");
++
+ if ( !allow_transitive )
+ PIN_FAIL(unlock_out_clear, GNTST_general_error,
+ "transitive grant when transitivity not allowed\n");
+@@ -3156,7 +3196,10 @@ do_grant_table_op(
+ }
+ case GNTTABOP_set_version:
+ {
+- rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t));
++ if ( opt_gnttab_max_version == 1 )
++ rc = -ENOSYS; /* Behave as before set_version was introduced. */
++ else
++ rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t));
+ break;
+ }
+ case GNTTABOP_get_status_frames:
Index: head/emulators/xen-kernel47/files/xsa227.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa227.patch
+++ head/emulators/xen-kernel47/files/xsa227.patch
@@ -0,0 +1,52 @@
+From fa7268b94f8a0a7792ee12d5b8e23a60e52a3a84 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Tue, 20 Jun 2017 19:18:54 +0100
+Subject: [PATCH] x86/grant: Disallow misaligned PTEs
+
+Pagetable entries must be aligned to function correctly. Disallow attempts
+from the guest to have a grant PTE created at a misaligned address, which
+would result in corruption of the L1 table with largely-guest-controlled
+values.
+
+This is XSA-227
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/arch/x86/mm.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index 97b3b4b..00f517a 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -3763,6 +3763,9 @@ static int create_grant_pte_mapping(
+ l1_pgentry_t ol1e;
+ struct domain *d = v->domain;
+
++ if ( !IS_ALIGNED(pte_addr, sizeof(nl1e)) )
++ return GNTST_general_error;
++
+ adjust_guest_l1e(nl1e, d);
+
+ gmfn = pte_addr >> PAGE_SHIFT;
+@@ -3819,6 +3822,16 @@ static int destroy_grant_pte_mapping(
+ struct page_info *page;
+ l1_pgentry_t ol1e;
+
++ /*
++ * addr comes from Xen's active_entry tracking so isn't guest controlled,
++ * but it had still better be PTE-aligned.
++ */
++ if ( !IS_ALIGNED(addr, sizeof(ol1e)) )
++ {
++ ASSERT_UNREACHABLE();
++ return GNTST_general_error;
++ }
++
+ gmfn = addr >> PAGE_SHIFT;
+ page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
+
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/xsa228-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa228-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa228-4.8.patch
@@ -0,0 +1,198 @@
+From cb91f4c43bd4158daa6561c73921a6455176f278 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Mon, 31 Jul 2017 15:17:56 +0100
+Subject: [PATCH] gnttab: split maptrack lock to make it fulfill its purpose
+ again
+
+The way the lock is currently being used in get_maptrack_handle(), it
+protects only the maptrack limit: The function acts on current's list
+only, so races on list accesses are impossible even without the lock.
+
+Otoh list access races are possible between __get_maptrack_handle() and
+put_maptrack_handle(), due to the invocation of the former for other
+than current from steal_maptrack_handle(). Introduce a per-vCPU lock
+for list accesses to become race free again. This lock will be
+uncontended except when it becomes necessary to take the steal path,
+i.e. in the common case there should be no meaningful performance
+impact.
+
+When in get_maptrack_handle adds a stolen entry to a fresh, empty,
+freelist, we think that there is probably no concurrency. However,
+this is not a fast path and adding the locking there makes the code
+clearly correct.
+
+Also, while we are here: the stolen maptrack_entry's tail pointer was
+not properly set. Set it.
+
+This is XSA-228.
+
+Reported-by: Ian Jackson <ian.jackson@eu.citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
+---
+ docs/misc/grant-tables.txt | 7 ++++++-
+ xen/common/grant_table.c | 30 ++++++++++++++++++++++++------
+ xen/include/xen/grant_table.h | 2 +-
+ xen/include/xen/sched.h | 1 +
+ 4 files changed, 32 insertions(+), 8 deletions(-)
+
+diff --git a/docs/misc/grant-tables.txt b/docs/misc/grant-tables.txt
+index 417ce2d..64da5cf 100644
+--- a/docs/misc/grant-tables.txt
++++ b/docs/misc/grant-tables.txt
+@@ -87,7 +87,8 @@ is complete.
+ inconsistent grant table state such as current
+ version, partially initialized active table pages,
+ etc.
+- grant_table->maptrack_lock : spinlock used to protect the maptrack free list
++ grant_table->maptrack_lock : spinlock used to protect the maptrack limit
++ v->maptrack_freelist_lock : spinlock used to protect the maptrack free list
+ active_grant_entry->lock : spinlock used to serialize modifications to
+ active entries
+
+@@ -102,6 +103,10 @@ is complete.
+ The maptrack free list is protected by its own spinlock. The maptrack
+ lock may be locked while holding the grant table lock.
+
++ The maptrack_freelist_lock is an innermost lock. It may be locked
++ while holding other locks, but no other locks may be acquired within
++ it.
++
+ Active entries are obtained by calling active_entry_acquire(gt, ref).
+ This function returns a pointer to the active entry after locking its
+ spinlock. The caller must hold the grant table read lock before
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index f9654f1..593121c 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -304,11 +304,16 @@ __get_maptrack_handle(
+ {
+ unsigned int head, next, prev_head;
+
++ spin_lock(&v->maptrack_freelist_lock);
++
+ do {
+ /* No maptrack pages allocated for this VCPU yet? */
+ head = read_atomic(&v->maptrack_head);
+ if ( unlikely(head == MAPTRACK_TAIL) )
++ {
++ spin_unlock(&v->maptrack_freelist_lock);
+ return -1;
++ }
+
+ /*
+ * Always keep one entry in the free list to make it easier to
+@@ -316,12 +321,17 @@ __get_maptrack_handle(
+ */
+ next = read_atomic(&maptrack_entry(t, head).ref);
+ if ( unlikely(next == MAPTRACK_TAIL) )
++ {
++ spin_unlock(&v->maptrack_freelist_lock);
+ return -1;
++ }
+
+ prev_head = head;
+ head = cmpxchg(&v->maptrack_head, prev_head, next);
+ } while ( head != prev_head );
+
++ spin_unlock(&v->maptrack_freelist_lock);
++
+ return head;
+ }
+
+@@ -380,6 +390,8 @@ put_maptrack_handle(
+ /* 2. Add entry to the tail of the list on the original VCPU. */
+ v = currd->vcpu[maptrack_entry(t, handle).vcpu];
+
++ spin_lock(&v->maptrack_freelist_lock);
++
+ cur_tail = read_atomic(&v->maptrack_tail);
+ do {
+ prev_tail = cur_tail;
+@@ -388,6 +400,8 @@ put_maptrack_handle(
+
+ /* 3. Update the old tail entry to point to the new entry. */
+ write_atomic(&maptrack_entry(t, prev_tail).ref, handle);
++
++ spin_unlock(&v->maptrack_freelist_lock);
+ }
+
+ static inline int
+@@ -411,10 +425,6 @@ get_maptrack_handle(
+ */
+ if ( nr_maptrack_frames(lgt) >= max_maptrack_frames )
+ {
+- /*
+- * Can drop the lock since no other VCPU can be adding a new
+- * frame once they've run out.
+- */
+ spin_unlock(&lgt->maptrack_lock);
+
+ /*
+@@ -426,8 +436,12 @@ get_maptrack_handle(
+ handle = steal_maptrack_handle(lgt, curr);
+ if ( handle == -1 )
+ return -1;
++ spin_lock(&curr->maptrack_freelist_lock);
++ maptrack_entry(lgt, handle).ref = MAPTRACK_TAIL;
+ curr->maptrack_tail = handle;
+- write_atomic(&curr->maptrack_head, handle);
++ if ( curr->maptrack_head == MAPTRACK_TAIL )
++ write_atomic(&curr->maptrack_head, handle);
++ spin_unlock(&curr->maptrack_freelist_lock);
+ }
+ return steal_maptrack_handle(lgt, curr);
+ }
+@@ -460,12 +474,15 @@ get_maptrack_handle(
+ smp_wmb();
+ lgt->maptrack_limit += MAPTRACK_PER_PAGE;
+
++ spin_unlock(&lgt->maptrack_lock);
++ spin_lock(&curr->maptrack_freelist_lock);
++
+ do {
+ new_mt[i - 1].ref = read_atomic(&curr->maptrack_head);
+ head = cmpxchg(&curr->maptrack_head, new_mt[i - 1].ref, handle + 1);
+ } while ( head != new_mt[i - 1].ref );
+
+- spin_unlock(&lgt->maptrack_lock);
++ spin_unlock(&curr->maptrack_freelist_lock);
+
+ return handle;
+ }
+@@ -3474,6 +3491,7 @@ grant_table_destroy(
+
+ void grant_table_init_vcpu(struct vcpu *v)
+ {
++ spin_lock_init(&v->maptrack_freelist_lock);
+ v->maptrack_head = MAPTRACK_TAIL;
+ v->maptrack_tail = MAPTRACK_TAIL;
+ }
+diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
+index 4e77899..100f2b3 100644
+--- a/xen/include/xen/grant_table.h
++++ b/xen/include/xen/grant_table.h
+@@ -78,7 +78,7 @@ struct grant_table {
+ /* Mapping tracking table per vcpu. */
+ struct grant_mapping **maptrack;
+ unsigned int maptrack_limit;
+- /* Lock protecting the maptrack page list, head, and limit */
++ /* Lock protecting the maptrack limit */
+ spinlock_t maptrack_lock;
+ /* The defined versions are 1 and 2. Set to 0 if we don't know
+ what version to use yet. */
+diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
+index 1fbda87..ff0f38f 100644
+--- a/xen/include/xen/sched.h
++++ b/xen/include/xen/sched.h
+@@ -223,6 +223,7 @@ struct vcpu
+ int controller_pause_count;
+
+ /* Maptrack */
++ spinlock_t maptrack_freelist_lock;
+ unsigned int maptrack_head;
+ unsigned int maptrack_tail;
+
+--
+2.1.4
+
Index: head/emulators/xen-kernel47/files/xsa230.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa230.patch
+++ head/emulators/xen-kernel47/files/xsa230.patch
@@ -0,0 +1,38 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: gnttab: correct pin status fixup for copy
+
+Regardless of copy operations only setting GNTPIN_hst*, GNTPIN_dev*
+also need to be taken into account when deciding whether to clear
+_GTF_{read,writ}ing. At least for consistency with code elsewhere the
+read part better doesn't use any mask at all.
+
+This is XSA-230.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
+index ae34547..9c9d33c 100644
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -2107,10 +2107,10 @@ __release_grant_for_copy(
+ static void __fixup_status_for_copy_pin(const struct active_grant_entry *act,
+ uint16_t *status)
+ {
+- if ( !(act->pin & GNTPIN_hstw_mask) )
++ if ( !(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
+ gnttab_clear_flag(_GTF_writing, status);
+
+- if ( !(act->pin & GNTPIN_hstr_mask) )
++ if ( !act->pin )
+ gnttab_clear_flag(_GTF_reading, status);
+ }
+
+@@ -2318,7 +2318,7 @@ __acquire_grant_for_copy(
+
+ unlock_out_clear:
+ if ( !(readonly) &&
+- !(act->pin & GNTPIN_hstw_mask) )
++ !(act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) )
+ gnttab_clear_flag(_GTF_writing, status);
+
+ if ( !act->pin )
Index: head/emulators/xen-kernel47/files/xsa231-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa231-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa231-4.7.patch
@@ -0,0 +1,108 @@
+From: George Dunlap <george.dunlap@citrix.com>
+Subject: xen/mm: make sure node is less than MAX_NUMNODES
+
+The output of MEMF_get_node(memflags) can be as large as nodeid_t can
+hold (currently 255). This is then used as an index to arrays of size
+MAX_NUMNODE, which is 64 on x86 and 1 on ARM, can be passed in by an
+untrusted guest (via memory_exchange and increase_reservation) and is
+not currently bounds-checked.
+
+Check the value in page_alloc.c before using it, and also check the
+value in the hypercall call sites and return -EINVAL if appropriate.
+Don't permit domains other than the hardware or control domain to
+allocate node-constrained memory.
+
+This is XSA-231.
+
+Reported-by: Matthew Daley <mattd@bugfuzz.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -390,6 +390,31 @@ static void decrease_reservation(struct
+ a->nr_done = i;
+ }
+
++static bool_t propagate_node(unsigned int xmf, unsigned int *memflags)
++{
++ const struct domain *currd = current->domain;
++
++ BUILD_BUG_ON(XENMEMF_get_node(0) != NUMA_NO_NODE);
++ BUILD_BUG_ON(MEMF_get_node(0) != NUMA_NO_NODE);
++
++ if ( XENMEMF_get_node(xmf) == NUMA_NO_NODE )
++ return 1;
++
++ if ( is_hardware_domain(currd) || is_control_domain(currd) )
++ {
++ if ( XENMEMF_get_node(xmf) >= MAX_NUMNODES )
++ return 0;
++
++ *memflags |= MEMF_node(XENMEMF_get_node(xmf));
++ if ( xmf & XENMEMF_exact_node_request )
++ *memflags |= MEMF_exact_node;
++ }
++ else if ( xmf & XENMEMF_exact_node_request )
++ return 0;
++
++ return 1;
++}
++
+ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
+ {
+ struct xen_memory_exchange exch;
+@@ -462,6 +487,12 @@ static long memory_exchange(XEN_GUEST_HA
+ }
+ }
+
++ if ( unlikely(!propagate_node(exch.out.mem_flags, &memflags)) )
++ {
++ rc = -EINVAL;
++ goto fail_early;
++ }
++
+ d = rcu_lock_domain_by_any_id(exch.in.domid);
+ if ( d == NULL )
+ {
+@@ -480,7 +511,6 @@ static long memory_exchange(XEN_GUEST_HA
+ d,
+ XENMEMF_get_address_bits(exch.out.mem_flags) ? :
+ (BITS_PER_LONG+PAGE_SHIFT)));
+- memflags |= MEMF_node(XENMEMF_get_node(exch.out.mem_flags));
+
+ for ( i = (exch.nr_exchanged >> in_chunk_order);
+ i < (exch.in.nr_extents >> in_chunk_order);
+@@ -834,12 +864,8 @@ static int construct_memop_from_reservat
+ }
+ read_unlock(&d->vnuma_rwlock);
+ }
+- else
+- {
+- a->memflags |= MEMF_node(XENMEMF_get_node(r->mem_flags));
+- if ( r->mem_flags & XENMEMF_exact_node_request )
+- a->memflags |= MEMF_exact_node;
+- }
++ else if ( unlikely(!propagate_node(r->mem_flags, &a->memflags)) )
++ return -EINVAL;
+
+ return 0;
+ }
+--- a/xen/common/page_alloc.c
++++ b/xen/common/page_alloc.c
+@@ -711,9 +711,13 @@ static struct page_info *alloc_heap_page
+ if ( node >= MAX_NUMNODES )
+ node = cpu_to_node(smp_processor_id());
+ }
++ else if ( unlikely(node >= MAX_NUMNODES) )
++ {
++ ASSERT_UNREACHABLE();
++ return NULL;
++ }
+ first_node = node;
+
+- ASSERT(node < MAX_NUMNODES);
+ ASSERT(zone_lo <= zone_hi);
+ ASSERT(zone_hi < NR_ZONES);
+
Index: head/emulators/xen-kernel47/files/xsa232.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa232.patch
+++ head/emulators/xen-kernel47/files/xsa232.patch
@@ -0,0 +1,23 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: grant_table: fix GNTTABOP_cache_flush handling
+
+Don't fall over a NULL grant_table pointer when the owner of the domain
+is a system domain (DOMID_{XEN,IO} etc).
+
+This is XSA-232.
+
+Reported-by: Matthew Daley <mattd@bugfuzz.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -3053,7 +3053,7 @@ static int cache_flush(gnttab_cache_flus
+
+ page = mfn_to_page(mfn);
+ owner = page_get_owner_and_reference(page);
+- if ( !owner )
++ if ( !owner || !owner->grant_table )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
Index: head/emulators/xen-kernel47/files/xsa233.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa233.patch
+++ head/emulators/xen-kernel47/files/xsa233.patch
@@ -0,0 +1,52 @@
+From: Juergen Gross <jgross@suse.com>
+Subject: tools/xenstore: dont unlink connection object twice
+
+A connection object of a domain with associated stubdom has two
+parents: the domain and the stubdom. When cleaning up the list of
+active domains in domain_cleanup() make sure not to unlink the
+connection twice from the same domain. This could happen when the
+domain and its stubdom are being destroyed at the same time leading
+to the domain loop being entered twice.
+
+Additionally don't use talloc_free() in this case as it will remove
+a random parent link, leading eventually to a memory leak. Use
+talloc_unlink() instead specifying the context from which the
+connection object should be removed.
+
+This is XSA-233.
+
+Reported-by: Eric Chanudet <chanudete@ainfosec.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Ian Jackson <ian.jackson@eu.citrix.com>
+
+--- a/tools/xenstore/xenstored_domain.c
++++ b/tools/xenstore/xenstored_domain.c
+@@ -221,10 +221,11 @@ static int destroy_domain(void *_domain)
+ static void domain_cleanup(void)
+ {
+ xc_dominfo_t dominfo;
+- struct domain *domain, *tmp;
++ struct domain *domain;
+ int notify = 0;
+
+- list_for_each_entry_safe(domain, tmp, &domains, list) {
++ again:
++ list_for_each_entry(domain, &domains, list) {
+ if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
+ &dominfo) == 1 &&
+ dominfo.domid == domain->domid) {
+@@ -236,8 +237,12 @@ static void domain_cleanup(void)
+ if (!dominfo.dying)
+ continue;
+ }
+- talloc_free(domain->conn);
+- notify = 0; /* destroy_domain() fires the watch */
++ if (domain->conn) {
++ talloc_unlink(talloc_autofree_context(), domain->conn);
++ domain->conn = NULL;
++ notify = 0; /* destroy_domain() fires the watch */
++ goto again;
++ }
+ }
+
+ if (notify)
Index: head/emulators/xen-kernel47/files/xsa234-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa234-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa234-4.8.patch
@@ -0,0 +1,185 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: gnttab: also validate PTE permissions upon destroy/replace
+
+In order for PTE handling to match up with the reference counting done
+by common code, presence and writability of grant mapping PTEs must
+also be taken into account; validating just the frame number is not
+enough. This is in particular relevant if a guest fiddles with grant
+PTEs via non-grant hypercalls.
+
+Note that the flags being passed to replace_grant_host_mapping()
+already happen to be those of the existing mapping, so no new function
+parameter is needed.
+
+This is XSA-234.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4017,7 +4017,8 @@ static int create_grant_pte_mapping(
+ }
+
+ static int destroy_grant_pte_mapping(
+- uint64_t addr, unsigned long frame, struct domain *d)
++ uint64_t addr, unsigned long frame, unsigned int grant_pte_flags,
++ struct domain *d)
+ {
+ int rc = GNTST_okay;
+ void *va;
+@@ -4063,16 +4064,27 @@ static int destroy_grant_pte_mapping(
+
+ ol1e = *(l1_pgentry_t *)va;
+
+- /* Check that the virtual address supplied is actually mapped to frame. */
+- if ( unlikely(l1e_get_pfn(ol1e) != frame) )
++ /*
++ * Check that the PTE supplied actually maps frame (with appropriate
++ * permissions).
++ */
++ if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
++ unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++ (_PAGE_PRESENT | _PAGE_RW)) )
+ {
+ page_unlock(page);
+- MEM_LOG("PTE entry %lx for address %"PRIx64" doesn't match frame %lx",
+- (unsigned long)l1e_get_intpte(ol1e), addr, frame);
++ MEM_LOG("PTE %"PRIpte" at %"PRIx64" doesn't match grant (%"PRIpte")",
++ l1e_get_intpte(ol1e), addr,
++ l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
+ rc = GNTST_general_error;
+ goto failed;
+ }
+
++ if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++ ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
++ MEM_LOG("PTE flags %x at %"PRIx64" don't match grant (%x)\n",
++ l1e_get_flags(ol1e), addr, grant_pte_flags);
++
+ /* Delete pagetable entry. */
+ if ( unlikely(!UPDATE_ENTRY
+ (l1,
+@@ -4081,7 +4093,7 @@ static int destroy_grant_pte_mapping(
+ 0)) )
+ {
+ page_unlock(page);
+- MEM_LOG("Cannot delete PTE entry at %p", va);
++ MEM_LOG("Cannot delete PTE entry at %"PRIx64, addr);
+ rc = GNTST_general_error;
+ goto failed;
+ }
+@@ -4149,7 +4161,8 @@ static int create_grant_va_mapping(
+ }
+
+ static int replace_grant_va_mapping(
+- unsigned long addr, unsigned long frame, l1_pgentry_t nl1e, struct vcpu *v)
++ unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
++ l1_pgentry_t nl1e, struct vcpu *v)
+ {
+ l1_pgentry_t *pl1e, ol1e;
+ unsigned long gl1mfn;
+@@ -4185,19 +4198,30 @@ static int replace_grant_va_mapping(
+
+ ol1e = *pl1e;
+
+- /* Check that the virtual address supplied is actually mapped to frame. */
+- if ( unlikely(l1e_get_pfn(ol1e) != frame) )
+- {
+- MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx",
+- l1e_get_pfn(ol1e), addr, frame);
++ /*
++ * Check that the virtual address supplied is actually mapped to frame
++ * (with appropriate permissions).
++ */
++ if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
++ unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++ (_PAGE_PRESENT | _PAGE_RW)) )
++ {
++ MEM_LOG("PTE %"PRIpte" for %lx doesn't match grant (%"PRIpte")",
++ l1e_get_intpte(ol1e), addr,
++ l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
+ rc = GNTST_general_error;
+ goto unlock_and_out;
+ }
+
++ if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++ ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
++ MEM_LOG("PTE flags %x for %"PRIx64" don't match grant (%x)",
++ l1e_get_flags(ol1e), addr, grant_pte_flags);
++
+ /* Delete pagetable entry. */
+ if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) )
+ {
+- MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e);
++ MEM_LOG("Cannot delete PTE entry for %"PRIx64, addr);
+ rc = GNTST_general_error;
+ goto unlock_and_out;
+ }
+@@ -4211,9 +4235,11 @@ static int replace_grant_va_mapping(
+ }
+
+ static int destroy_grant_va_mapping(
+- unsigned long addr, unsigned long frame, struct vcpu *v)
++ unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
++ struct vcpu *v)
+ {
+- return replace_grant_va_mapping(addr, frame, l1e_empty(), v);
++ return replace_grant_va_mapping(addr, frame, grant_pte_flags,
++ l1e_empty(), v);
+ }
+
+ static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame,
+@@ -4307,21 +4333,40 @@ int replace_grant_host_mapping(
+ unsigned long gl1mfn;
+ struct page_info *l1pg;
+ int rc;
++ unsigned int grant_pte_flags;
+
+ if ( paging_mode_external(current->domain) )
+ return replace_grant_p2m_mapping(addr, frame, new_addr, flags);
+
++ grant_pte_flags =
++ _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_GNTTAB | _PAGE_NX;
++
++ if ( flags & GNTMAP_application_map )
++ grant_pte_flags |= _PAGE_USER;
++ if ( !(flags & GNTMAP_readonly) )
++ grant_pte_flags |= _PAGE_RW;
++ /*
++ * On top of the explicit settings done by create_grant_host_mapping()
++ * also open-code relevant parts of adjust_guest_l1e(). Don't mirror
++ * available and cachability flags, though.
++ */
++ if ( !is_pv_32bit_domain(curr->domain) )
++ grant_pte_flags |= (grant_pte_flags & _PAGE_USER)
++ ? _PAGE_GLOBAL
++ : _PAGE_GUEST_KERNEL | _PAGE_USER;
++
+ if ( flags & GNTMAP_contains_pte )
+ {
+ if ( !new_addr )
+- return destroy_grant_pte_mapping(addr, frame, curr->domain);
++ return destroy_grant_pte_mapping(addr, frame, grant_pte_flags,
++ curr->domain);
+
+ MEM_LOG("Unsupported grant table operation");
+ return GNTST_general_error;
+ }
+
+ if ( !new_addr )
+- return destroy_grant_va_mapping(addr, frame, curr);
++ return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr);
+
+ pl1e = guest_map_l1e(new_addr, &gl1mfn);
+ if ( !pl1e )
+@@ -4369,7 +4414,7 @@ int replace_grant_host_mapping(
+ put_page(l1pg);
+ guest_unmap_l1e(pl1e);
+
+- rc = replace_grant_va_mapping(addr, frame, ol1e, curr);
++ rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr);
+ if ( rc && !paging_mode_refcounts(curr->domain) )
+ put_page_from_l1e(ol1e, curr->domain);
+
Index: head/emulators/xen-kernel47/files/xsa236-4.9.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa236-4.9.patch
+++ head/emulators/xen-kernel47/files/xsa236-4.9.patch
@@ -0,0 +1,66 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: gnttab: fix pin count / page reference race
+
+Dropping page references before decrementing pin counts is a bad idea
+if assumptions are being made that a non-zero pin count implies a valid
+page. Fix the order of operations in gnttab_copy_release_buf(), but at
+the same time also remove the assertion that was found to trigger:
+map_grant_ref() also has the potential of causing a race here, and
+changing the order of operations there would likely be quite a bit more
+involved.
+
+This is XSA-236.
+
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -2330,9 +2330,20 @@ __acquire_grant_for_copy(
+ td = page_get_owner_and_reference(*page);
+ /*
+ * act->pin being non-zero should guarantee the page to have a
+- * non-zero refcount and hence a valid owner.
++ * non-zero refcount and hence a valid owner (matching the one on
++ * record), with one exception: If the owning domain is dying we
++ * had better not make implications from pin count (map_grant_ref()
++ * updates pin counts before obtaining page references, for
++ * example).
+ */
+- ASSERT(td);
++ if ( td != rd || rd->is_dying )
++ {
++ if ( td )
++ put_page(*page);
++ *page = NULL;
++ rc = GNTST_bad_domain;
++ goto unlock_out_clear;
++ }
+ }
+
+ act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
+@@ -2451,6 +2462,11 @@ static void gnttab_copy_release_buf(stru
+ unmap_domain_page(buf->virt);
+ buf->virt = NULL;
+ }
++ if ( buf->have_grant )
++ {
++ __release_grant_for_copy(buf->domain, buf->ptr.u.ref, buf->read_only);
++ buf->have_grant = 0;
++ }
+ if ( buf->have_type )
+ {
+ put_page_type(buf->page);
+@@ -2461,11 +2477,6 @@ static void gnttab_copy_release_buf(stru
+ put_page(buf->page);
+ buf->page = NULL;
+ }
+- if ( buf->have_grant )
+- {
+- __release_grant_for_copy(buf->domain, buf->ptr.u.ref, buf->read_only);
+- buf->have_grant = 0;
+- }
+ }
+
+ static int gnttab_copy_claim_buf(const struct gnttab_copy *op,
Index: head/emulators/xen-kernel47/files/xsa238.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa238.patch
+++ head/emulators/xen-kernel47/files/xsa238.patch
@@ -0,0 +1,45 @@
+From cdc2887076b19b39fab9faec495082586f3113df Mon Sep 17 00:00:00 2001
+From: XenProject Security Team <security@xenproject.org>
+Date: Tue, 5 Sep 2017 13:41:37 +0200
+Subject: x86/ioreq server: correctly handle bogus
+ XEN_DMOP_{,un}map_io_range_to_ioreq_server arguments
+
+Misbehaving device model can pass incorrect XEN_DMOP_map/
+unmap_io_range_to_ioreq_server arguments, namely end < start when
+specifying address range. When this happens we hit ASSERT(s <= e) in
+rangeset_contains_range()/rangeset_overlaps_range() with debug builds.
+Production builds will not trap right away but may misbehave later
+while handling such bogus ranges.
+
+This is XSA-238.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/arch/x86/hvm/ioreq.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
+index b2a8b0e986..8c8bf1f0ec 100644
+--- a/xen/arch/x86/hvm/ioreq.c
++++ b/xen/arch/x86/hvm/ioreq.c
+@@ -820,6 +820,9 @@ int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
+ struct hvm_ioreq_server *s;
+ int rc;
+
++ if ( start > end )
++ return -EINVAL;
++
+ spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
+@@ -872,6 +875,9 @@ int hvm_unmap_io_range_from_ioreq_server(struct domain *d, ioservid_t id,
+ struct hvm_ioreq_server *s;
+ int rc;
+
++ if ( start > end )
++ return -EINVAL;
++
+ spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
+
+ rc = -ENOENT;
Index: head/emulators/xen-kernel47/files/xsa239.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa239.patch
+++ head/emulators/xen-kernel47/files/xsa239.patch
@@ -0,0 +1,46 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/HVM: prefill partially used variable on emulation paths
+
+Certain handlers ignore the access size (vioapic_write() being the
+example this was found with), perhaps leading to subsequent reads
+seeing data that wasn't actually written by the guest. For
+consistency and extra safety also do this on the read path of
+hvm_process_io_intercept(), even if this doesn't directly affect what
+guests get to see, as we've supposedly already dealt with read handlers
+leaving data completely unitialized.
+
+This is XSA-239.
+
+Reported-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/hvm/emulate.c
++++ b/xen/arch/x86/hvm/emulate.c
+@@ -129,7 +129,7 @@ static int hvmemul_do_io(
+ .count = *reps,
+ .dir = dir,
+ .df = df,
+- .data = data,
++ .data = data_is_addr ? data : 0,
+ .data_is_ptr = data_is_addr, /* ioreq_t field name is misleading */
+ .state = STATE_IOREQ_READY,
+ };
+--- a/xen/arch/x86/hvm/intercept.c
++++ b/xen/arch/x86/hvm/intercept.c
+@@ -127,6 +127,7 @@ int hvm_process_io_intercept(const struc
+ addr = (p->type == IOREQ_TYPE_COPY) ?
+ p->addr + step * i :
+ p->addr;
++ data = 0;
+ rc = ops->read(handler, addr, p->size, &data);
+ if ( rc != X86EMUL_OKAY )
+ break;
+@@ -161,6 +162,7 @@ int hvm_process_io_intercept(const struc
+ {
+ if ( p->data_is_ptr )
+ {
++ data = 0;
+ switch ( hvm_copy_from_guest_phys(&data, p->data + step * i,
+ p->size) )
+ {
Index: head/emulators/xen-kernel47/files/xsa241-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa241-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa241-4.8.patch
@@ -0,0 +1,120 @@
+x86: don't store possibly stale TLB flush time stamp
+
+While the timing window is extremely narrow, it is theoretically
+possible for an update to the TLB flush clock and a subsequent flush
+IPI to happen between the read and write parts of the update of the
+per-page stamp. Exclude this possibility by disabling interrupts
+across the update, preventing the IPI to be serviced in the middle.
+
+This is XSA-241.
+
+Reported-by: Jann Horn <jannh@google.com>
+Suggested-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/arm/smp.c
++++ b/xen/arch/arm/smp.c
+@@ -1,4 +1,5 @@
+ #include <xen/config.h>
++#include <xen/mm.h>
+ #include <asm/system.h>
+ #include <asm/smp.h>
+ #include <asm/cpregs.h>
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -2524,7 +2524,7 @@ static int _put_final_page_type(struct p
+ */
+ if ( !(shadow_mode_enabled(page_get_owner(page)) &&
+ (page->count_info & PGC_page_table)) )
+- page->tlbflush_timestamp = tlbflush_current_time();
++ page_set_tlbflush_timestamp(page);
+ wmb();
+ page->u.inuse.type_info--;
+ }
+@@ -2534,7 +2534,7 @@ static int _put_final_page_type(struct p
+ (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
+ if ( !(shadow_mode_enabled(page_get_owner(page)) &&
+ (page->count_info & PGC_page_table)) )
+- page->tlbflush_timestamp = tlbflush_current_time();
++ page_set_tlbflush_timestamp(page);
+ wmb();
+ page->u.inuse.type_info |= PGT_validated;
+ }
+@@ -2588,7 +2588,7 @@ static int _put_page_type(struct page_in
+ if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
+ {
+ /*
+- * page_set_tlbflush_timestamp() accesses the same union
++ * set_tlbflush_timestamp() accesses the same union
+ * linear_pt_count lives in. Unvalidated page table pages,
+ * however, should occur during domain destruction only
+ * anyway. Updating of linear_pt_count luckily is not
+@@ -2609,7 +2609,7 @@ static int _put_page_type(struct page_in
+ */
+ if ( !(shadow_mode_enabled(page_get_owner(page)) &&
+ (page->count_info & PGC_page_table)) )
+- page->tlbflush_timestamp = tlbflush_current_time();
++ page_set_tlbflush_timestamp(page);
+ }
+
+ if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
+--- a/xen/arch/x86/mm/shadow/common.c
++++ b/xen/arch/x86/mm/shadow/common.c
+@@ -1464,7 +1464,7 @@ void shadow_free(struct domain *d, mfn_t
+ * TLBs when we reuse the page. Because the destructors leave the
+ * contents of the pages in place, we can delay TLB flushes until
+ * just before the allocator hands the page out again. */
+- sp->tlbflush_timestamp = tlbflush_current_time();
++ page_set_tlbflush_timestamp(sp);
+ perfc_decr(shadow_alloc_count);
+ page_list_add_tail(sp, &d->arch.paging.shadow.freelist);
+ sp = next;
+--- a/xen/common/page_alloc.c
++++ b/xen/common/page_alloc.c
+@@ -960,7 +960,7 @@ static void free_heap_pages(
+ /* If a page has no owner it will need no safety TLB flush. */
+ pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
+ if ( pg[i].u.free.need_tlbflush )
+- pg[i].tlbflush_timestamp = tlbflush_current_time();
++ page_set_tlbflush_timestamp(&pg[i]);
+
+ /* This page is not a guest frame any more. */
+ page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
+--- a/xen/include/asm-arm/flushtlb.h
++++ b/xen/include/asm-arm/flushtlb.h
+@@ -12,6 +12,11 @@ static inline void tlbflush_filter(cpuma
+
+ #define tlbflush_current_time() (0)
+
++static inline void page_set_tlbflush_timestamp(struct page_info *page)
++{
++ page->tlbflush_timestamp = tlbflush_current_time();
++}
++
+ #if defined(CONFIG_ARM_32)
+ # include <asm/arm32/flushtlb.h>
+ #elif defined(CONFIG_ARM_64)
+--- a/xen/include/asm-x86/flushtlb.h
++++ b/xen/include/asm-x86/flushtlb.h
+@@ -23,6 +23,20 @@ DECLARE_PER_CPU(u32, tlbflush_time);
+
+ #define tlbflush_current_time() tlbflush_clock
+
++static inline void page_set_tlbflush_timestamp(struct page_info *page)
++{
++ /*
++ * Prevent storing a stale time stamp, which could happen if an update
++ * to tlbflush_clock plus a subsequent flush IPI happen between the
++ * reading of tlbflush_clock and the writing of the struct page_info
++ * field.
++ */
++ ASSERT(local_irq_is_enabled());
++ local_irq_disable();
++ page->tlbflush_timestamp = tlbflush_current_time();
++ local_irq_enable();
++}
++
+ /*
+ * @cpu_stamp is the timestamp at last TLB flush for the CPU we are testing.
+ * @lastuse_stamp is a timestamp taken when the PFN we are testing was last
Index: head/emulators/xen-kernel47/files/xsa242-4.9.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa242-4.9.patch
+++ head/emulators/xen-kernel47/files/xsa242-4.9.patch
@@ -0,0 +1,43 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: don't allow page_unlock() to drop the last type reference
+
+Only _put_page_type() does the necessary cleanup, and hence not all
+domain pages can be released during guest cleanup (leaving around
+zombie domains) if we get this wrong.
+
+This is XSA-242.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -1923,7 +1923,11 @@ void page_unlock(struct page_info *page)
+
+ do {
+ x = y;
++ ASSERT((x & PGT_count_mask) && (x & PGT_locked));
++
+ nx = x - (1 | PGT_locked);
++ /* We must not drop the last reference here. */
++ ASSERT(nx & PGT_count_mask);
+ } while ( (y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x );
+ }
+
+@@ -2611,6 +2615,17 @@ static int _put_page_type(struct page_in
+ (page->count_info & PGC_page_table)) )
+ page_set_tlbflush_timestamp(page);
+ }
++ else if ( unlikely((nx & (PGT_locked | PGT_count_mask)) ==
++ (PGT_locked | 1)) )
++ {
++ /*
++ * We must not drop the second to last reference when the page is
++ * locked, as page_unlock() doesn't do any cleanup of the type.
++ */
++ cpu_relax();
++ y = page->u.inuse.type_info;
++ continue;
++ }
+
+ if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
+ break;
Index: head/emulators/xen-kernel47/files/xsa243-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa243-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa243-4.7.patch
@@ -0,0 +1,93 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests
+
+When initially creating a monitor table for 4-level translated guests, don't
+install a shadow-linear mapping. This mapping is actually self-linear, and
+trips up the writeable heuristic logic into following Xen's mappings, not the
+guests' shadows it was expecting to follow.
+
+A consequence of this is that sh_guess_wrmap() needs to cope with there being
+no shadow-linear mapping present, which in practice occurs once each time a
+vcpu switches to 4-level paging from a different paging mode.
+
+An appropriate shadow-linear slot will be inserted into the monitor table
+either while constructing lower level monitor tables, or by sh_update_cr3().
+
+While fixing this, clarify the safety of the other mappings. Despite
+appearing unsafe, it is correct to create a guest-linear mapping for
+translated domains; this is self-linear and doesn't point into the translated
+domain. Drop a dead clause for translate != external guests.
+
+This is XSA-243.
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Acked-by: Tim Deegan <tim@xen.org>
+
+diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
+index 428be37..c83932f 100644
+--- a/xen/arch/x86/mm/shadow/multi.c
++++ b/xen/arch/x86/mm/shadow/multi.c
+@@ -1472,26 +1472,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
+ sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
+ }
+
+- /* Shadow linear mapping for 4-level shadows. N.B. for 3-level
+- * shadows on 64-bit xen, this linear mapping is later replaced by the
+- * monitor pagetable structure, which is built in make_monitor_table
+- * and maintained by sh_update_linear_entries. */
+- sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+- shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
+-
+- /* Self linear mapping. */
+- if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
++ /*
++ * Linear mapping slots:
++ *
++ * Calling this function with gl4mfn == sl4mfn is used to construct a
++ * monitor table for translated domains. In this case, gl4mfn forms the
++ * self-linear mapping (i.e. not pointing into the translated domain), and
++ * the shadow-linear slot is skipped. The shadow-linear slot is either
++ * filled when constructing lower level monitor tables, or via
++ * sh_update_cr3() for 4-level guests.
++ *
++ * Calling this function with gl4mfn != sl4mfn is used for non-translated
++ * guests, where the shadow-linear slot is actually self-linear, and the
++ * guest-linear slot points into the guests view of its pagetables.
++ */
++ if ( shadow_mode_translate(d) )
+ {
+- // linear tables may not be used with translated PV guests
+- sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
++ ASSERT(mfn_x(gl4mfn) == mfn_x(sl4mfn));
++
++ sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+ shadow_l4e_empty();
+ }
+ else
+ {
+- sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+- shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
++ ASSERT(mfn_x(gl4mfn) != mfn_x(sl4mfn));
++
++ sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
++ shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
+ }
+
++ sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
++ shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
++
+ unmap_domain_page(sl4e);
+ }
+ #endif
+@@ -4293,6 +4305,11 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn)
+
+ /* Carefully look in the shadow linear map for the l1e we expect */
+ #if SHADOW_PAGING_LEVELS >= 4
++ /* Is a shadow linear map is installed in the first place? */
++ sl4p = v->arch.paging.shadow.guest_vtable;
++ sl4p += shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START);
++ if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
++ return 0;
+ sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
+ if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
+ return 0;
Index: head/emulators/xen-kernel47/files/xsa244-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa244-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa244-4.7.patch
@@ -0,0 +1,51 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: x86/cpu: fix IST handling during PCPU bringup
+
+Clear IST references in newly allocated IDTs. Nothing good will come of
+having them set before the TSS is suitably constructed (although the chances
+of the CPU surviving such an IST interrupt/exception is extremely slim).
+
+Uniformly set the IST references after the TSS is in place. This fixes an
+issue on AMD hardware, where onlining a PCPU while PCPU0 is in HVM context
+will cause IST_NONE to be copied into the new IDT, making that PCPU vulnerable
+to privilege escalation from PV guests until it subsequently schedules an HVM
+guest.
+
+This is XSA-244.
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/arch/x86/cpu/common.c
++++ b/xen/arch/x86/cpu/common.c
+@@ -617,6 +617,7 @@ void __init early_cpu_init(void)
+ * - Sets up TSS with stack pointers, including ISTs
+ * - Inserts TSS selector into regular and compat GDTs
+ * - Loads GDT, IDT, TR then null LDT
++ * - Sets up IST references in the IDT
+ */
+ void load_system_tables(void)
+ {
+@@ -663,6 +664,10 @@ void load_system_tables(void)
+ asm volatile ("lidt %0" : : "m" (idtr) );
+ asm volatile ("ltr %w0" : : "rm" (TSS_ENTRY << 3) );
+ asm volatile ("lldt %w0" : : "rm" (0) );
++
++ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_DF);
++ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NMI);
++ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_MCE);
+ }
+
+ /*
+--- a/xen/arch/x86/smpboot.c
++++ b/xen/arch/x86/smpboot.c
+@@ -715,6 +715,9 @@ static int cpu_smpboot_alloc(unsigned in
+ if ( idt_tables[cpu] == NULL )
+ goto oom;
+ memcpy(idt_tables[cpu], idt_table, IDT_ENTRIES * sizeof(idt_entry_t));
++ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_NONE);
++ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NONE);
++ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
+
+ for ( stub_page = 0, i = cpu & ~(STUBS_PER_PAGE - 1);
+ i < nr_cpu_ids && i <= (cpu | (STUBS_PER_PAGE - 1)); ++i )
Index: head/emulators/xen-kernel47/files/xsa246-4.7.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa246-4.7.patch
+++ head/emulators/xen-kernel47/files/xsa246-4.7.patch
@@ -0,0 +1,74 @@
+From: Julien Grall <julien.grall@linaro.org>
+Subject: x86/pod: prevent infinite loop when shattering large pages
+
+When populating pages, the PoD may need to split large ones using
+p2m_set_entry and request the caller to retry (see ept_get_entry for
+instance).
+
+p2m_set_entry may fail to shatter if it is not possible to allocate
+memory for the new page table. However, the error is not propagated
+resulting to the callers to retry infinitely the PoD.
+
+Prevent the infinite loop by return false when it is not possible to
+shatter the large mapping.
+
+This is XSA-246.
+
+Signed-off-by: Julien Grall <julien.grall@linaro.org>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/x86/mm/p2m-pod.c
++++ b/xen/arch/x86/mm/p2m-pod.c
+@@ -1073,9 +1073,8 @@ p2m_pod_demand_populate(struct p2m_domai
+ * NOTE: In a fine-grained p2m locking scenario this operation
+ * may need to promote its locking from gfn->1g superpage
+ */
+- p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_2M,
+- p2m_populate_on_demand, p2m->default_access);
+- return 0;
++ return p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_2M,
++ p2m_populate_on_demand, p2m->default_access);
+ }
+
+ /* Only reclaim if we're in actual need of more cache. */
+@@ -1106,8 +1105,12 @@ p2m_pod_demand_populate(struct p2m_domai
+
+ gfn_aligned = (gfn >> order) << order;
+
+- p2m_set_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw,
+- p2m->default_access);
++ if ( p2m_set_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw,
++ p2m->default_access) )
++ {
++ p2m_pod_cache_add(p2m, p, order);
++ goto out_fail;
++ }
+
+ for( i = 0; i < (1UL << order); i++ )
+ {
+@@ -1152,13 +1155,18 @@ remap_and_retry:
+ BUG_ON(order != PAGE_ORDER_2M);
+ pod_unlock(p2m);
+
+- /* Remap this 2-meg region in singleton chunks */
+- /* NOTE: In a p2m fine-grained lock scenario this might
+- * need promoting the gfn lock from gfn->2M superpage */
++ /*
++ * Remap this 2-meg region in singleton chunks. See the comment on the
++ * 1G page splitting path above for why a single call suffices.
++ *
++ * NOTE: In a p2m fine-grained lock scenario this might
++ * need promoting the gfn lock from gfn->2M superpage.
++ */
+ gfn_aligned = (gfn>>order)<<order;
+- for(i=0; i<(1<<order); i++)
+- p2m_set_entry(p2m, gfn_aligned + i, _mfn(INVALID_MFN), PAGE_ORDER_4K,
+- p2m_populate_on_demand, p2m->default_access);
++ if ( p2m_set_entry(p2m, gfn_aligned, _mfn(INVALID_MFN), PAGE_ORDER_4K,
++ p2m_populate_on_demand, p2m->default_access) )
++ return -1;
++
+ if ( tb_init_done )
+ {
+ struct {
Index: head/emulators/xen-kernel47/files/xsa248-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa248-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa248-4.8.patch
@@ -0,0 +1,162 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/mm: don't wrongly set page ownership
+
+PV domains can obtain mappings of any pages owned by the correct domain,
+including ones that aren't actually assigned as "normal" RAM, but used
+by Xen internally. At the moment such "internal" pages marked as owned
+by a guest include pages used to track logdirty bits, as well as p2m
+pages and the "unpaged pagetable" for HVM guests. Since the PV memory
+management and shadow code conflict in their use of struct page_info
+fields, and since shadow code is being used for log-dirty handling for
+PV domains, pages coming from the shadow pool must, for PV domains, not
+have the domain set as their owner.
+
+While the change could be done conditionally for just the PV case in
+shadow code, do it unconditionally (and for consistency also for HAP),
+just to be on the safe side.
+
+There's one special case though for shadow code: The page table used for
+running a HVM guest in unpaged mode is subject to get_page() (in
+set_shadow_status()) and hence must have its owner set.
+
+This is XSA-248.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Tim Deegan <tim@xen.org>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+
+--- a/xen/arch/x86/mm/hap/hap.c
++++ b/xen/arch/x86/mm/hap/hap.c
+@@ -283,8 +283,7 @@ static struct page_info *hap_alloc_p2m_p
+ {
+ d->arch.paging.hap.total_pages--;
+ d->arch.paging.hap.p2m_pages++;
+- page_set_owner(pg, d);
+- pg->count_info |= 1;
++ ASSERT(!page_get_owner(pg) && !(pg->count_info & PGC_count_mask));
+ }
+ else if ( !d->arch.paging.p2m_alloc_failed )
+ {
+@@ -299,21 +298,23 @@ static struct page_info *hap_alloc_p2m_p
+
+ static void hap_free_p2m_page(struct domain *d, struct page_info *pg)
+ {
++ struct domain *owner = page_get_owner(pg);
++
+ /* This is called both from the p2m code (which never holds the
+ * paging lock) and the log-dirty code (which always does). */
+ paging_lock_recursive(d);
+
+- ASSERT(page_get_owner(pg) == d);
+- /* Should have just the one ref we gave it in alloc_p2m_page() */
+- if ( (pg->count_info & PGC_count_mask) != 1 ) {
+- HAP_ERROR("Odd p2m page %p count c=%#lx t=%"PRtype_info"\n",
+- pg, pg->count_info, pg->u.inuse.type_info);
++ /* Should still have no owner and count zero. */
++ if ( owner || (pg->count_info & PGC_count_mask) )
++ {
++ HAP_ERROR("d%d: Odd p2m page %"PRI_mfn" d=%d c=%lx t=%"PRtype_info"\n",
++ d->domain_id, mfn_x(page_to_mfn(pg)),
++ owner ? owner->domain_id : DOMID_INVALID,
++ pg->count_info, pg->u.inuse.type_info);
+ WARN();
++ pg->count_info &= ~PGC_count_mask;
++ page_set_owner(pg, NULL);
+ }
+- pg->count_info &= ~PGC_count_mask;
+- /* Free should not decrement domain's total allocation, since
+- * these pages were allocated without an owner. */
+- page_set_owner(pg, NULL);
+ d->arch.paging.hap.p2m_pages--;
+ d->arch.paging.hap.total_pages++;
+ hap_free(d, page_to_mfn(pg));
+--- a/xen/arch/x86/mm/shadow/common.c
++++ b/xen/arch/x86/mm/shadow/common.c
+@@ -1573,32 +1573,29 @@ shadow_alloc_p2m_page(struct domain *d)
+ pg = mfn_to_page(shadow_alloc(d, SH_type_p2m_table, 0));
+ d->arch.paging.shadow.p2m_pages++;
+ d->arch.paging.shadow.total_pages--;
++ ASSERT(!page_get_owner(pg) && !(pg->count_info & PGC_count_mask));
+
+ paging_unlock(d);
+
+- /* Unlike shadow pages, mark p2m pages as owned by the domain.
+- * Marking the domain as the owner would normally allow the guest to
+- * create mappings of these pages, but these p2m pages will never be
+- * in the domain's guest-physical address space, and so that is not
+- * believed to be a concern. */
+- page_set_owner(pg, d);
+- pg->count_info |= 1;
+ return pg;
+ }
+
+ static void
+ shadow_free_p2m_page(struct domain *d, struct page_info *pg)
+ {
+- ASSERT(page_get_owner(pg) == d);
+- /* Should have just the one ref we gave it in alloc_p2m_page() */
+- if ( (pg->count_info & PGC_count_mask) != 1 )
++ struct domain *owner = page_get_owner(pg);
++
++ /* Should still have no owner and count zero. */
++ if ( owner || (pg->count_info & PGC_count_mask) )
+ {
+- SHADOW_ERROR("Odd p2m page count c=%#lx t=%"PRtype_info"\n",
++ SHADOW_ERROR("d%d: Odd p2m page %"PRI_mfn" d=%d c=%lx t=%"PRtype_info"\n",
++ d->domain_id, mfn_x(page_to_mfn(pg)),
++ owner ? owner->domain_id : DOMID_INVALID,
+ pg->count_info, pg->u.inuse.type_info);
++ pg->count_info &= ~PGC_count_mask;
++ page_set_owner(pg, NULL);
+ }
+- pg->count_info &= ~PGC_count_mask;
+ pg->u.sh.type = SH_type_p2m_table; /* p2m code reuses type-info */
+- page_set_owner(pg, NULL);
+
+ /* This is called both from the p2m code (which never holds the
+ * paging lock) and the log-dirty code (which always does). */
+@@ -3216,7 +3213,9 @@ int shadow_enable(struct domain *d, u32
+ | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER
+ | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
+ unmap_domain_page(e);
++ pg->count_info = 1;
+ pg->u.inuse.type_info = PGT_l2_page_table | 1 | PGT_validated;
++ page_set_owner(pg, d);
+ }
+
+ paging_lock(d);
+@@ -3254,7 +3253,11 @@ int shadow_enable(struct domain *d, u32
+ if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) )
+ p2m_teardown(p2m);
+ if ( rv != 0 && pg != NULL )
++ {
++ pg->count_info &= ~PGC_count_mask;
++ page_set_owner(pg, NULL);
+ shadow_free_p2m_page(d, pg);
++ }
+ domain_unpause(d);
+ return rv;
+ }
+@@ -3363,7 +3366,22 @@ out:
+
+ /* Must be called outside the lock */
+ if ( unpaged_pagetable )
++ {
++ if ( page_get_owner(unpaged_pagetable) == d &&
++ (unpaged_pagetable->count_info & PGC_count_mask) == 1 )
++ {
++ unpaged_pagetable->count_info &= ~PGC_count_mask;
++ page_set_owner(unpaged_pagetable, NULL);
++ }
++ /* Complain here in cases where shadow_free_p2m_page() won't. */
++ else if ( !page_get_owner(unpaged_pagetable) &&
++ !(unpaged_pagetable->count_info & PGC_count_mask) )
++ SHADOW_ERROR("d%d: Odd unpaged pt %"PRI_mfn" c=%lx t=%"PRtype_info"\n",
++ d->domain_id, mfn_x(page_to_mfn(unpaged_pagetable)),
++ unpaged_pagetable->count_info,
++ unpaged_pagetable->u.inuse.type_info);
+ shadow_free_p2m_page(d, unpaged_pagetable);
++ }
+ }
+
+ void shadow_final_teardown(struct domain *d)
Index: head/emulators/xen-kernel47/files/xsa249.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa249.patch
+++ head/emulators/xen-kernel47/files/xsa249.patch
@@ -0,0 +1,42 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/shadow: fix refcount overflow check
+
+Commit c385d27079 ("x86 shadow: for multi-page shadows, explicitly track
+the first page") reduced the refcount width to 25, without adjusting the
+overflow check. Eliminate the disconnect by using a manifest constant.
+
+Interestingly, up to commit 047782fa01 ("Out-of-sync L1 shadows: OOS
+snapshot") the refcount was 27 bits wide, yet the check was already
+using 26.
+
+This is XSA-249.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: George Dunlap <george.dunlap@citrix.com>
+Reviewed-by: Tim Deegan <tim@xen.org>
+---
+v2: Simplify expression back to the style it was.
+
+--- a/xen/arch/x86/mm/shadow/private.h
++++ b/xen/arch/x86/mm/shadow/private.h
+@@ -529,7 +529,7 @@ static inline int sh_get_ref(struct doma
+ x = sp->u.sh.count;
+ nx = x + 1;
+
+- if ( unlikely(nx >= 1U<<26) )
++ if ( unlikely(nx >= (1U << PAGE_SH_REFCOUNT_WIDTH)) )
+ {
+ SHADOW_PRINTK("shadow ref overflow, gmfn=%lx smfn=%lx\n",
+ __backpointer(sp), mfn_x(smfn));
+--- a/xen/include/asm-x86/mm.h
++++ b/xen/include/asm-x86/mm.h
+@@ -82,7 +82,8 @@ struct page_info
+ unsigned long type:5; /* What kind of shadow is this? */
+ unsigned long pinned:1; /* Is the shadow pinned? */
+ unsigned long head:1; /* Is this the first page of the shadow? */
+- unsigned long count:25; /* Reference count */
++#define PAGE_SH_REFCOUNT_WIDTH 25
++ unsigned long count:PAGE_SH_REFCOUNT_WIDTH; /* Reference count */
+ } sh;
+
+ /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
Index: head/emulators/xen-kernel47/files/xsa250.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa250.patch
+++ head/emulators/xen-kernel47/files/xsa250.patch
@@ -0,0 +1,67 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/shadow: fix ref-counting error handling
+
+The old-Linux handling in shadow_set_l4e() mistakenly ORed together the
+results of sh_get_ref() and sh_pin(). As the latter failing is not a
+correctness problem, simply ignore its return value.
+
+In sh_set_toplevel_shadow() a failing sh_get_ref() must not be
+accompanied by installing the entry, despite the domain being crashed.
+
+This is XSA-250.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Tim Deegan <tim@xen.org>
+
+--- a/xen/arch/x86/mm/shadow/multi.c
++++ b/xen/arch/x86/mm/shadow/multi.c
+@@ -923,7 +923,7 @@ static int shadow_set_l4e(struct domain
+ shadow_l4e_t new_sl4e,
+ mfn_t sl4mfn)
+ {
+- int flags = 0, ok;
++ int flags = 0;
+ shadow_l4e_t old_sl4e;
+ paddr_t paddr;
+ ASSERT(sl4e != NULL);
+@@ -938,15 +938,16 @@ static int shadow_set_l4e(struct domain
+ {
+ /* About to install a new reference */
+ mfn_t sl3mfn = shadow_l4e_get_mfn(new_sl4e);
+- ok = sh_get_ref(d, sl3mfn, paddr);
+- /* Are we pinning l3 shadows to handle wierd linux behaviour? */
+- if ( sh_type_is_pinnable(d, SH_type_l3_64_shadow) )
+- ok |= sh_pin(d, sl3mfn);
+- if ( !ok )
++
++ if ( !sh_get_ref(d, sl3mfn, paddr) )
+ {
+ domain_crash(d);
+ return SHADOW_SET_ERROR;
+ }
++
++ /* Are we pinning l3 shadows to handle weird Linux behaviour? */
++ if ( sh_type_is_pinnable(d, SH_type_l3_64_shadow) )
++ sh_pin(d, sl3mfn);
+ }
+
+ /* Write the new entry */
+@@ -3965,14 +3966,15 @@ sh_set_toplevel_shadow(struct vcpu *v,
+
+ /* Take a ref to this page: it will be released in sh_detach_old_tables()
+ * or the next call to set_toplevel_shadow() */
+- if ( !sh_get_ref(d, smfn, 0) )
++ if ( sh_get_ref(d, smfn, 0) )
++ new_entry = pagetable_from_mfn(smfn);
++ else
+ {
+ SHADOW_ERROR("can't install %#lx as toplevel shadow\n", mfn_x(smfn));
+ domain_crash(d);
++ new_entry = pagetable_null();
+ }
+
+- new_entry = pagetable_from_mfn(smfn);
+-
+ install_new_entry:
+ /* Done. Install it */
+ SHADOW_PRINTK("%u/%u [%u] gmfn %#"PRI_mfn" smfn %#"PRI_mfn"\n",
Index: head/emulators/xen-kernel47/files/xsa251-4.8.patch
===================================================================
--- head/emulators/xen-kernel47/files/xsa251-4.8.patch
+++ head/emulators/xen-kernel47/files/xsa251-4.8.patch
@@ -0,0 +1,21 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/paging: don't unconditionally BUG() on finding SHARED_M2P_ENTRY
+
+PV guests can fully control the values written into the P2M.
+
+This is XSA-251.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/mm/paging.c
++++ b/xen/arch/x86/mm/paging.c
+@@ -276,7 +276,7 @@ void paging_mark_pfn_dirty(struct domain
+ return;
+
+ /* Shared MFNs should NEVER be marked dirty */
+- BUG_ON(SHARED_M2P(pfn));
++ BUG_ON(paging_mode_translate(d) && SHARED_M2P(pfn));
+
+ /*
+ * Values with the MSB set denote MFNs that aren't really part of the
Index: head/emulators/xen-kernel47/pkg-descr
===================================================================
--- head/emulators/xen-kernel47/pkg-descr
+++ head/emulators/xen-kernel47/pkg-descr
@@ -0,0 +1,10 @@
+The Xen Project hypervisor is an open-source type-1 or baremetal hypervisor,
+which makes it possible to run many instances of an operating system or indeed
+different operating systems in parallel on a single machine (or host). The Xen
+Project hypervisor is the only type-1 hypervisor that is available as open
+source. It is used as the basis for a number of different commercial and open
+source applications, such as: server virtualization, Infrastructure as a Service
+(IaaS), desktop virtualization, security applications, embedded and hardware
+appliances
+
+WWW: http://www.xenproject.org/
Index: head/emulators/xen-kernel47/pkg-message
===================================================================
--- head/emulators/xen-kernel47/pkg-message
+++ head/emulators/xen-kernel47/pkg-message
@@ -0,0 +1,18 @@
+Please add the following entries in order to boot the xen kernel
+
+In /etc/sysctl.conf:
+ vm.max_wired=-1
+
+In /etc/ttys:
+ xc0 "/usr/libexec/getty Pc" xterm on secure
+
+In /boot/loader.conf for a dom0 with 2G memory and 4 vcpus:
+ hw.pci.mcfg=0
+ xen_kernel="/boot/xen"
+ xen_cmdline="dom0_mem=2048M dom0_max_vcpus=4 dom0pvh=1 com1=115200,8n1 guest_loglvl=all loglvl=all"
+
+Add to the above xen_cmdline in order to activate the serial console:
+ console=com1
+
+In /boot/menu.rc.local:
+ try-include /boot/xen.4th
Index: head/emulators/xen/Makefile
===================================================================
--- head/emulators/xen/Makefile
+++ head/emulators/xen/Makefile
@@ -1,20 +0,0 @@
-# $FreeBSD$
-
-PORTNAME= xen
-PORTVERSION= 4.7.0
-PORTREVISION= 2
-CATEGORIES= emulators
-
-MAINTAINER= royger@FreeBSD.org
-COMMENT= Xen Hypervisor meta port
-
-LICENSE= GPLv2
-
-ONLY_FOR_ARCHS= amd64
-
-RUN_DEPENDS= /boot/xen:emulators/xen-kernel \
- xl:sysutils/xen-tools
-
-USES= metaport
-
-.include <bsd.port.mk>
Index: head/emulators/xen/pkg-descr
===================================================================
--- head/emulators/xen/pkg-descr
+++ head/emulators/xen/pkg-descr
@@ -1,11 +0,0 @@
-The Xen Project hypervisor is an open-source type-1 or baremetal hypervisor,
-which makes it possible to run many instances of an operating system or indeed
-different operating systems in parallel on a single machine (or host). The Xen
-Project hypervisor is the only type-1 hypervisor that is available as open
-source. It is used as the basis for a number of different commercial and open
-source applications, such as: server virtualization, Infrastructure as a Service
-(IaaS), desktop virtualization, security applications, embedded and hardware
-appliances
-
-WWW: http://www.xenproject.org/
-
Index: head/sysutils/xen-tools/Makefile
===================================================================
--- head/sysutils/xen-tools/Makefile
+++ head/sysutils/xen-tools/Makefile
@@ -1,93 +0,0 @@
-# $FreeBSD$
-
-PORTNAME= xen
-PKGNAMESUFFIX= -tools
-PORTVERSION= 4.7.2
-PORTREVISION= 4
-CATEGORIES= sysutils emulators
-MASTER_SITES= http://downloads.xenproject.org/release/xen/${PORTVERSION}/
-
-MAINTAINER= royger@FreeBSD.org
-COMMENT= Xen management tool, based on LibXenlight
-
-LICENSE= GPLv2 LGPL3
-LICENSE_COMB= multi
-
-BROKEN_FreeBSD_10= does not build
-
-LIB_DEPENDS= libyajl.so:devel/yajl \
- liblzo2.so:archivers/lzo2 \
- libpixman-1.so:x11/pixman \
- libargp.so:devel/argp-standalone
-BUILD_DEPENDS= dev86>0:devel/dev86 \
- seabios>0:misc/seabios \
- markdown>0:textproc/markdown
-
-OPTIONS_DEFINE= DOCS
-
-ONLY_FOR_ARCHS= amd64
-ONLY_FOR_ARCHS_REASON= "not yet ported to anything other than amd64"
-
-USES= cpe gettext gmake libtool localbase:ldflags perl5 pkgconfig \
- python:2.7 shebangfix
-USE_GNOME= glib20
-USE_LDCONFIG= yes
-GNU_CONFIGURE= yes
-MAKE_ARGS= clang=y
-QEMU_ARGS= --disable-gtk \
- --disable-smartcard-nss \
- --disable-sdl \
- --disable-vte \
- --disable-curses \
- --disable-tools \
- --disable-curl \
- --cxx=c++
-
-EXTRA_PATCHES= ${FILESDIR}/var_paths.patch:-p1 \
- ${FILESDIR}/0001-libxl-fix-creation-of-pkgconf-install-dir.patch:-p1 \
- ${FILESDIR}/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch:-p1 \
- ${FILESDIR}/0001-libs-xenstore-set-correct-FreeBSD-device.patch:-p1 \
- ${FILESDIR}/kdd.patch:-p1 \
- ${FILESDIR}/0001-xenstored-apply-a-write-transaction-rate-limit.patch:-p1 \
- ${FILESDIR}/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch:-p1 \
- ${FILESDIR}/0001-Backport-of-commit-858dba.patch:-p1
-
-CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}" \
- --with-system-seabios=${LOCALBASE}/share/seabios/bios.bin
-
-# Disable bash and xgettext tests, they are not needed on FreeBSD.
-CONFIGURE_ENV+= ac_cv_path_BASH=${TRUE}
-
-SHEBANG_FILES= tools/misc/xen-ringwatch \
- tools/misc/xencov_split \
- tools/python/scripts/convert-legacy-stream \
- tools/python/scripts/verify-stream-v2 \
- tools/xenmon/xenmon.py
-
-ALL_TARGET= tools docs
-INSTALL_TARGET= install-tools install-docs
-
-.include <bsd.port.options.mk>
-
-.if ${OPSYS} != FreeBSD
-IGNORE= only supported on FreeBSD
-.endif
-
-post-patch:
- @${REINPLACE_CMD} "s,x86_64,amd64,g" ${WRKSRC}/tools/configure
- @${REINPLACE_CMD} -e "s,/var/lib,/var/db,g" \
- ${WRKSRC}/tools/Makefile \
- ${WRKSRC}/tools/libxc/include/xenguest.h \
- ${WRKSRC}/tools/libxl/libxl_dom.c \
- ${WRKSRC}/tools/libxl/libxl_dm.c \
- ${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \
- ${WRKSRC}/docs/man/*
- @for p in `ls ${FILESDIR}/*qemuu*.patch 2>/dev/null`; do \
- ${ECHO_CMD} "====> Applying $${p##*/}" ; \
- ${PATCH} -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \
- done
-
-post-install:
- ${MKDIR} ${STAGEDIR}/var/run/xen
-
-.include <bsd.port.mk>
Index: head/sysutils/xen-tools/distinfo
===================================================================
--- head/sysutils/xen-tools/distinfo
+++ head/sysutils/xen-tools/distinfo
@@ -1,3 +0,0 @@
-TIMESTAMP = 1489085975
-SHA256 (xen-4.7.2.tar.gz) = 61494a56d9251e2108080f95b0dc8e3d175f1ba4da34603fc07b91cfebf358d5
-SIZE (xen-4.7.2.tar.gz) = 20714281
Index: head/sysutils/xen-tools/files/0001-Backport-of-commit-858dba.patch
===================================================================
--- head/sysutils/xen-tools/files/0001-Backport-of-commit-858dba.patch
+++ head/sysutils/xen-tools/files/0001-Backport-of-commit-858dba.patch
@@ -1,35 +0,0 @@
-From 2ff6287610fa44eec9f30630d87166ad1fc0e452 Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Tue, 22 May 2018 17:47:37 +0200
-Subject: [PATCH] Backport of commit 858dba
-
-This is required in order to build Xen with newer iasl found in HEAD.
----
- tools/firmware/hvmloader/acpi/Makefile | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/tools/firmware/hvmloader/acpi/Makefile b/tools/firmware/hvmloader/acpi/Makefile
-index d3e882ac69..29f93e6a8c 100644
---- a/tools/firmware/hvmloader/acpi/Makefile
-+++ b/tools/firmware/hvmloader/acpi/Makefile
-@@ -27,7 +27,7 @@ all: acpi.a
-
- ssdt_s3.h ssdt_s4.h ssdt_pm.h ssdt_tpm.h: %.h: %.asl iasl
- iasl -vs -p $* -tc $<
-- sed -e 's/AmlCode/$*/g' $*.hex >$@
-+ sed -e 's/AmlCode/$*/g' -e 's/_aml_code//g' $*.hex >$@
- rm -f $*.hex $*.aml
-
- mk_dsdt: mk_dsdt.c
-@@ -44,7 +44,7 @@ dsdt_%cpu.asl: dsdt.asl mk_dsdt
-
- $(filter dsdt_%.c,$(C_SRC)): %.c: iasl %.asl
- iasl -vs -p $* -tc $*.asl
-- sed -e 's/AmlCode/$*/g' $*.hex >$@
-+ sed -e 's/AmlCode/$*/g' -e 's/_aml_code//g' $*.hex >$@
- echo "int $*_len=sizeof($*);" >>$@
- rm -f $*.aml $*.hex
-
---
-2.17.0
-
Index: head/sysutils/xen-tools/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
===================================================================
--- head/sysutils/xen-tools/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
+++ head/sysutils/xen-tools/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
@@ -1,32 +0,0 @@
-From 7ff99b232e0f91a5189f429498868bfccf8d7154 Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Mon, 12 Dec 2016 16:07:40 +0000
-Subject: [PATCH] libs/xenstore: set correct FreeBSD device
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The path to the xenstore FreeBSD device is /dev/xen/xenstore.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Acked-by: Wei Liu <wei.liu2@citrix.com>
----
- tools/xenstore/xs_lib.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/tools/xenstore/xs_lib.c b/tools/xenstore/xs_lib.c
-index 5ef3d6d..3e43f88 100644
---- a/tools/xenstore/xs_lib.c
-+++ b/tools/xenstore/xs_lib.c
-@@ -85,6 +85,8 @@ const char *xs_domain_dev(void)
- return "/proc/xen/xenbus";
- #elif defined(__NetBSD__)
- return "/kern/xen/xenbus";
-+#elif defined(__FreeBSD__)
-+ return "/dev/xen/xenstore";
- #else
- return "/dev/xen/xenbus";
- #endif
---
-2.10.1 (Apple Git-78)
-
Index: head/sysutils/xen-tools/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
===================================================================
--- head/sysutils/xen-tools/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
+++ head/sysutils/xen-tools/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
@@ -1,35 +0,0 @@
-From 45434adc3c94f5229744beaa12028aa23f63b9e7 Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Wed, 23 Nov 2016 16:56:39 +0000
-Subject: [PATCH] libxl: fix creation of pkgconf install dir
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When PKG_INSTALLDIR was introduced the creation of the previous pkgconf install
-directory was not changed. Fix this by correctly using PKG_INSTALLDIR for the
-directory creation in libxl Makefile.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Acked-by: Wei Liu <wei.liu2@citrix.com>
-Release-acked-by: Wei Liu <wei.liu2@citrix.com>
----
- tools/libxl/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
-index f5053a0..ef01785 100644
---- a/tools/libxl/Makefile
-+++ b/tools/libxl/Makefile
-@@ -308,7 +308,7 @@ install: all
- $(INSTALL_DIR) $(DESTDIR)$(includedir)
- $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
-- $(INSTALL_DIR) $(DESTDIR)$(SHAREDIR)/pkgconfig
-+ $(INSTALL_DIR) $(DESTDIR)$(PKG_INSTALLDIR)
- $(INSTALL_PROG) xl $(DESTDIR)$(sbindir)
- $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(LIBEXEC_BIN)
- $(INSTALL_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
---
-2.9.3 (Apple Git-75)
-
Index: head/sysutils/xen-tools/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
===================================================================
--- head/sysutils/xen-tools/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
+++ head/sysutils/xen-tools/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
@@ -1,66 +0,0 @@
-From 4000a7c7d7b0e01837abd3918e393f289c07d68c Mon Sep 17 00:00:00 2001
-From: Roger Pau Monne <roger.pau@citrix.com>
-Date: Tue, 25 Oct 2016 11:53:28 +0200
-Subject: [PATCH] tools/configure: fix pkg-config install path for FreeBSD
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-pkg-config from FreeBSD ports doesn't have ${prefix}/share/pkgconfig in the
-default search path, fix this by having a PKG_INSTALLDIR variable that can
-be changed on a per-OS basis.
-
-It would be best to use PKG_INSTALLDIR as defined by the pkg.m4 macro, but
-sadly this also reports a wrong value on FreeBSD (${libdir}/pkgconfig, which
-expands to /usr/local/lib/pkgconfig by default, and is also _not_ part of
-the default pkg-config search path).
-
-This patch should not change the behavior for Linux installs.
-
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Reported-by: Alexander Nusov <alexander.nusov@nfvexpress.com>
-Acked-by: Wei Liu <wei.liu2@citrix.com>
-Release-acked-by: Wei Liu <wei.liu2@citrix.com>
----
- config/FreeBSD.mk | 1 +
- config/Paths.mk.in | 2 ++
- tools/libxl/Makefile | 4 ++--
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
-index bb3a5d0..afeaefb 100644
---- a/config/FreeBSD.mk
-+++ b/config/FreeBSD.mk
-@@ -2,3 +2,4 @@ include $(XEN_ROOT)/config/StdGNU.mk
-
- # No wget on FreeBSD base system
- WGET = ftp
-+PKG_INSTALLDIR = ${prefix}/libdata/pkgconfig
-diff --git a/config/Paths.mk.in b/config/Paths.mk.in
-index 62cea48..a603295 100644
---- a/config/Paths.mk.in
-+++ b/config/Paths.mk.in
-@@ -56,3 +56,5 @@ XENFIRMWAREDIR := @XENFIRMWAREDIR@
-
- XEN_CONFIG_DIR := @XEN_CONFIG_DIR@
- XEN_SCRIPT_DIR := @XEN_SCRIPT_DIR@
-+
-+PKG_INSTALLDIR := ${SHAREDIR}/pkgconfig
-diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
-index 79e4019..af0a3ad 100644
---- a/tools/libxl/Makefile
-+++ b/tools/libxl/Makefile
-@@ -320,8 +320,8 @@ install: all
- $(INSTALL_DATA) libxlutil.a $(DESTDIR)$(libdir)
- $(INSTALL_DATA) libxl.h libxl_event.h libxl_json.h _libxl_types.h _libxl_types_json.h _libxl_list.h libxl_utils.h libxl_uuid.h libxlutil.h $(DESTDIR)$(includedir)
- $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
-- $(INSTALL_DATA) xenlight.pc $(DESTDIR)$(SHAREDIR)/pkgconfig/
-- $(INSTALL_DATA) xlutil.pc $(DESTDIR)$(SHAREDIR)/pkgconfig/
-+ $(INSTALL_DATA) xenlight.pc $(DESTDIR)$(PKG_INSTALLDIR)
-+ $(INSTALL_DATA) xlutil.pc $(DESTDIR)$(PKG_INSTALLDIR)
-
- .PHONY: clean
- clean:
---
-2.9.3 (Apple Git-75)
-
Index: head/sysutils/xen-tools/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
===================================================================
--- head/sysutils/xen-tools/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
+++ head/sysutils/xen-tools/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
@@ -1,456 +0,0 @@
-From bfe42a836450591bb41f4f6393c42dbb0d72abb9 Mon Sep 17 00:00:00 2001
-From: Ian Jackson <ian.jackson@eu.citrix.com>
-Date: Sat, 18 Mar 2017 16:12:26 +0000
-Subject: [PATCH 01/15] xenstored: apply a write transaction rate limit
-
-This avoids a rogue client being about to stall another client (eg the
-toolstack) indefinitely.
-
-This is XSA-206.
-
-Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
-
-Backported to 4.8 (not entirely trivial).
-
-Reported-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: George Dunlap <george.dunlap@citrix.com>
-Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
----
- tools/xenstore/Makefile | 3 +-
- tools/xenstore/xenstored_core.c | 9 ++
- tools/xenstore/xenstored_core.h | 6 +
- tools/xenstore/xenstored_domain.c | 215 +++++++++++++++++++++++++++++++++
- tools/xenstore/xenstored_domain.h | 25 ++++
- tools/xenstore/xenstored_transaction.c | 5 +
- 6 files changed, 262 insertions(+), 1 deletion(-)
-
-diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
-index d691b78..b458729 100644
---- a/tools/xenstore/Makefile
-+++ b/tools/xenstore/Makefile
-@@ -31,6 +31,7 @@ XENSTORED_OBJS_$(CONFIG_FreeBSD) = xenstored_posix.o
- XENSTORED_OBJS_$(CONFIG_MiniOS) = xenstored_minios.o
-
- XENSTORED_OBJS += $(XENSTORED_OBJS_y)
-+LDLIBS_xenstored += -lrt
-
- ifneq ($(XENSTORE_STATIC_CLIENTS),y)
- LIBXENSTORE := libxenstore.so
-@@ -72,7 +73,7 @@ endif
- $(XENSTORED_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
-
- xenstored: $(XENSTORED_OBJS)
-- $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
-+ $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxenctrl) $(LDLIBS_xenstored) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
-
- xenstored.a: $(XENSTORED_OBJS)
- $(AR) cr $@ $^
-diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
-index 51fb0b3..1aabc93 100644
---- a/tools/xenstore/xenstored_core.c
-+++ b/tools/xenstore/xenstored_core.c
-@@ -357,6 +357,7 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
- int *ptimeout)
- {
- struct connection *conn;
-+ struct wrl_timestampt now;
-
- if (fds)
- memset(fds, 0, sizeof(struct pollfd) * current_array_size);
-@@ -376,8 +377,11 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
- xce_pollfd_idx = set_fd(xenevtchn_fd(xce_handle),
- POLLIN|POLLPRI);
-
-+ wrl_gettime_now(&now);
-+
- list_for_each_entry(conn, &connections, list) {
- if (conn->domain) {
-+ wrl_check_timeout(conn->domain, now, ptimeout);
- if (domain_can_read(conn) ||
- (domain_can_write(conn) &&
- !list_empty(&conn->out_list)))
-@@ -810,6 +814,7 @@ static void delete_node_single(struct connection *conn, struct node *node)
- corrupt(conn, "Could not delete '%s'", node->name);
- return;
- }
-+
- domain_entry_dec(conn, node);
- }
-
-@@ -949,6 +954,7 @@ static void do_write(struct connection *conn, struct buffered_data *in)
- }
-
- add_change_node(conn->transaction, name, false);
-+ wrl_apply_debit_direct(conn);
- fire_watches(conn, name, false);
- send_ack(conn, XS_WRITE);
- }
-@@ -973,6 +979,7 @@ static void do_mkdir(struct connection *conn, const char *name)
- return;
- }
- add_change_node(conn->transaction, name, false);
-+ wrl_apply_debit_direct(conn);
- fire_watches(conn, name, false);
- }
- send_ack(conn, XS_MKDIR);
-@@ -1098,6 +1105,7 @@ static void do_rm(struct connection *conn, const char *name)
-
- if (_rm(conn, node, name)) {
- add_change_node(conn->transaction, name, true);
-+ wrl_apply_debit_direct(conn);
- fire_watches(conn, name, true);
- send_ack(conn, XS_RM);
- }
-@@ -1173,6 +1181,7 @@ static void do_set_perms(struct connection *conn, struct buffered_data *in)
- }
-
- add_change_node(conn->transaction, name, false);
-+ wrl_apply_debit_direct(conn);
- fire_watches(conn, name, false);
- send_ack(conn, XS_SET_PERMS);
- }
-diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
-index 3a497f7..a2a3427 100644
---- a/tools/xenstore/xenstored_core.h
-+++ b/tools/xenstore/xenstored_core.h
-@@ -33,6 +33,12 @@
- #include "list.h"
- #include "tdb.h"
-
-+#define MIN(a, b) (((a) < (b))? (a) : (b))
-+
-+typedef int32_t wrl_creditt;
-+#define WRL_CREDIT_MAX (1000*1000*1000)
-+/* ^ satisfies non-overflow condition for wrl_xfer_credit */
-+
- struct buffered_data
- {
- struct list_head list;
-diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
-index 47b4f03..486c96f 100644
---- a/tools/xenstore/xenstored_domain.c
-+++ b/tools/xenstore/xenstored_domain.c
-@@ -21,6 +21,7 @@
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdarg.h>
-+#include <time.h>
-
- #include "utils.h"
- #include "talloc.h"
-@@ -74,6 +75,10 @@ struct domain
-
- /* number of watch for this domain */
- int nbwatch;
-+
-+ /* write rate limit */
-+ wrl_creditt wrl_credit; /* [ -wrl_config_writecost, +_dburst ] */
-+ struct wrl_timestampt wrl_timestamp;
- };
-
- static LIST_HEAD(domains);
-@@ -206,6 +211,8 @@ static int destroy_domain(void *_domain)
-
- fire_watches(NULL, "@releaseDomain", false);
-
-+ wrl_domain_destroy(domain);
-+
- return 0;
- }
-
-@@ -253,6 +260,9 @@ void handle_event(void)
- bool domain_can_read(struct connection *conn)
- {
- struct xenstore_domain_interface *intf = conn->domain->interface;
-+
-+ if (domain_is_unprivileged(conn) && conn->domain->wrl_credit < 0)
-+ return false;
- return (intf->req_cons != intf->req_prod);
- }
-
-@@ -284,6 +294,8 @@ static struct domain *new_domain(void *context, unsigned int domid,
- domain->domid = domid;
- domain->path = talloc_domain_path(domain, domid);
-
-+ wrl_domain_new(domain);
-+
- list_add(&domain->list, &domains);
- talloc_set_destructor(domain, destroy_domain);
-
-@@ -747,6 +759,209 @@ int domain_watch(struct connection *conn)
- : 0;
- }
-
-+static wrl_creditt wrl_config_writecost = WRL_FACTOR;
-+static wrl_creditt wrl_config_rate = WRL_RATE * WRL_FACTOR;
-+static wrl_creditt wrl_config_dburst = WRL_DBURST * WRL_FACTOR;
-+static wrl_creditt wrl_config_gburst = WRL_GBURST * WRL_FACTOR;
-+static wrl_creditt wrl_config_newdoms_dburst =
-+ WRL_DBURST * WRL_NEWDOMS * WRL_FACTOR;
-+
-+long wrl_ntransactions;
-+
-+static long wrl_ndomains;
-+static wrl_creditt wrl_reserve; /* [-wrl_config_newdoms_dburst, +_gburst ] */
-+
-+void wrl_gettime_now(struct wrl_timestampt *now_wt)
-+{
-+ struct timespec now_ts;
-+ int r;
-+
-+ r = clock_gettime(CLOCK_MONOTONIC, &now_ts);
-+ if (r)
-+ barf_perror("Could not find time (clock_gettime failed)");
-+
-+ now_wt->sec = now_ts.tv_sec;
-+ now_wt->msec = now_ts.tv_nsec / 1000000;
-+}
-+
-+static void wrl_xfer_credit(wrl_creditt *debit, wrl_creditt debit_floor,
-+ wrl_creditt *credit, wrl_creditt credit_ceil)
-+ /*
-+ * Transfers zero or more credit from "debit" to "credit".
-+ * Transfers as much as possible while maintaining
-+ * debit >= debit_floor and credit <= credit_ceil.
-+ * (If that's violated already, does nothing.)
-+ *
-+ * Sufficient conditions to avoid overflow, either of:
-+ * |every argument| <= 0x3fffffff
-+ * |every argument| <= 1E9
-+ * |every argument| <= WRL_CREDIT_MAX
-+ * (And this condition is preserved.)
-+ */
-+{
-+ wrl_creditt xfer = MIN( *debit - debit_floor,
-+ credit_ceil - *credit );
-+ if (xfer > 0) {
-+ *debit -= xfer;
-+ *credit += xfer;
-+ }
-+}
-+
-+void wrl_domain_new(struct domain *domain)
-+{
-+ domain->wrl_credit = 0;
-+ wrl_gettime_now(&domain->wrl_timestamp);
-+ wrl_ndomains++;
-+ /* Steal up to DBURST from the reserve */
-+ wrl_xfer_credit(&wrl_reserve, -wrl_config_newdoms_dburst,
-+ &domain->wrl_credit, wrl_config_dburst);
-+}
-+
-+void wrl_domain_destroy(struct domain *domain)
-+{
-+ wrl_ndomains--;
-+ /*
-+ * Don't bother recalculating domain's credit - this just
-+ * means we don't give the reserve the ending domain's credit
-+ * for time elapsed since last update.
-+ */
-+ wrl_xfer_credit(&domain->wrl_credit, 0,
-+ &wrl_reserve, wrl_config_dburst);
-+}
-+
-+void wrl_credit_update(struct domain *domain, struct wrl_timestampt now)
-+{
-+ /*
-+ * We want to calculate
-+ * credit += (now - timestamp) * RATE / ndoms;
-+ * But we want it to saturate, and to avoid floating point.
-+ * To avoid rounding errors from constantly adding small
-+ * amounts of credit, we only add credit for whole milliseconds.
-+ */
-+ long seconds = now.sec - domain->wrl_timestamp.sec;
-+ long milliseconds = now.msec - domain->wrl_timestamp.msec;
-+ long msec;
-+ int64_t denom, num;
-+ wrl_creditt surplus;
-+
-+ seconds = MIN(seconds, 1000*1000); /* arbitrary, prevents overflow */
-+ msec = seconds * 1000 + milliseconds;
-+
-+ if (msec < 0)
-+ /* shouldn't happen with CLOCK_MONOTONIC */
-+ msec = 0;
-+
-+ /* 32x32 -> 64 cannot overflow */
-+ denom = (int64_t)msec * wrl_config_rate;
-+ num = (int64_t)wrl_ndomains * 1000;
-+ /* denom / num <= 1E6 * wrl_config_rate, so with
-+ reasonable wrl_config_rate, denom / num << 2^64 */
-+
-+ /* at last! */
-+ domain->wrl_credit = MIN( (int64_t)domain->wrl_credit + denom / num,
-+ WRL_CREDIT_MAX );
-+ /* (maybe briefly violating the DBURST cap on wrl_credit) */
-+
-+ /* maybe take from the reserve to make us nonnegative */
-+ wrl_xfer_credit(&wrl_reserve, 0,
-+ &domain->wrl_credit, 0);
-+
-+ /* return any surplus (over DBURST) to the reserve */
-+ surplus = 0;
-+ wrl_xfer_credit(&domain->wrl_credit, wrl_config_dburst,
-+ &surplus, WRL_CREDIT_MAX);
-+ wrl_xfer_credit(&surplus, 0,
-+ &wrl_reserve, wrl_config_gburst);
-+ /* surplus is now implicitly discarded */
-+
-+ domain->wrl_timestamp = now;
-+
-+ trace("wrl: dom %4d %6ld msec %9ld credit %9ld reserve"
-+ " %9ld discard\n",
-+ domain->domid,
-+ msec,
-+ (long)domain->wrl_credit, (long)wrl_reserve,
-+ (long)surplus);
-+}
-+
-+void wrl_check_timeout(struct domain *domain,
-+ struct wrl_timestampt now,
-+ int *ptimeout)
-+{
-+ uint64_t num, denom;
-+ int wakeup;
-+
-+ wrl_credit_update(domain, now);
-+
-+ if (domain->wrl_credit >= 0)
-+ /* not blocked */
-+ return;
-+
-+ if (!*ptimeout)
-+ /* already decided on immediate wakeup,
-+ so no need to calculate our timeout */
-+ return;
-+
-+ /* calculate wakeup = now + -credit / (RATE / ndoms); */
-+
-+ /* credit cannot go more -ve than one transaction,
-+ * so the first multiplication cannot overflow even 32-bit */
-+ num = (uint64_t)(-domain->wrl_credit * 1000) * wrl_ndomains;
-+ denom = wrl_config_rate;
-+
-+ wakeup = MIN( num / denom /* uint64_t */, INT_MAX );
-+ if (*ptimeout==-1 || wakeup < *ptimeout)
-+ *ptimeout = wakeup;
-+
-+ trace("wrl: domain %u credit=%ld (reserve=%ld) SLEEPING for %d\n",
-+ domain->domid,
-+ (long)domain->wrl_credit, (long)wrl_reserve,
-+ wakeup);
-+}
-+
-+void wrl_apply_debit_actual(struct domain *domain)
-+{
-+ struct wrl_timestampt now;
-+
-+ if (!domain)
-+ /* sockets escape the write rate limit */
-+ return;
-+
-+ wrl_gettime_now(&now);
-+ wrl_credit_update(domain, now);
-+
-+ domain->wrl_credit -= wrl_config_writecost;
-+ trace("wrl: domain %u credit=%ld (reserve=%ld)\n",
-+ domain->domid,
-+ (long)domain->wrl_credit, (long)wrl_reserve);
-+}
-+
-+void wrl_apply_debit_direct(struct connection *conn)
-+{
-+ if (!conn)
-+ /* some writes are generated internally */
-+ return;
-+
-+ if (conn->transaction)
-+ /* these are accounted for when the transaction ends */
-+ return;
-+
-+ if (!wrl_ntransactions)
-+ /* we don't conflict with anyone */
-+ return;
-+
-+ wrl_apply_debit_actual(conn->domain);
-+}
-+
-+void wrl_apply_debit_trans_commit(struct connection *conn)
-+{
-+ if (wrl_ntransactions <= 1)
-+ /* our own transaction appears in the counter */
-+ return;
-+
-+ wrl_apply_debit_actual(conn->domain);
-+}
-+
- /*
- * Local variables:
- * c-file-style: "linux"
-diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
-index 83488ed..bdc4044 100644
---- a/tools/xenstore/xenstored_domain.h
-+++ b/tools/xenstore/xenstored_domain.h
-@@ -65,4 +65,29 @@ void domain_watch_inc(struct connection *conn);
- void domain_watch_dec(struct connection *conn);
- int domain_watch(struct connection *conn);
-
-+/* Write rate limiting */
-+
-+#define WRL_FACTOR 1000 /* for fixed-point arithmetic */
-+#define WRL_RATE 200
-+#define WRL_DBURST 10
-+#define WRL_GBURST 1000
-+#define WRL_NEWDOMS 5
-+
-+struct wrl_timestampt {
-+ time_t sec;
-+ int msec;
-+};
-+
-+extern long wrl_ntransactions;
-+
-+void wrl_gettime_now(struct wrl_timestampt *now_ts);
-+void wrl_domain_new(struct domain *domain);
-+void wrl_domain_destroy(struct domain *domain);
-+void wrl_credit_update(struct domain *domain, struct wrl_timestampt now);
-+void wrl_check_timeout(struct domain *domain,
-+ struct wrl_timestampt now,
-+ int *ptimeout);
-+void wrl_apply_debit_direct(struct connection *conn);
-+void wrl_apply_debit_trans_commit(struct connection *conn);
-+
- #endif /* _XENSTORED_DOMAIN_H */
-diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c
-index d0e4739..a4b328f 100644
---- a/tools/xenstore/xenstored_transaction.c
-+++ b/tools/xenstore/xenstored_transaction.c
-@@ -116,6 +116,7 @@ static int destroy_transaction(void *_transaction)
- {
- struct transaction *trans = _transaction;
-
-+ wrl_ntransactions--;
- trace_destroy(trans, "transaction");
- if (trans->tdb)
- tdb_close(trans->tdb);
-@@ -179,6 +180,7 @@ void do_transaction_start(struct connection *conn, struct buffered_data *in)
- talloc_steal(conn, trans);
- talloc_set_destructor(trans, destroy_transaction);
- conn->transaction_started++;
-+ wrl_ntransactions++;
-
- snprintf(id_str, sizeof(id_str), "%u", trans->id);
- send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1);
-@@ -213,6 +215,9 @@ void do_transaction_end(struct connection *conn, const char *arg)
- send_error(conn, EAGAIN);
- return;
- }
-+
-+ wrl_apply_debit_trans_commit(conn);
-+
- if (!replace_tdb(trans->tdb_name, trans->tdb)) {
- send_error(conn, errno);
- return;
---
-2.1.4
-
Index: head/sysutils/xen-tools/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
===================================================================
--- head/sysutils/xen-tools/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
+++ head/sysutils/xen-tools/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
@@ -1,113 +0,0 @@
-From 1d713bf29548ee3e48c3170bafe2863d17694e90 Mon Sep 17 00:00:00 2001
-From: Ian Jackson <ian.jackson@eu.citrix.com>
-Date: Sat, 18 Mar 2017 16:39:31 +0000
-Subject: [PATCH 02/15] xenstored: Log when the write transaction rate limit
- bites
-
-Reported-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
----
- tools/xenstore/xenstored_core.c | 1 +
- tools/xenstore/xenstored_domain.c | 25 +++++++++++++++++++++++++
- tools/xenstore/xenstored_domain.h | 2 ++
- 3 files changed, 28 insertions(+)
-
-diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
-index 1aabc93..907b44f 100644
---- a/tools/xenstore/xenstored_core.c
-+++ b/tools/xenstore/xenstored_core.c
-@@ -378,6 +378,7 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
- POLLIN|POLLPRI);
-
- wrl_gettime_now(&now);
-+ wrl_log_periodic(now);
-
- list_for_each_entry(conn, &connections, list) {
- if (conn->domain) {
-diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
-index 486c96f..75cfad1 100644
---- a/tools/xenstore/xenstored_domain.c
-+++ b/tools/xenstore/xenstored_domain.c
-@@ -22,6 +22,7 @@
- #include <stdlib.h>
- #include <stdarg.h>
- #include <time.h>
-+#include <syslog.h>
-
- #include "utils.h"
- #include "talloc.h"
-@@ -79,6 +80,7 @@ struct domain
- /* write rate limit */
- wrl_creditt wrl_credit; /* [ -wrl_config_writecost, +_dburst ] */
- struct wrl_timestampt wrl_timestamp;
-+ bool wrl_delay_logged;
- };
-
- static LIST_HEAD(domains);
-@@ -770,6 +772,7 @@ long wrl_ntransactions;
-
- static long wrl_ndomains;
- static wrl_creditt wrl_reserve; /* [-wrl_config_newdoms_dburst, +_gburst ] */
-+static time_t wrl_log_last_warning; /* 0: no previous warning */
-
- void wrl_gettime_now(struct wrl_timestampt *now_wt)
- {
-@@ -919,6 +922,9 @@ void wrl_check_timeout(struct domain *domain,
- wakeup);
- }
-
-+#define WRL_LOG(now, ...) \
-+ (syslog(LOG_WARNING, "write rate limit: " __VA_ARGS__))
-+
- void wrl_apply_debit_actual(struct domain *domain)
- {
- struct wrl_timestampt now;
-@@ -934,6 +940,25 @@ void wrl_apply_debit_actual(struct domain *domain)
- trace("wrl: domain %u credit=%ld (reserve=%ld)\n",
- domain->domid,
- (long)domain->wrl_credit, (long)wrl_reserve);
-+
-+ if (domain->wrl_credit < 0) {
-+ if (!domain->wrl_delay_logged++) {
-+ WRL_LOG(now, "domain %ld is affected",
-+ (long)domain->domid);
-+ } else if (!wrl_log_last_warning) {
-+ WRL_LOG(now, "rate limiting restarts");
-+ }
-+ wrl_log_last_warning = now.sec;
-+ }
-+}
-+
-+void wrl_log_periodic(struct wrl_timestampt now)
-+{
-+ if (wrl_log_last_warning &&
-+ (now.sec - wrl_log_last_warning) > WRL_LOGEVERY) {
-+ WRL_LOG(now, "not in force recently");
-+ wrl_log_last_warning = 0;
-+ }
- }
-
- void wrl_apply_debit_direct(struct connection *conn)
-diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
-index bdc4044..2b963ed 100644
---- a/tools/xenstore/xenstored_domain.h
-+++ b/tools/xenstore/xenstored_domain.h
-@@ -72,6 +72,7 @@ int domain_watch(struct connection *conn);
- #define WRL_DBURST 10
- #define WRL_GBURST 1000
- #define WRL_NEWDOMS 5
-+#define WRL_LOGEVERY 120 /* seconds */
-
- struct wrl_timestampt {
- time_t sec;
-@@ -87,6 +88,7 @@ void wrl_credit_update(struct domain *domain, struct wrl_timestampt now);
- void wrl_check_timeout(struct domain *domain,
- struct wrl_timestampt now,
- int *ptimeout);
-+void wrl_log_periodic(struct wrl_timestampt now);
- void wrl_apply_debit_direct(struct connection *conn);
- void wrl_apply_debit_trans_commit(struct connection *conn);
-
---
-2.1.4
-
Index: head/sysutils/xen-tools/files/iasl-qemuu.patch
===================================================================
--- head/sysutils/xen-tools/files/iasl-qemuu.patch
+++ head/sysutils/xen-tools/files/iasl-qemuu.patch
@@ -1,26 +0,0 @@
-diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
-index a2d84ecf8f..e86d3eb263 100644
---- a/hw/i386/acpi-dsdt.dsl
-+++ b/hw/i386/acpi-dsdt.dsl
-@@ -62,8 +62,6 @@ DefinitionBlock (
-
- Scope(\_SB.PCI0) {
-
-- External(ISA, DeviceObj)
--
- Device(ISA) {
- Name(_ADR, 0x00010000)
-
-diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
-index 16eaca3fae..44fa4a9c0c 100644
---- a/hw/i386/q35-acpi-dsdt.dsl
-+++ b/hw/i386/q35-acpi-dsdt.dsl
-@@ -55,8 +55,6 @@ DefinitionBlock (
- Name(_ADR, 0x00)
- Name(_UID, 1)
-
-- External(ISA, DeviceObj)
--
- // _OSC: based on sample of ACPI3.0b spec
- Name(SUPP, 0) // PCI _OSC Support Field value
- Name(CTRL, 0) // PCI _OSC Control Field value
Index: head/sysutils/xen-tools/files/kdd.patch
===================================================================
--- head/sysutils/xen-tools/files/kdd.patch
+++ head/sysutils/xen-tools/files/kdd.patch
@@ -1,36 +0,0 @@
-Subject: [PATCH] tools/kdd: don't use a pointer to an unaligned field.
-
-The 'val' field in the packet is byte-aligned (because it is part of a
-packed struct), but the pointer argument to kdd_rdmsr() has the normal
-alignment constraints for a uint64_t *. Use a local variable to make sure
-the passed pointer has the correct alignment.
-
-Reported-by: Roger Pau Monné <roger.pau@citrix.com>
-Signed-off-by: Tim Deegan <tim@xen.org>
----
- tools/debugger/kdd/kdd.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/debugger/kdd/kdd.c b/tools/debugger/kdd/kdd.c
-index 70f007e..1bd5dd5 100644
---- a/tools/debugger/kdd/kdd.c
-+++ b/tools/debugger/kdd/kdd.c
-@@ -710,11 +710,13 @@ static void kdd_handle_read_ctrl(kdd_state *s)
- static void kdd_handle_read_msr(kdd_state *s)
- {
- uint32_t msr = s->rxp.cmd.msr.msr;
-+ uint64_t val;
- int ok;
- KDD_LOG(s, "Read MSR 0x%"PRIx32"\n", msr);
-
-- ok = (kdd_rdmsr(s->guest, s->cpuid, msr, &s->txp.cmd.msr.val) == 0);
-+ ok = (kdd_rdmsr(s->guest, s->cpuid, msr, &val) == 0);
- s->txp.cmd.msr.msr = msr;
-+ s->txp.cmd.msr.val = val;
- s->txp.cmd.msr.status = (ok ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE);
- kdd_send_cmd(s, KDD_CMD_READ_MSR, 0);
- }
---
-2.7.4
-
-
Index: head/sysutils/xen-tools/files/var_paths.patch
===================================================================
--- head/sysutils/xen-tools/files/var_paths.patch
+++ head/sysutils/xen-tools/files/var_paths.patch
@@ -1,13 +0,0 @@
-diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
-index bb3a5d0..b072030 100644
---- a/config/FreeBSD.mk
-+++ b/config/FreeBSD.mk
-@@ -2,3 +2,8 @@ include $(XEN_ROOT)/config/StdGNU.mk
-
- # No wget on FreeBSD base system
- WGET = ftp
-+
-+XEN_LIB_STORED := ${localstatedir}/db/xenstored
-+XEN_LOCK_DIR := ${localstatedir}/db
-+XEN_PAGING_DIR := ${localstatedir}/db/xen/xenpaging
-+XEN_DUMP_DIR := ${localstatedir}/crash/xen
Index: head/sysutils/xen-tools/files/xsa211-qemuu-4.7.patch
===================================================================
--- head/sysutils/xen-tools/files/xsa211-qemuu-4.7.patch
+++ head/sysutils/xen-tools/files/xsa211-qemuu-4.7.patch
@@ -1,259 +0,0 @@
-From 9de536fbc2be97ae887560f08f0fd824efa3d5db Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Tue, 14 Feb 2017 19:09:59 +0100
-Subject: [PATCH] cirrus/vnc: zap bitblit support from console code.
-
-There is a special code path (dpy_gfx_copy) to allow graphic emulation
-notify user interface code about bitblit operations carryed out by
-guests. It is supported by cirrus and vnc server. The intended purpose
-is to optimize display scrolls and just send over the scroll op instead
-of a full display update.
-
-This is rarely used these days though because modern guests simply don't
-use the cirrus blitter any more. Any linux guest using the cirrus drm
-driver doesn't. Any windows guest newer than winxp doesn't ship with a
-cirrus driver any more and thus uses the cirrus as simple framebuffer.
-
-So this code tends to bitrot and bugs can go unnoticed for a long time.
-See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
-which fixes a bug lingering in the code for almost a year, added by
-commit "c7628bf vnc: only alloc server surface with clients connected".
-
-Also the vnc server will throttle the frame rate in case it figures the
-network can't keep up (send buffers are full). This doesn't work with
-dpy_gfx_copy, for any copy operation sent to the vnc client we have to
-send all outstanding updates beforehand, otherwise the vnc client might
-run the client side blit on outdated data and thereby corrupt the
-display. So this dpy_gfx_copy "optimization" might even make things
-worse on slow network links.
-
-Lets kill it once for all.
-
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
----
- hw/display/cirrus_vga.c | 12 ++-----
- include/ui/console.h | 7 ----
- ui/console.c | 28 ---------------
- ui/vnc.c | 91 -------------------------------------------------
- 4 files changed, 3 insertions(+), 135 deletions(-)
-
-diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
-index 5901250..2841676 100644
---- a/hw/display/cirrus_vga.c
-+++ b/hw/display/cirrus_vga.c
-@@ -758,11 +758,6 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
- }
- }
-
-- /* we have to flush all pending changes so that the copy
-- is generated at the appropriate moment in time */
-- if (notify)
-- graphic_hw_update(s->vga.con);
--
- (*s->cirrus_rop) (s, s->vga.vram_ptr +
- (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
- s->vga.vram_ptr +
-@@ -771,10 +766,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
- s->cirrus_blt_width, s->cirrus_blt_height);
-
- if (notify) {
-- qemu_console_copy(s->vga.con,
-- sx, sy, dx, dy,
-- s->cirrus_blt_width / depth,
-- s->cirrus_blt_height);
-+ dpy_gfx_update(s->vga.con, dx, dy,
-+ s->cirrus_blt_width / depth,
-+ s->cirrus_blt_height);
- }
-
- /* we don't have to notify the display that this portion has
-diff --git a/include/ui/console.h b/include/ui/console.h
-index 047a2b4..ed07065 100644
---- a/include/ui/console.h
-+++ b/include/ui/console.h
-@@ -166,9 +166,6 @@ typedef struct DisplayChangeListenerOps {
- int x, int y, int w, int h);
- void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
- struct DisplaySurface *new_surface);
-- void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
-- int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h);
- bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl,
- pixman_format_code_t format);
-
-@@ -233,8 +230,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info);
- void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
- void dpy_gfx_replace_surface(QemuConsole *con,
- DisplaySurface *surface);
--void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h);
- void dpy_text_cursor(QemuConsole *con, int x, int y);
- void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
- void dpy_text_resize(QemuConsole *con, int w, int h);
-@@ -329,8 +324,6 @@ void text_consoles_set_display(DisplayState *ds);
- void console_select(unsigned int index);
- void console_color_init(DisplayState *ds);
- void qemu_console_resize(QemuConsole *con, int width, int height);
--void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h);
- DisplaySurface *qemu_console_surface(QemuConsole *con);
-
- /* console-gl.c */
-diff --git a/ui/console.c b/ui/console.c
-index 75fc492..72d91cb 100644
---- a/ui/console.c
-+++ b/ui/console.c
-@@ -1495,27 +1495,6 @@ static void dpy_refresh(DisplayState *s)
- }
- }
-
--void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h)
--{
-- DisplayState *s = con->ds;
-- DisplayChangeListener *dcl;
--
-- if (!qemu_console_is_visible(con)) {
-- return;
-- }
-- QLIST_FOREACH(dcl, &s->listeners, next) {
-- if (con != (dcl->con ? dcl->con : active_console)) {
-- continue;
-- }
-- if (dcl->ops->dpy_gfx_copy) {
-- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
-- } else { /* TODO */
-- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
-- }
-- }
--}
--
- void dpy_text_cursor(QemuConsole *con, int x, int y)
- {
- DisplayState *s = con->ds;
-@@ -1968,13 +1947,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
- dpy_gfx_replace_surface(s, surface);
- }
-
--void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h)
--{
-- assert(con->console_type == GRAPHIC_CONSOLE);
-- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
--}
--
- DisplaySurface *qemu_console_surface(QemuConsole *console)
- {
- return console->surface;
-diff --git a/ui/vnc.c b/ui/vnc.c
-index 52c6809..61ab611 100644
---- a/ui/vnc.c
-+++ b/ui/vnc.c
-@@ -908,96 +908,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
- return n;
- }
-
--static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
--{
-- /* send bitblit op to the vnc client */
-- vnc_lock_output(vs);
-- vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
-- vnc_write_u8(vs, 0);
-- vnc_write_u16(vs, 1); /* number of rects */
-- vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
-- vnc_write_u16(vs, src_x);
-- vnc_write_u16(vs, src_y);
-- vnc_unlock_output(vs);
-- vnc_flush(vs);
--}
--
--static void vnc_dpy_copy(DisplayChangeListener *dcl,
-- int src_x, int src_y,
-- int dst_x, int dst_y, int w, int h)
--{
-- VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
-- VncState *vs, *vn;
-- uint8_t *src_row;
-- uint8_t *dst_row;
-- int i, x, y, pitch, inc, w_lim, s;
-- int cmp_bytes;
--
-- vnc_refresh_server_surface(vd);
-- QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
-- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-- vs->force_update = 1;
-- vnc_update_client(vs, 1, true);
-- /* vs might be free()ed here */
-- }
-- }
--
-- /* do bitblit op on the local surface too */
-- pitch = vnc_server_fb_stride(vd);
-- src_row = vnc_server_fb_ptr(vd, src_x, src_y);
-- dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
-- y = dst_y;
-- inc = 1;
-- if (dst_y > src_y) {
-- /* copy backwards */
-- src_row += pitch * (h-1);
-- dst_row += pitch * (h-1);
-- pitch = -pitch;
-- y = dst_y + h - 1;
-- inc = -1;
-- }
-- w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
-- if (w_lim < 0) {
-- w_lim = w;
-- } else {
-- w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT);
-- }
-- for (i = 0; i < h; i++) {
-- for (x = 0; x <= w_lim;
-- x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
-- if (x == w_lim) {
-- if ((s = w - w_lim) == 0)
-- break;
-- } else if (!x) {
-- s = (VNC_DIRTY_PIXELS_PER_BIT -
-- (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
-- s = MIN(s, w_lim);
-- } else {
-- s = VNC_DIRTY_PIXELS_PER_BIT;
-- }
-- cmp_bytes = s * VNC_SERVER_FB_BYTES;
-- if (memcmp(src_row, dst_row, cmp_bytes) == 0)
-- continue;
-- memmove(dst_row, src_row, cmp_bytes);
-- QTAILQ_FOREACH(vs, &vd->clients, next) {
-- if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-- set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT),
-- vs->dirty[y]);
-- }
-- }
-- }
-- src_row += pitch - w * VNC_SERVER_FB_BYTES;
-- dst_row += pitch - w * VNC_SERVER_FB_BYTES;
-- y += inc;
-- }
--
-- QTAILQ_FOREACH(vs, &vd->clients, next) {
-- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-- vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
-- }
-- }
--}
--
- static void vnc_mouse_set(DisplayChangeListener *dcl,
- int x, int y, int visible)
- {
-@@ -3131,7 +3041,6 @@ static void vnc_listen_websocket_read(void *opaque)
- static const DisplayChangeListenerOps dcl_ops = {
- .dpy_name = "vnc",
- .dpy_refresh = vnc_refresh,
-- .dpy_gfx_copy = vnc_dpy_copy,
- .dpy_gfx_update = vnc_dpy_update,
- .dpy_gfx_switch = vnc_dpy_switch,
- .dpy_gfx_check_format = qemu_pixman_check_format,
---
-2.1.4
-
Index: head/sysutils/xen-tools/pkg-descr
===================================================================
--- head/sysutils/xen-tools/pkg-descr
+++ head/sysutils/xen-tools/pkg-descr
@@ -1,5 +0,0 @@
-The xl program is the new tool for managing Xen guest domains. The program can
-be used to create, pause, and shutdown domains. It can also be used to list
-current domains, enable or pin VCPUs, and attach or detach virtual block devices
-
-WWW: https://wiki.xen.org/wiki/XL
Index: head/sysutils/xen-tools/pkg-plist
===================================================================
--- head/sysutils/xen-tools/pkg-plist
+++ head/sysutils/xen-tools/pkg-plist
@@ -1,606 +0,0 @@
-bin/pygrub
-bin/xen-cpuid
-bin/xen-detect
-bin/xenalyze
-bin/xencons
-bin/xencov_split
-bin/xenstore
-bin/xenstore-chmod
-bin/xenstore-control
-bin/xenstore-exists
-bin/xenstore-list
-bin/xenstore-ls
-bin/xenstore-read
-bin/xenstore-rm
-bin/xenstore-watch
-bin/xenstore-write
-bin/xentrace_format
-etc/bash_completion.d/xl.sh
-etc/rc.d/xencommons
-etc/rc.d/xendriverdomain
-%%ETCDIR%%/README
-%%ETCDIR%%/README.incompatibilities
-%%ETCDIR%%/cpupool
-%%ETCDIR%%/scripts/block
-%%ETCDIR%%/scripts/hotplugpath.sh
-%%ETCDIR%%/scripts/vif-bridge
-%%ETCDIR%%/xl.conf
-%%ETCDIR%%/xlexample.hvm
-%%ETCDIR%%/xlexample.pvlinux
-include/_libxl_list.h
-include/_libxl_types.h
-include/_libxl_types_json.h
-include/fsimage.h
-include/fsimage_grub.h
-include/fsimage_plugin.h
-include/libxl.h
-include/libxl_event.h
-include/libxl_json.h
-include/libxl_utils.h
-include/libxl_uuid.h
-include/libxlutil.h
-include/xen/COPYING
-include/xen/arch-arm.h
-include/xen/arch-arm/hvm/save.h
-include/xen/arch-x86/cpufeatureset.h
-include/xen/arch-x86/cpuid.h
-include/xen/arch-x86/hvm/save.h
-include/xen/arch-x86/pmu.h
-include/xen/arch-x86/xen-mca.h
-include/xen/arch-x86/xen-x86_32.h
-include/xen/arch-x86/xen-x86_64.h
-include/xen/arch-x86/xen.h
-include/xen/arch-x86_32.h
-include/xen/arch-x86_64.h
-include/xen/callback.h
-include/xen/dom0_ops.h
-include/xen/domctl.h
-include/xen/elfnote.h
-include/xen/errno.h
-include/xen/event_channel.h
-include/xen/features.h
-include/xen/foreign/arm32.h
-include/xen/foreign/arm64.h
-include/xen/foreign/x86_32.h
-include/xen/foreign/x86_64.h
-include/xen/gcov.h
-include/xen/grant_table.h
-include/xen/hvm/e820.h
-include/xen/hvm/hvm_info_table.h
-include/xen/hvm/hvm_op.h
-include/xen/hvm/hvm_vcpu.h
-include/xen/hvm/hvm_xs_strings.h
-include/xen/hvm/ioreq.h
-include/xen/hvm/params.h
-include/xen/hvm/pvdrivers.h
-include/xen/hvm/save.h
-include/xen/io/blkif.h
-include/xen/io/console.h
-include/xen/io/fbif.h
-include/xen/io/fsif.h
-include/xen/io/kbdif.h
-include/xen/io/libxenvchan.h
-include/xen/io/netif.h
-include/xen/io/pciif.h
-include/xen/io/protocols.h
-include/xen/io/ring.h
-include/xen/io/tpmif.h
-include/xen/io/usbif.h
-include/xen/io/vscsiif.h
-include/xen/io/xenbus.h
-include/xen/io/xs_wire.h
-include/xen/kexec.h
-include/xen/memory.h
-include/xen/nmi.h
-include/xen/physdev.h
-include/xen/platform.h
-include/xen/pmu.h
-include/xen/sched.h
-include/xen/sys/evtchn.h
-include/xen/sys/privcmd.h
-include/xen/sysctl.h
-include/xen/tmem.h
-include/xen/trace.h
-include/xen/vcpu.h
-include/xen/version.h
-include/xen/vm_event.h
-include/xen/xen-compat.h
-include/xen/xen.h
-include/xen/xencomm.h
-include/xen/xenoprof.h
-include/xen/xsm/flask_op.h
-include/xencall.h
-include/xenctrl.h
-include/xenctrl_compat.h
-include/xenevtchn.h
-include/xenforeignmemory.h
-include/xengnttab.h
-include/xenguest.h
-include/xenstat.h
-include/xenstore-compat/xs.h
-include/xenstore-compat/xs_lib.h
-include/xenstore.h
-include/xenstore_lib.h
-include/xentoollog.h
-include/xs.h
-include/xs_lib.h
-lib/fs/ext2fs/fsimage.so
-lib/fs/fat/fsimage.so
-lib/fs/iso9660/fsimage.so
-lib/fs/reiserfs/fsimage.so
-lib/fs/ufs/fsimage.so
-lib/fs/xfs/fsimage.so
-lib/fs/zfs/fsimage.so
-lib/libfsimage.so
-lib/libfsimage.so.1.0
-lib/libfsimage.so.1.0.0
-lib/libxencall.a
-lib/libxencall.so
-lib/libxencall.so.1
-lib/libxencall.so.1.0
-lib/libxenctrl.a
-lib/libxenctrl.so
-lib/libxenctrl.so.4.7
-lib/libxenctrl.so.4.7.0
-lib/libxenevtchn.a
-lib/libxenevtchn.so
-lib/libxenevtchn.so.1
-lib/libxenevtchn.so.1.0
-lib/libxenforeignmemory.a
-lib/libxenforeignmemory.so
-lib/libxenforeignmemory.so.1
-lib/libxenforeignmemory.so.1.0
-lib/libxengnttab.a
-lib/libxengnttab.so
-lib/libxengnttab.so.1
-lib/libxengnttab.so.1.0
-lib/libxenguest.a
-lib/libxenguest.so
-lib/libxenguest.so.4.7
-lib/libxenguest.so.4.7.0
-lib/libxenlight.a
-lib/libxenlight.so
-lib/libxenlight.so.4.7
-lib/libxenlight.so.4.7.0
-lib/libxenstat.a
-lib/libxenstat.so
-lib/libxenstat.so.0
-lib/libxenstat.so.0.0
-lib/libxenstore.a
-lib/libxenstore.so
-lib/libxenstore.so.3.0
-lib/libxenstore.so.3.0.3
-lib/libxentoollog.a
-lib/libxentoollog.so
-lib/libxentoollog.so.1
-lib/libxentoollog.so.1.0
-lib/libxlutil.a
-lib/libxlutil.so
-lib/libxlutil.so.4.7
-lib/libxlutil.so.4.7.0
-%%PYTHON_SITELIBDIR%%/fsimage.so
-%%PYTHON_SITELIBDIR%%/grub/ExtLinuxConf.py
-%%PYTHON_SITELIBDIR%%/grub/ExtLinuxConf.pyc
-%%PYTHON_SITELIBDIR%%/grub/GrubConf.py
-%%PYTHON_SITELIBDIR%%/grub/GrubConf.pyc
-%%PYTHON_SITELIBDIR%%/grub/LiloConf.py
-%%PYTHON_SITELIBDIR%%/grub/LiloConf.pyc
-%%PYTHON_SITELIBDIR%%/grub/__init__.py
-%%PYTHON_SITELIBDIR%%/grub/__init__.pyc
-%%PYTHON_SITELIBDIR%%/pygrub-0.3-py%%PYTHON_VER%%.egg-info
-%%PYTHON_SITELIBDIR%%/xen-3.0-py%%PYTHON_VER%%.egg-info
-%%PYTHON_SITELIBDIR%%/xen/__init__.py
-%%PYTHON_SITELIBDIR%%/xen/__init__.pyc
-%%PYTHON_SITELIBDIR%%/xen/lowlevel/__init__.py
-%%PYTHON_SITELIBDIR%%/xen/lowlevel/__init__.pyc
-%%PYTHON_SITELIBDIR%%/xen/lowlevel/xc.so
-%%PYTHON_SITELIBDIR%%/xen/lowlevel/xs.so
-%%PYTHON_SITELIBDIR%%/xen/migration/__init__.py
-%%PYTHON_SITELIBDIR%%/xen/migration/__init__.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/legacy.py
-%%PYTHON_SITELIBDIR%%/xen/migration/legacy.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/libxc.py
-%%PYTHON_SITELIBDIR%%/xen/migration/libxc.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/libxl.py
-%%PYTHON_SITELIBDIR%%/xen/migration/libxl.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/public.py
-%%PYTHON_SITELIBDIR%%/xen/migration/public.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/tests.py
-%%PYTHON_SITELIBDIR%%/xen/migration/tests.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/verify.py
-%%PYTHON_SITELIBDIR%%/xen/migration/verify.pyc
-%%PYTHON_SITELIBDIR%%/xen/migration/xl.py
-%%PYTHON_SITELIBDIR%%/xen/migration/xl.pyc
-lib/xen/bin/convert-legacy-stream
-lib/xen/bin/libxl-save-helper
-lib/xen/bin/lsevtchn
-lib/xen/bin/pygrub
-lib/xen/bin/qemu-system-i386
-lib/xen/bin/readnotes
-lib/xen/bin/verify-stream-v2
-lib/xen/bin/xen-init-dom0
-lib/xen/bin/xenconsole
-lib/xen/bin/xenctx
-lib/xen/bin/xenpaging
-lib/xen/bin/xenpvnetboot
-lib/xen/boot/hvmloader
-man/man1/xenstore-chmod.1.gz
-man/man1/xenstore-ls.1.gz
-man/man1/xenstore.1.gz
-man/man1/xentop.1.gz
-man/man1/xentrace_format.1.gz
-man/man1/xl.1.gz
-man/man5/xl.cfg.5.gz
-man/man5/xl.conf.5.gz
-man/man5/xlcpupool.cfg.5.gz
-man/man8/xentrace.8.gz
-sbin/flask-get-bool
-sbin/flask-getenforce
-sbin/flask-label-pci
-sbin/flask-loadpolicy
-sbin/flask-set-bool
-sbin/flask-setenforce
-sbin/gdbsx
-sbin/gtracestat
-sbin/gtraceview
-sbin/kdd
-sbin/xen-bugtool
-sbin/xen-hptool
-sbin/xen-hvmcrash
-sbin/xen-hvmctx
-sbin/xen-lowmemd
-sbin/xen-mfndump
-sbin/xen-ringwatch
-sbin/xen-tmem-list-parse
-sbin/xen-livepatch
-sbin/xenbaked
-sbin/xenconsoled
-sbin/xencov
-sbin/xenlockprof
-sbin/xenmon.py
-sbin/xenperf
-sbin/xenpm
-sbin/xenpmd
-sbin/xenstored
-sbin/xentop
-sbin/xentrace
-sbin/xentrace_setmask
-sbin/xentrace_setsize
-sbin/xenwatchdogd
-sbin/xl
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/.deps
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,arch-arm,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,arch-arm.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,callback.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,dom0_ops.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,domctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,elfnote.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,event_channel.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,features.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,gcov.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,grant_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,e820.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_info_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_xs_strings.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,ioreq.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,params.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,pvdrivers.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,blkif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,console.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,fbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,fsif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,kbdif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,libxenvchan.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,netif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,pciif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,protocols.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,ring.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,tpmif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,usbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,vscsiif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,xenbus.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,xs_wire.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,kexec.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,memory.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,nmi.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,physdev.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,platform.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,pmu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,sched.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,sysctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,tmem.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,trace.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,version.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,vm_event.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xen-compat.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xen.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xencomm.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xenoprof.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xsm,flask_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,xen,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/.deps
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,cpufeatureset.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,cpuid.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,pmu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen-mca.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen-x86_32.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86_32.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,callback.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,dom0_ops.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,domctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,elfnote.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,event_channel.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,features.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,gcov.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,grant_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,e820.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_info_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_xs_strings.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,ioreq.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,params.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,pvdrivers.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,blkif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,console.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,fbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,fsif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,kbdif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,libxenvchan.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,netif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,pciif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,protocols.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,ring.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,tpmif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,usbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,vscsiif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,xenbus.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,xs_wire.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,kexec.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,memory.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,nmi.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,physdev.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,platform.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,pmu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,sched.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,sysctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,tmem.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,trace.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,version.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,vm_event.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xen-compat.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xen.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xencomm.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xenoprof.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xsm,flask_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,xen,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/.deps
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,cpufeatureset.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,cpuid.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,pmu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen-mca.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen-x86_64.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86_64.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,callback.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,dom0_ops.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,domctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,elfnote.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,event_channel.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,features.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,gcov.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,grant_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,e820.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_info_table.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_xs_strings.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,ioreq.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,params.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,pvdrivers.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,save.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,blkif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,console.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,fbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,fsif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,kbdif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,libxenvchan.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,netif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,pciif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,protocols.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,ring.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,tpmif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,usbif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,vscsiif.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,xenbus.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,xs_wire.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,kexec.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,memory.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,nmi.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,physdev.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,platform.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,pmu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,sched.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,sysctl.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,tmem.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,trace.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,vcpu.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,version.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,vm_event.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xen-compat.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xen.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xencomm.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xenoprof.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xsm,flask_op.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,xen,errno.h.html
-%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore-chmod.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore-ls.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xentop.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xentrace.8.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xentrace_format.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.1.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.cfg.5.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.conf.5.html
-%%PORTDOCS%%%%DOCSDIR%%/html/man/xlcpupool.cfg.5.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/amd-ucode-container.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/booting.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/booting.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/guest.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/passthrough.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/early-printk.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/passthrough.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/block-scripts.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/channel.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/console.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/coverage.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/crashdb.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/distro_mapping.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/dump-core-format.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/efi.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/grant-tables.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/hvm-emulated-unplug.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/hvmlite.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/index.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/kconfig-language.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/kconfig.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/kexec_and_kdump.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/libxl_memory.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/pci-device-reservations.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/printk-formats.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/pvh-readme.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/pvh.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/qemu-backends.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/qemu-deprivilege.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/stubdom.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/tscmode.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vbd-interface.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtd-pi.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtd.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpm-platforms.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpm.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpmmgr.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/x86-xenpv-bootloader.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xen-command-line.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xen-error-handling.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenmon.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenpaging.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore-paths.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore-ring.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-disk-configuration.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-network-configuration.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-numa-placement.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-psr.html
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/xsm-flask.txt
-%%PORTDOCS%%%%DOCSDIR%%/html/misc/livepatch.html
-libdata/pkgconfig/xenlight.pc
-libdata/pkgconfig/xlutil.pc
-share/qemu-xen/qemu/QEMU,cgthree.bin
-share/qemu-xen/qemu/QEMU,tcx.bin
-share/qemu-xen/qemu/acpi-dsdt.aml
-share/qemu-xen/qemu/bamboo.dtb
-share/qemu-xen/qemu/bios-256k.bin
-share/qemu-xen/qemu/bios.bin
-share/qemu-xen/qemu/efi-e1000.rom
-share/qemu-xen/qemu/efi-eepro100.rom
-share/qemu-xen/qemu/efi-ne2k_pci.rom
-share/qemu-xen/qemu/efi-pcnet.rom
-share/qemu-xen/qemu/efi-rtl8139.rom
-share/qemu-xen/qemu/efi-virtio.rom
-share/qemu-xen/qemu/keymaps/ar
-share/qemu-xen/qemu/keymaps/bepo
-share/qemu-xen/qemu/keymaps/common
-share/qemu-xen/qemu/keymaps/cz
-share/qemu-xen/qemu/keymaps/da
-share/qemu-xen/qemu/keymaps/de
-share/qemu-xen/qemu/keymaps/de-ch
-share/qemu-xen/qemu/keymaps/en-gb
-share/qemu-xen/qemu/keymaps/en-us
-share/qemu-xen/qemu/keymaps/es
-share/qemu-xen/qemu/keymaps/et
-share/qemu-xen/qemu/keymaps/fi
-share/qemu-xen/qemu/keymaps/fo
-share/qemu-xen/qemu/keymaps/fr
-share/qemu-xen/qemu/keymaps/fr-be
-share/qemu-xen/qemu/keymaps/fr-ca
-share/qemu-xen/qemu/keymaps/fr-ch
-share/qemu-xen/qemu/keymaps/hr
-share/qemu-xen/qemu/keymaps/hu
-share/qemu-xen/qemu/keymaps/is
-share/qemu-xen/qemu/keymaps/it
-share/qemu-xen/qemu/keymaps/ja
-share/qemu-xen/qemu/keymaps/lt
-share/qemu-xen/qemu/keymaps/lv
-share/qemu-xen/qemu/keymaps/mk
-share/qemu-xen/qemu/keymaps/modifiers
-share/qemu-xen/qemu/keymaps/nl
-share/qemu-xen/qemu/keymaps/nl-be
-share/qemu-xen/qemu/keymaps/no
-share/qemu-xen/qemu/keymaps/pl
-share/qemu-xen/qemu/keymaps/pt
-share/qemu-xen/qemu/keymaps/pt-br
-share/qemu-xen/qemu/keymaps/ru
-share/qemu-xen/qemu/keymaps/sl
-share/qemu-xen/qemu/keymaps/sv
-share/qemu-xen/qemu/keymaps/th
-share/qemu-xen/qemu/keymaps/tr
-share/qemu-xen/qemu/kvmvapic.bin
-share/qemu-xen/qemu/linuxboot.bin
-share/qemu-xen/qemu/multiboot.bin
-share/qemu-xen/qemu/openbios-ppc
-share/qemu-xen/qemu/openbios-sparc32
-share/qemu-xen/qemu/openbios-sparc64
-share/qemu-xen/qemu/palcode-clipper
-share/qemu-xen/qemu/petalogix-ml605.dtb
-share/qemu-xen/qemu/petalogix-s3adsp1800.dtb
-share/qemu-xen/qemu/ppc_rom.bin
-share/qemu-xen/qemu/pxe-e1000.rom
-share/qemu-xen/qemu/pxe-eepro100.rom
-share/qemu-xen/qemu/pxe-ne2k_pci.rom
-share/qemu-xen/qemu/pxe-pcnet.rom
-share/qemu-xen/qemu/pxe-rtl8139.rom
-share/qemu-xen/qemu/pxe-virtio.rom
-share/qemu-xen/qemu/q35-acpi-dsdt.aml
-share/qemu-xen/qemu/qemu-icon.bmp
-share/qemu-xen/qemu/qemu_logo_no_text.svg
-share/qemu-xen/qemu/s390-ccw.img
-share/qemu-xen/qemu/s390-zipl.rom
-share/qemu-xen/qemu/sgabios.bin
-share/qemu-xen/qemu/slof.bin
-share/qemu-xen/qemu/spapr-rtas.bin
-share/qemu-xen/qemu/trace-events
-share/qemu-xen/qemu/u-boot.e500
-share/qemu-xen/qemu/vgabios-cirrus.bin
-share/qemu-xen/qemu/vgabios-qxl.bin
-share/qemu-xen/qemu/vgabios-stdvga.bin
-share/qemu-xen/qemu/vgabios-virtio.bin
-share/qemu-xen/qemu/vgabios-vmware.bin
-share/qemu-xen/qemu/vgabios.bin
-@dir %%ETCDIR%%/auto
-@dir /var/crash/xen
-@dir /var/db/xen/xenpaging
-@dir /var/db/xen
-@dir /var/db/xenstored
-@dir /var/log/xen
-@dir /var/run/xen
Index: head/sysutils/xen-tools47/Makefile
===================================================================
--- head/sysutils/xen-tools47/Makefile
+++ head/sysutils/xen-tools47/Makefile
@@ -0,0 +1,93 @@
+# $FreeBSD$
+
+PORTNAME= xen
+PKGNAMESUFFIX= -tools
+PORTVERSION= 4.7.2
+PORTREVISION= 4
+CATEGORIES= sysutils emulators
+MASTER_SITES= http://downloads.xenproject.org/release/xen/${PORTVERSION}/
+
+MAINTAINER= royger@FreeBSD.org
+COMMENT= Xen management tool, based on LibXenlight
+
+LICENSE= GPLv2 LGPL3
+LICENSE_COMB= multi
+
+BROKEN_FreeBSD_10= does not build
+
+LIB_DEPENDS= libyajl.so:devel/yajl \
+ liblzo2.so:archivers/lzo2 \
+ libpixman-1.so:x11/pixman \
+ libargp.so:devel/argp-standalone
+BUILD_DEPENDS= dev86>0:devel/dev86 \
+ seabios>0:misc/seabios \
+ markdown>0:textproc/markdown
+
+OPTIONS_DEFINE= DOCS
+
+ONLY_FOR_ARCHS= amd64
+ONLY_FOR_ARCHS_REASON= "not yet ported to anything other than amd64"
+
+USES= cpe gettext gmake libtool localbase:ldflags perl5 pkgconfig \
+ python:2.7 shebangfix
+USE_GNOME= glib20
+USE_LDCONFIG= yes
+GNU_CONFIGURE= yes
+MAKE_ARGS= clang=y
+QEMU_ARGS= --disable-gtk \
+ --disable-smartcard-nss \
+ --disable-sdl \
+ --disable-vte \
+ --disable-curses \
+ --disable-tools \
+ --disable-curl \
+ --cxx=c++
+
+EXTRA_PATCHES= ${FILESDIR}/var_paths.patch:-p1 \
+ ${FILESDIR}/0001-libxl-fix-creation-of-pkgconf-install-dir.patch:-p1 \
+ ${FILESDIR}/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch:-p1 \
+ ${FILESDIR}/0001-libs-xenstore-set-correct-FreeBSD-device.patch:-p1 \
+ ${FILESDIR}/kdd.patch:-p1 \
+ ${FILESDIR}/0001-xenstored-apply-a-write-transaction-rate-limit.patch:-p1 \
+ ${FILESDIR}/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch:-p1 \
+ ${FILESDIR}/0001-Backport-of-commit-858dba.patch:-p1
+
+CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}" \
+ --with-system-seabios=${LOCALBASE}/share/seabios/bios.bin
+
+# Disable bash and xgettext tests, they are not needed on FreeBSD.
+CONFIGURE_ENV+= ac_cv_path_BASH=${TRUE}
+
+SHEBANG_FILES= tools/misc/xen-ringwatch \
+ tools/misc/xencov_split \
+ tools/python/scripts/convert-legacy-stream \
+ tools/python/scripts/verify-stream-v2 \
+ tools/xenmon/xenmon.py
+
+ALL_TARGET= tools docs
+INSTALL_TARGET= install-tools install-docs
+
+.include <bsd.port.options.mk>
+
+.if ${OPSYS} != FreeBSD
+IGNORE= only supported on FreeBSD
+.endif
+
+post-patch:
+ @${REINPLACE_CMD} "s,x86_64,amd64,g" ${WRKSRC}/tools/configure
+ @${REINPLACE_CMD} -e "s,/var/lib,/var/db,g" \
+ ${WRKSRC}/tools/Makefile \
+ ${WRKSRC}/tools/libxc/include/xenguest.h \
+ ${WRKSRC}/tools/libxl/libxl_dom.c \
+ ${WRKSRC}/tools/libxl/libxl_dm.c \
+ ${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \
+ ${WRKSRC}/docs/man/*
+ @for p in `ls ${FILESDIR}/*qemuu*.patch 2>/dev/null`; do \
+ ${ECHO_CMD} "====> Applying $${p##*/}" ; \
+ ${PATCH} -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \
+ done
+
+post-install:
+ ${MKDIR} ${STAGEDIR}/var/run/xen
+
+.include <bsd.port.mk>
Index: head/sysutils/xen-tools47/distinfo
===================================================================
--- head/sysutils/xen-tools47/distinfo
+++ head/sysutils/xen-tools47/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1489085975
+SHA256 (xen-4.7.2.tar.gz) = 61494a56d9251e2108080f95b0dc8e3d175f1ba4da34603fc07b91cfebf358d5
+SIZE (xen-4.7.2.tar.gz) = 20714281
Index: head/sysutils/xen-tools47/files/0001-Backport-of-commit-858dba.patch
===================================================================
--- head/sysutils/xen-tools47/files/0001-Backport-of-commit-858dba.patch
+++ head/sysutils/xen-tools47/files/0001-Backport-of-commit-858dba.patch
@@ -0,0 +1,35 @@
+From 2ff6287610fa44eec9f30630d87166ad1fc0e452 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 22 May 2018 17:47:37 +0200
+Subject: [PATCH] Backport of commit 858dba
+
+This is required in order to build Xen with newer iasl found in HEAD.
+---
+ tools/firmware/hvmloader/acpi/Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/firmware/hvmloader/acpi/Makefile b/tools/firmware/hvmloader/acpi/Makefile
+index d3e882ac69..29f93e6a8c 100644
+--- a/tools/firmware/hvmloader/acpi/Makefile
++++ b/tools/firmware/hvmloader/acpi/Makefile
+@@ -27,7 +27,7 @@ all: acpi.a
+
+ ssdt_s3.h ssdt_s4.h ssdt_pm.h ssdt_tpm.h: %.h: %.asl iasl
+ iasl -vs -p $* -tc $<
+- sed -e 's/AmlCode/$*/g' $*.hex >$@
++ sed -e 's/AmlCode/$*/g' -e 's/_aml_code//g' $*.hex >$@
+ rm -f $*.hex $*.aml
+
+ mk_dsdt: mk_dsdt.c
+@@ -44,7 +44,7 @@ dsdt_%cpu.asl: dsdt.asl mk_dsdt
+
+ $(filter dsdt_%.c,$(C_SRC)): %.c: iasl %.asl
+ iasl -vs -p $* -tc $*.asl
+- sed -e 's/AmlCode/$*/g' $*.hex >$@
++ sed -e 's/AmlCode/$*/g' -e 's/_aml_code//g' $*.hex >$@
+ echo "int $*_len=sizeof($*);" >>$@
+ rm -f $*.aml $*.hex
+
+--
+2.17.0
+
Index: head/sysutils/xen-tools47/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
===================================================================
--- head/sysutils/xen-tools47/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
+++ head/sysutils/xen-tools47/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch
@@ -0,0 +1,32 @@
+From 7ff99b232e0f91a5189f429498868bfccf8d7154 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Mon, 12 Dec 2016 16:07:40 +0000
+Subject: [PATCH] libs/xenstore: set correct FreeBSD device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The path to the xenstore FreeBSD device is /dev/xen/xenstore.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Acked-by: Wei Liu <wei.liu2@citrix.com>
+---
+ tools/xenstore/xs_lib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/xenstore/xs_lib.c b/tools/xenstore/xs_lib.c
+index 5ef3d6d..3e43f88 100644
+--- a/tools/xenstore/xs_lib.c
++++ b/tools/xenstore/xs_lib.c
+@@ -85,6 +85,8 @@ const char *xs_domain_dev(void)
+ return "/proc/xen/xenbus";
+ #elif defined(__NetBSD__)
+ return "/kern/xen/xenbus";
++#elif defined(__FreeBSD__)
++ return "/dev/xen/xenstore";
+ #else
+ return "/dev/xen/xenbus";
+ #endif
+--
+2.10.1 (Apple Git-78)
+
Index: head/sysutils/xen-tools47/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
===================================================================
--- head/sysutils/xen-tools47/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
+++ head/sysutils/xen-tools47/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch
@@ -0,0 +1,35 @@
+From 45434adc3c94f5229744beaa12028aa23f63b9e7 Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Wed, 23 Nov 2016 16:56:39 +0000
+Subject: [PATCH] libxl: fix creation of pkgconf install dir
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When PKG_INSTALLDIR was introduced the creation of the previous pkgconf install
+directory was not changed. Fix this by correctly using PKG_INSTALLDIR for the
+directory creation in libxl Makefile.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Acked-by: Wei Liu <wei.liu2@citrix.com>
+Release-acked-by: Wei Liu <wei.liu2@citrix.com>
+---
+ tools/libxl/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
+index f5053a0..ef01785 100644
+--- a/tools/libxl/Makefile
++++ b/tools/libxl/Makefile
+@@ -308,7 +308,7 @@ install: all
+ $(INSTALL_DIR) $(DESTDIR)$(includedir)
+ $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR)
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+- $(INSTALL_DIR) $(DESTDIR)$(SHAREDIR)/pkgconfig
++ $(INSTALL_DIR) $(DESTDIR)$(PKG_INSTALLDIR)
+ $(INSTALL_PROG) xl $(DESTDIR)$(sbindir)
+ $(INSTALL_PROG) libxl-save-helper $(DESTDIR)$(LIBEXEC_BIN)
+ $(INSTALL_SHLIB) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+--
+2.9.3 (Apple Git-75)
+
Index: head/sysutils/xen-tools47/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
===================================================================
--- head/sysutils/xen-tools47/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
+++ head/sysutils/xen-tools47/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch
@@ -0,0 +1,66 @@
+From 4000a7c7d7b0e01837abd3918e393f289c07d68c Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 25 Oct 2016 11:53:28 +0200
+Subject: [PATCH] tools/configure: fix pkg-config install path for FreeBSD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+pkg-config from FreeBSD ports doesn't have ${prefix}/share/pkgconfig in the
+default search path, fix this by having a PKG_INSTALLDIR variable that can
+be changed on a per-OS basis.
+
+It would be best to use PKG_INSTALLDIR as defined by the pkg.m4 macro, but
+sadly this also reports a wrong value on FreeBSD (${libdir}/pkgconfig, which
+expands to /usr/local/lib/pkgconfig by default, and is also _not_ part of
+the default pkg-config search path).
+
+This patch should not change the behavior for Linux installs.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reported-by: Alexander Nusov <alexander.nusov@nfvexpress.com>
+Acked-by: Wei Liu <wei.liu2@citrix.com>
+Release-acked-by: Wei Liu <wei.liu2@citrix.com>
+---
+ config/FreeBSD.mk | 1 +
+ config/Paths.mk.in | 2 ++
+ tools/libxl/Makefile | 4 ++--
+ 3 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
+index bb3a5d0..afeaefb 100644
+--- a/config/FreeBSD.mk
++++ b/config/FreeBSD.mk
+@@ -2,3 +2,4 @@ include $(XEN_ROOT)/config/StdGNU.mk
+
+ # No wget on FreeBSD base system
+ WGET = ftp
++PKG_INSTALLDIR = ${prefix}/libdata/pkgconfig
+diff --git a/config/Paths.mk.in b/config/Paths.mk.in
+index 62cea48..a603295 100644
+--- a/config/Paths.mk.in
++++ b/config/Paths.mk.in
+@@ -56,3 +56,5 @@ XENFIRMWAREDIR := @XENFIRMWAREDIR@
+
+ XEN_CONFIG_DIR := @XEN_CONFIG_DIR@
+ XEN_SCRIPT_DIR := @XEN_SCRIPT_DIR@
++
++PKG_INSTALLDIR := ${SHAREDIR}/pkgconfig
+diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
+index 79e4019..af0a3ad 100644
+--- a/tools/libxl/Makefile
++++ b/tools/libxl/Makefile
+@@ -320,8 +320,8 @@ install: all
+ $(INSTALL_DATA) libxlutil.a $(DESTDIR)$(libdir)
+ $(INSTALL_DATA) libxl.h libxl_event.h libxl_json.h _libxl_types.h _libxl_types_json.h _libxl_list.h libxl_utils.h libxl_uuid.h libxlutil.h $(DESTDIR)$(includedir)
+ $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xl.sh
+- $(INSTALL_DATA) xenlight.pc $(DESTDIR)$(SHAREDIR)/pkgconfig/
+- $(INSTALL_DATA) xlutil.pc $(DESTDIR)$(SHAREDIR)/pkgconfig/
++ $(INSTALL_DATA) xenlight.pc $(DESTDIR)$(PKG_INSTALLDIR)
++ $(INSTALL_DATA) xlutil.pc $(DESTDIR)$(PKG_INSTALLDIR)
+
+ .PHONY: clean
+ clean:
+--
+2.9.3 (Apple Git-75)
+
Index: head/sysutils/xen-tools47/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
===================================================================
--- head/sysutils/xen-tools47/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
+++ head/sysutils/xen-tools47/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch
@@ -0,0 +1,456 @@
+From bfe42a836450591bb41f4f6393c42dbb0d72abb9 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson@eu.citrix.com>
+Date: Sat, 18 Mar 2017 16:12:26 +0000
+Subject: [PATCH 01/15] xenstored: apply a write transaction rate limit
+
+This avoids a rogue client being about to stall another client (eg the
+toolstack) indefinitely.
+
+This is XSA-206.
+
+Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
+
+Backported to 4.8 (not entirely trivial).
+
+Reported-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Acked-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
+---
+ tools/xenstore/Makefile | 3 +-
+ tools/xenstore/xenstored_core.c | 9 ++
+ tools/xenstore/xenstored_core.h | 6 +
+ tools/xenstore/xenstored_domain.c | 215 +++++++++++++++++++++++++++++++++
+ tools/xenstore/xenstored_domain.h | 25 ++++
+ tools/xenstore/xenstored_transaction.c | 5 +
+ 6 files changed, 262 insertions(+), 1 deletion(-)
+
+diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
+index d691b78..b458729 100644
+--- a/tools/xenstore/Makefile
++++ b/tools/xenstore/Makefile
+@@ -31,6 +31,7 @@ XENSTORED_OBJS_$(CONFIG_FreeBSD) = xenstored_posix.o
+ XENSTORED_OBJS_$(CONFIG_MiniOS) = xenstored_minios.o
+
+ XENSTORED_OBJS += $(XENSTORED_OBJS_y)
++LDLIBS_xenstored += -lrt
+
+ ifneq ($(XENSTORE_STATIC_CLIENTS),y)
+ LIBXENSTORE := libxenstore.so
+@@ -72,7 +73,7 @@ endif
+ $(XENSTORED_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
+
+ xenstored: $(XENSTORED_OBJS)
+- $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxenctrl) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
++ $(CC) $^ $(LDFLAGS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxenctrl) $(LDLIBS_xenstored) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
+
+ xenstored.a: $(XENSTORED_OBJS)
+ $(AR) cr $@ $^
+diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
+index 51fb0b3..1aabc93 100644
+--- a/tools/xenstore/xenstored_core.c
++++ b/tools/xenstore/xenstored_core.c
+@@ -357,6 +357,7 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
+ int *ptimeout)
+ {
+ struct connection *conn;
++ struct wrl_timestampt now;
+
+ if (fds)
+ memset(fds, 0, sizeof(struct pollfd) * current_array_size);
+@@ -376,8 +377,11 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
+ xce_pollfd_idx = set_fd(xenevtchn_fd(xce_handle),
+ POLLIN|POLLPRI);
+
++ wrl_gettime_now(&now);
++
+ list_for_each_entry(conn, &connections, list) {
+ if (conn->domain) {
++ wrl_check_timeout(conn->domain, now, ptimeout);
+ if (domain_can_read(conn) ||
+ (domain_can_write(conn) &&
+ !list_empty(&conn->out_list)))
+@@ -810,6 +814,7 @@ static void delete_node_single(struct connection *conn, struct node *node)
+ corrupt(conn, "Could not delete '%s'", node->name);
+ return;
+ }
++
+ domain_entry_dec(conn, node);
+ }
+
+@@ -949,6 +954,7 @@ static void do_write(struct connection *conn, struct buffered_data *in)
+ }
+
+ add_change_node(conn->transaction, name, false);
++ wrl_apply_debit_direct(conn);
+ fire_watches(conn, name, false);
+ send_ack(conn, XS_WRITE);
+ }
+@@ -973,6 +979,7 @@ static void do_mkdir(struct connection *conn, const char *name)
+ return;
+ }
+ add_change_node(conn->transaction, name, false);
++ wrl_apply_debit_direct(conn);
+ fire_watches(conn, name, false);
+ }
+ send_ack(conn, XS_MKDIR);
+@@ -1098,6 +1105,7 @@ static void do_rm(struct connection *conn, const char *name)
+
+ if (_rm(conn, node, name)) {
+ add_change_node(conn->transaction, name, true);
++ wrl_apply_debit_direct(conn);
+ fire_watches(conn, name, true);
+ send_ack(conn, XS_RM);
+ }
+@@ -1173,6 +1181,7 @@ static void do_set_perms(struct connection *conn, struct buffered_data *in)
+ }
+
+ add_change_node(conn->transaction, name, false);
++ wrl_apply_debit_direct(conn);
+ fire_watches(conn, name, false);
+ send_ack(conn, XS_SET_PERMS);
+ }
+diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
+index 3a497f7..a2a3427 100644
+--- a/tools/xenstore/xenstored_core.h
++++ b/tools/xenstore/xenstored_core.h
+@@ -33,6 +33,12 @@
+ #include "list.h"
+ #include "tdb.h"
+
++#define MIN(a, b) (((a) < (b))? (a) : (b))
++
++typedef int32_t wrl_creditt;
++#define WRL_CREDIT_MAX (1000*1000*1000)
++/* ^ satisfies non-overflow condition for wrl_xfer_credit */
++
+ struct buffered_data
+ {
+ struct list_head list;
+diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
+index 47b4f03..486c96f 100644
+--- a/tools/xenstore/xenstored_domain.c
++++ b/tools/xenstore/xenstored_domain.c
+@@ -21,6 +21,7 @@
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
++#include <time.h>
+
+ #include "utils.h"
+ #include "talloc.h"
+@@ -74,6 +75,10 @@ struct domain
+
+ /* number of watch for this domain */
+ int nbwatch;
++
++ /* write rate limit */
++ wrl_creditt wrl_credit; /* [ -wrl_config_writecost, +_dburst ] */
++ struct wrl_timestampt wrl_timestamp;
+ };
+
+ static LIST_HEAD(domains);
+@@ -206,6 +211,8 @@ static int destroy_domain(void *_domain)
+
+ fire_watches(NULL, "@releaseDomain", false);
+
++ wrl_domain_destroy(domain);
++
+ return 0;
+ }
+
+@@ -253,6 +260,9 @@ void handle_event(void)
+ bool domain_can_read(struct connection *conn)
+ {
+ struct xenstore_domain_interface *intf = conn->domain->interface;
++
++ if (domain_is_unprivileged(conn) && conn->domain->wrl_credit < 0)
++ return false;
+ return (intf->req_cons != intf->req_prod);
+ }
+
+@@ -284,6 +294,8 @@ static struct domain *new_domain(void *context, unsigned int domid,
+ domain->domid = domid;
+ domain->path = talloc_domain_path(domain, domid);
+
++ wrl_domain_new(domain);
++
+ list_add(&domain->list, &domains);
+ talloc_set_destructor(domain, destroy_domain);
+
+@@ -747,6 +759,209 @@ int domain_watch(struct connection *conn)
+ : 0;
+ }
+
++static wrl_creditt wrl_config_writecost = WRL_FACTOR;
++static wrl_creditt wrl_config_rate = WRL_RATE * WRL_FACTOR;
++static wrl_creditt wrl_config_dburst = WRL_DBURST * WRL_FACTOR;
++static wrl_creditt wrl_config_gburst = WRL_GBURST * WRL_FACTOR;
++static wrl_creditt wrl_config_newdoms_dburst =
++ WRL_DBURST * WRL_NEWDOMS * WRL_FACTOR;
++
++long wrl_ntransactions;
++
++static long wrl_ndomains;
++static wrl_creditt wrl_reserve; /* [-wrl_config_newdoms_dburst, +_gburst ] */
++
++void wrl_gettime_now(struct wrl_timestampt *now_wt)
++{
++ struct timespec now_ts;
++ int r;
++
++ r = clock_gettime(CLOCK_MONOTONIC, &now_ts);
++ if (r)
++ barf_perror("Could not find time (clock_gettime failed)");
++
++ now_wt->sec = now_ts.tv_sec;
++ now_wt->msec = now_ts.tv_nsec / 1000000;
++}
++
++static void wrl_xfer_credit(wrl_creditt *debit, wrl_creditt debit_floor,
++ wrl_creditt *credit, wrl_creditt credit_ceil)
++ /*
++ * Transfers zero or more credit from "debit" to "credit".
++ * Transfers as much as possible while maintaining
++ * debit >= debit_floor and credit <= credit_ceil.
++ * (If that's violated already, does nothing.)
++ *
++ * Sufficient conditions to avoid overflow, either of:
++ * |every argument| <= 0x3fffffff
++ * |every argument| <= 1E9
++ * |every argument| <= WRL_CREDIT_MAX
++ * (And this condition is preserved.)
++ */
++{
++ wrl_creditt xfer = MIN( *debit - debit_floor,
++ credit_ceil - *credit );
++ if (xfer > 0) {
++ *debit -= xfer;
++ *credit += xfer;
++ }
++}
++
++void wrl_domain_new(struct domain *domain)
++{
++ domain->wrl_credit = 0;
++ wrl_gettime_now(&domain->wrl_timestamp);
++ wrl_ndomains++;
++ /* Steal up to DBURST from the reserve */
++ wrl_xfer_credit(&wrl_reserve, -wrl_config_newdoms_dburst,
++ &domain->wrl_credit, wrl_config_dburst);
++}
++
++void wrl_domain_destroy(struct domain *domain)
++{
++ wrl_ndomains--;
++ /*
++ * Don't bother recalculating domain's credit - this just
++ * means we don't give the reserve the ending domain's credit
++ * for time elapsed since last update.
++ */
++ wrl_xfer_credit(&domain->wrl_credit, 0,
++ &wrl_reserve, wrl_config_dburst);
++}
++
++void wrl_credit_update(struct domain *domain, struct wrl_timestampt now)
++{
++ /*
++ * We want to calculate
++ * credit += (now - timestamp) * RATE / ndoms;
++ * But we want it to saturate, and to avoid floating point.
++ * To avoid rounding errors from constantly adding small
++ * amounts of credit, we only add credit for whole milliseconds.
++ */
++ long seconds = now.sec - domain->wrl_timestamp.sec;
++ long milliseconds = now.msec - domain->wrl_timestamp.msec;
++ long msec;
++ int64_t denom, num;
++ wrl_creditt surplus;
++
++ seconds = MIN(seconds, 1000*1000); /* arbitrary, prevents overflow */
++ msec = seconds * 1000 + milliseconds;
++
++ if (msec < 0)
++ /* shouldn't happen with CLOCK_MONOTONIC */
++ msec = 0;
++
++ /* 32x32 -> 64 cannot overflow */
++ denom = (int64_t)msec * wrl_config_rate;
++ num = (int64_t)wrl_ndomains * 1000;
++ /* denom / num <= 1E6 * wrl_config_rate, so with
++ reasonable wrl_config_rate, denom / num << 2^64 */
++
++ /* at last! */
++ domain->wrl_credit = MIN( (int64_t)domain->wrl_credit + denom / num,
++ WRL_CREDIT_MAX );
++ /* (maybe briefly violating the DBURST cap on wrl_credit) */
++
++ /* maybe take from the reserve to make us nonnegative */
++ wrl_xfer_credit(&wrl_reserve, 0,
++ &domain->wrl_credit, 0);
++
++ /* return any surplus (over DBURST) to the reserve */
++ surplus = 0;
++ wrl_xfer_credit(&domain->wrl_credit, wrl_config_dburst,
++ &surplus, WRL_CREDIT_MAX);
++ wrl_xfer_credit(&surplus, 0,
++ &wrl_reserve, wrl_config_gburst);
++ /* surplus is now implicitly discarded */
++
++ domain->wrl_timestamp = now;
++
++ trace("wrl: dom %4d %6ld msec %9ld credit %9ld reserve"
++ " %9ld discard\n",
++ domain->domid,
++ msec,
++ (long)domain->wrl_credit, (long)wrl_reserve,
++ (long)surplus);
++}
++
++void wrl_check_timeout(struct domain *domain,
++ struct wrl_timestampt now,
++ int *ptimeout)
++{
++ uint64_t num, denom;
++ int wakeup;
++
++ wrl_credit_update(domain, now);
++
++ if (domain->wrl_credit >= 0)
++ /* not blocked */
++ return;
++
++ if (!*ptimeout)
++ /* already decided on immediate wakeup,
++ so no need to calculate our timeout */
++ return;
++
++ /* calculate wakeup = now + -credit / (RATE / ndoms); */
++
++ /* credit cannot go more -ve than one transaction,
++ * so the first multiplication cannot overflow even 32-bit */
++ num = (uint64_t)(-domain->wrl_credit * 1000) * wrl_ndomains;
++ denom = wrl_config_rate;
++
++ wakeup = MIN( num / denom /* uint64_t */, INT_MAX );
++ if (*ptimeout==-1 || wakeup < *ptimeout)
++ *ptimeout = wakeup;
++
++ trace("wrl: domain %u credit=%ld (reserve=%ld) SLEEPING for %d\n",
++ domain->domid,
++ (long)domain->wrl_credit, (long)wrl_reserve,
++ wakeup);
++}
++
++void wrl_apply_debit_actual(struct domain *domain)
++{
++ struct wrl_timestampt now;
++
++ if (!domain)
++ /* sockets escape the write rate limit */
++ return;
++
++ wrl_gettime_now(&now);
++ wrl_credit_update(domain, now);
++
++ domain->wrl_credit -= wrl_config_writecost;
++ trace("wrl: domain %u credit=%ld (reserve=%ld)\n",
++ domain->domid,
++ (long)domain->wrl_credit, (long)wrl_reserve);
++}
++
++void wrl_apply_debit_direct(struct connection *conn)
++{
++ if (!conn)
++ /* some writes are generated internally */
++ return;
++
++ if (conn->transaction)
++ /* these are accounted for when the transaction ends */
++ return;
++
++ if (!wrl_ntransactions)
++ /* we don't conflict with anyone */
++ return;
++
++ wrl_apply_debit_actual(conn->domain);
++}
++
++void wrl_apply_debit_trans_commit(struct connection *conn)
++{
++ if (wrl_ntransactions <= 1)
++ /* our own transaction appears in the counter */
++ return;
++
++ wrl_apply_debit_actual(conn->domain);
++}
++
+ /*
+ * Local variables:
+ * c-file-style: "linux"
+diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
+index 83488ed..bdc4044 100644
+--- a/tools/xenstore/xenstored_domain.h
++++ b/tools/xenstore/xenstored_domain.h
+@@ -65,4 +65,29 @@ void domain_watch_inc(struct connection *conn);
+ void domain_watch_dec(struct connection *conn);
+ int domain_watch(struct connection *conn);
+
++/* Write rate limiting */
++
++#define WRL_FACTOR 1000 /* for fixed-point arithmetic */
++#define WRL_RATE 200
++#define WRL_DBURST 10
++#define WRL_GBURST 1000
++#define WRL_NEWDOMS 5
++
++struct wrl_timestampt {
++ time_t sec;
++ int msec;
++};
++
++extern long wrl_ntransactions;
++
++void wrl_gettime_now(struct wrl_timestampt *now_ts);
++void wrl_domain_new(struct domain *domain);
++void wrl_domain_destroy(struct domain *domain);
++void wrl_credit_update(struct domain *domain, struct wrl_timestampt now);
++void wrl_check_timeout(struct domain *domain,
++ struct wrl_timestampt now,
++ int *ptimeout);
++void wrl_apply_debit_direct(struct connection *conn);
++void wrl_apply_debit_trans_commit(struct connection *conn);
++
+ #endif /* _XENSTORED_DOMAIN_H */
+diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c
+index d0e4739..a4b328f 100644
+--- a/tools/xenstore/xenstored_transaction.c
++++ b/tools/xenstore/xenstored_transaction.c
+@@ -116,6 +116,7 @@ static int destroy_transaction(void *_transaction)
+ {
+ struct transaction *trans = _transaction;
+
++ wrl_ntransactions--;
+ trace_destroy(trans, "transaction");
+ if (trans->tdb)
+ tdb_close(trans->tdb);
+@@ -179,6 +180,7 @@ void do_transaction_start(struct connection *conn, struct buffered_data *in)
+ talloc_steal(conn, trans);
+ talloc_set_destructor(trans, destroy_transaction);
+ conn->transaction_started++;
++ wrl_ntransactions++;
+
+ snprintf(id_str, sizeof(id_str), "%u", trans->id);
+ send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1);
+@@ -213,6 +215,9 @@ void do_transaction_end(struct connection *conn, const char *arg)
+ send_error(conn, EAGAIN);
+ return;
+ }
++
++ wrl_apply_debit_trans_commit(conn);
++
+ if (!replace_tdb(trans->tdb_name, trans->tdb)) {
+ send_error(conn, errno);
+ return;
+--
+2.1.4
+
Index: head/sysutils/xen-tools47/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
===================================================================
--- head/sysutils/xen-tools47/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
+++ head/sysutils/xen-tools47/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch
@@ -0,0 +1,113 @@
+From 1d713bf29548ee3e48c3170bafe2863d17694e90 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson@eu.citrix.com>
+Date: Sat, 18 Mar 2017 16:39:31 +0000
+Subject: [PATCH 02/15] xenstored: Log when the write transaction rate limit
+ bites
+
+Reported-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
+---
+ tools/xenstore/xenstored_core.c | 1 +
+ tools/xenstore/xenstored_domain.c | 25 +++++++++++++++++++++++++
+ tools/xenstore/xenstored_domain.h | 2 ++
+ 3 files changed, 28 insertions(+)
+
+diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
+index 1aabc93..907b44f 100644
+--- a/tools/xenstore/xenstored_core.c
++++ b/tools/xenstore/xenstored_core.c
+@@ -378,6 +378,7 @@ static void initialize_fds(int sock, int *p_sock_pollfd_idx,
+ POLLIN|POLLPRI);
+
+ wrl_gettime_now(&now);
++ wrl_log_periodic(now);
+
+ list_for_each_entry(conn, &connections, list) {
+ if (conn->domain) {
+diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
+index 486c96f..75cfad1 100644
+--- a/tools/xenstore/xenstored_domain.c
++++ b/tools/xenstore/xenstored_domain.c
+@@ -22,6 +22,7 @@
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <time.h>
++#include <syslog.h>
+
+ #include "utils.h"
+ #include "talloc.h"
+@@ -79,6 +80,7 @@ struct domain
+ /* write rate limit */
+ wrl_creditt wrl_credit; /* [ -wrl_config_writecost, +_dburst ] */
+ struct wrl_timestampt wrl_timestamp;
++ bool wrl_delay_logged;
+ };
+
+ static LIST_HEAD(domains);
+@@ -770,6 +772,7 @@ long wrl_ntransactions;
+
+ static long wrl_ndomains;
+ static wrl_creditt wrl_reserve; /* [-wrl_config_newdoms_dburst, +_gburst ] */
++static time_t wrl_log_last_warning; /* 0: no previous warning */
+
+ void wrl_gettime_now(struct wrl_timestampt *now_wt)
+ {
+@@ -919,6 +922,9 @@ void wrl_check_timeout(struct domain *domain,
+ wakeup);
+ }
+
++#define WRL_LOG(now, ...) \
++ (syslog(LOG_WARNING, "write rate limit: " __VA_ARGS__))
++
+ void wrl_apply_debit_actual(struct domain *domain)
+ {
+ struct wrl_timestampt now;
+@@ -934,6 +940,25 @@ void wrl_apply_debit_actual(struct domain *domain)
+ trace("wrl: domain %u credit=%ld (reserve=%ld)\n",
+ domain->domid,
+ (long)domain->wrl_credit, (long)wrl_reserve);
++
++ if (domain->wrl_credit < 0) {
++ if (!domain->wrl_delay_logged++) {
++ WRL_LOG(now, "domain %ld is affected",
++ (long)domain->domid);
++ } else if (!wrl_log_last_warning) {
++ WRL_LOG(now, "rate limiting restarts");
++ }
++ wrl_log_last_warning = now.sec;
++ }
++}
++
++void wrl_log_periodic(struct wrl_timestampt now)
++{
++ if (wrl_log_last_warning &&
++ (now.sec - wrl_log_last_warning) > WRL_LOGEVERY) {
++ WRL_LOG(now, "not in force recently");
++ wrl_log_last_warning = 0;
++ }
+ }
+
+ void wrl_apply_debit_direct(struct connection *conn)
+diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
+index bdc4044..2b963ed 100644
+--- a/tools/xenstore/xenstored_domain.h
++++ b/tools/xenstore/xenstored_domain.h
+@@ -72,6 +72,7 @@ int domain_watch(struct connection *conn);
+ #define WRL_DBURST 10
+ #define WRL_GBURST 1000
+ #define WRL_NEWDOMS 5
++#define WRL_LOGEVERY 120 /* seconds */
+
+ struct wrl_timestampt {
+ time_t sec;
+@@ -87,6 +88,7 @@ void wrl_credit_update(struct domain *domain, struct wrl_timestampt now);
+ void wrl_check_timeout(struct domain *domain,
+ struct wrl_timestampt now,
+ int *ptimeout);
++void wrl_log_periodic(struct wrl_timestampt now);
+ void wrl_apply_debit_direct(struct connection *conn);
+ void wrl_apply_debit_trans_commit(struct connection *conn);
+
+--
+2.1.4
+
Index: head/sysutils/xen-tools47/files/iasl-qemuu.patch
===================================================================
--- head/sysutils/xen-tools47/files/iasl-qemuu.patch
+++ head/sysutils/xen-tools47/files/iasl-qemuu.patch
@@ -0,0 +1,26 @@
+diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
+index a2d84ecf8f..e86d3eb263 100644
+--- a/hw/i386/acpi-dsdt.dsl
++++ b/hw/i386/acpi-dsdt.dsl
+@@ -62,8 +62,6 @@ DefinitionBlock (
+
+ Scope(\_SB.PCI0) {
+
+- External(ISA, DeviceObj)
+-
+ Device(ISA) {
+ Name(_ADR, 0x00010000)
+
+diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
+index 16eaca3fae..44fa4a9c0c 100644
+--- a/hw/i386/q35-acpi-dsdt.dsl
++++ b/hw/i386/q35-acpi-dsdt.dsl
+@@ -55,8 +55,6 @@ DefinitionBlock (
+ Name(_ADR, 0x00)
+ Name(_UID, 1)
+
+- External(ISA, DeviceObj)
+-
+ // _OSC: based on sample of ACPI3.0b spec
+ Name(SUPP, 0) // PCI _OSC Support Field value
+ Name(CTRL, 0) // PCI _OSC Control Field value
Index: head/sysutils/xen-tools47/files/kdd.patch
===================================================================
--- head/sysutils/xen-tools47/files/kdd.patch
+++ head/sysutils/xen-tools47/files/kdd.patch
@@ -0,0 +1,36 @@
+Subject: [PATCH] tools/kdd: don't use a pointer to an unaligned field.
+
+The 'val' field in the packet is byte-aligned (because it is part of a
+packed struct), but the pointer argument to kdd_rdmsr() has the normal
+alignment constraints for a uint64_t *. Use a local variable to make sure
+the passed pointer has the correct alignment.
+
+Reported-by: Roger Pau Monné <roger.pau@citrix.com>
+Signed-off-by: Tim Deegan <tim@xen.org>
+---
+ tools/debugger/kdd/kdd.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/debugger/kdd/kdd.c b/tools/debugger/kdd/kdd.c
+index 70f007e..1bd5dd5 100644
+--- a/tools/debugger/kdd/kdd.c
++++ b/tools/debugger/kdd/kdd.c
+@@ -710,11 +710,13 @@ static void kdd_handle_read_ctrl(kdd_state *s)
+ static void kdd_handle_read_msr(kdd_state *s)
+ {
+ uint32_t msr = s->rxp.cmd.msr.msr;
++ uint64_t val;
+ int ok;
+ KDD_LOG(s, "Read MSR 0x%"PRIx32"\n", msr);
+
+- ok = (kdd_rdmsr(s->guest, s->cpuid, msr, &s->txp.cmd.msr.val) == 0);
++ ok = (kdd_rdmsr(s->guest, s->cpuid, msr, &val) == 0);
+ s->txp.cmd.msr.msr = msr;
++ s->txp.cmd.msr.val = val;
+ s->txp.cmd.msr.status = (ok ? KDD_STATUS_SUCCESS : KDD_STATUS_FAILURE);
+ kdd_send_cmd(s, KDD_CMD_READ_MSR, 0);
+ }
+--
+2.7.4
+
+
Index: head/sysutils/xen-tools47/files/var_paths.patch
===================================================================
--- head/sysutils/xen-tools47/files/var_paths.patch
+++ head/sysutils/xen-tools47/files/var_paths.patch
@@ -0,0 +1,13 @@
+diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
+index bb3a5d0..b072030 100644
+--- a/config/FreeBSD.mk
++++ b/config/FreeBSD.mk
+@@ -2,3 +2,8 @@ include $(XEN_ROOT)/config/StdGNU.mk
+
+ # No wget on FreeBSD base system
+ WGET = ftp
++
++XEN_LIB_STORED := ${localstatedir}/db/xenstored
++XEN_LOCK_DIR := ${localstatedir}/db
++XEN_PAGING_DIR := ${localstatedir}/db/xen/xenpaging
++XEN_DUMP_DIR := ${localstatedir}/crash/xen
Index: head/sysutils/xen-tools47/files/xsa211-qemuu-4.7.patch
===================================================================
--- head/sysutils/xen-tools47/files/xsa211-qemuu-4.7.patch
+++ head/sysutils/xen-tools47/files/xsa211-qemuu-4.7.patch
@@ -0,0 +1,259 @@
+From 9de536fbc2be97ae887560f08f0fd824efa3d5db Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 14 Feb 2017 19:09:59 +0100
+Subject: [PATCH] cirrus/vnc: zap bitblit support from console code.
+
+There is a special code path (dpy_gfx_copy) to allow graphic emulation
+notify user interface code about bitblit operations carryed out by
+guests. It is supported by cirrus and vnc server. The intended purpose
+is to optimize display scrolls and just send over the scroll op instead
+of a full display update.
+
+This is rarely used these days though because modern guests simply don't
+use the cirrus blitter any more. Any linux guest using the cirrus drm
+driver doesn't. Any windows guest newer than winxp doesn't ship with a
+cirrus driver any more and thus uses the cirrus as simple framebuffer.
+
+So this code tends to bitrot and bugs can go unnoticed for a long time.
+See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
+which fixes a bug lingering in the code for almost a year, added by
+commit "c7628bf vnc: only alloc server surface with clients connected".
+
+Also the vnc server will throttle the frame rate in case it figures the
+network can't keep up (send buffers are full). This doesn't work with
+dpy_gfx_copy, for any copy operation sent to the vnc client we have to
+send all outstanding updates beforehand, otherwise the vnc client might
+run the client side blit on outdated data and thereby corrupt the
+display. So this dpy_gfx_copy "optimization" might even make things
+worse on slow network links.
+
+Lets kill it once for all.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/display/cirrus_vga.c | 12 ++-----
+ include/ui/console.h | 7 ----
+ ui/console.c | 28 ---------------
+ ui/vnc.c | 91 -------------------------------------------------
+ 4 files changed, 3 insertions(+), 135 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 5901250..2841676 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -758,11 +758,6 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ }
+ }
+
+- /* we have to flush all pending changes so that the copy
+- is generated at the appropriate moment in time */
+- if (notify)
+- graphic_hw_update(s->vga.con);
+-
+ (*s->cirrus_rop) (s, s->vga.vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->vga.vram_ptr +
+@@ -771,10 +766,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ s->cirrus_blt_width, s->cirrus_blt_height);
+
+ if (notify) {
+- qemu_console_copy(s->vga.con,
+- sx, sy, dx, dy,
+- s->cirrus_blt_width / depth,
+- s->cirrus_blt_height);
++ dpy_gfx_update(s->vga.con, dx, dy,
++ s->cirrus_blt_width / depth,
++ s->cirrus_blt_height);
+ }
+
+ /* we don't have to notify the display that this portion has
+diff --git a/include/ui/console.h b/include/ui/console.h
+index 047a2b4..ed07065 100644
+--- a/include/ui/console.h
++++ b/include/ui/console.h
+@@ -166,9 +166,6 @@ typedef struct DisplayChangeListenerOps {
+ int x, int y, int w, int h);
+ void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
+ struct DisplaySurface *new_surface);
+- void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
+- int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl,
+ pixman_format_code_t format);
+
+@@ -233,8 +230,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info);
+ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_gfx_replace_surface(QemuConsole *con,
+ DisplaySurface *surface);
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ void dpy_text_cursor(QemuConsole *con, int x, int y);
+ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_text_resize(QemuConsole *con, int w, int h);
+@@ -329,8 +324,6 @@ void text_consoles_set_display(DisplayState *ds);
+ void console_select(unsigned int index);
+ void console_color_init(DisplayState *ds);
+ void qemu_console_resize(QemuConsole *con, int width, int height);
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ DisplaySurface *qemu_console_surface(QemuConsole *con);
+
+ /* console-gl.c */
+diff --git a/ui/console.c b/ui/console.c
+index 75fc492..72d91cb 100644
+--- a/ui/console.c
++++ b/ui/console.c
+@@ -1495,27 +1495,6 @@ static void dpy_refresh(DisplayState *s)
+ }
+ }
+
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- DisplayState *s = con->ds;
+- DisplayChangeListener *dcl;
+-
+- if (!qemu_console_is_visible(con)) {
+- return;
+- }
+- QLIST_FOREACH(dcl, &s->listeners, next) {
+- if (con != (dcl->con ? dcl->con : active_console)) {
+- continue;
+- }
+- if (dcl->ops->dpy_gfx_copy) {
+- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
+- } else { /* TODO */
+- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+- }
+- }
+-}
+-
+ void dpy_text_cursor(QemuConsole *con, int x, int y)
+ {
+ DisplayState *s = con->ds;
+@@ -1968,13 +1947,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
+ dpy_gfx_replace_surface(s, surface);
+ }
+
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- assert(con->console_type == GRAPHIC_CONSOLE);
+- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
+-}
+-
+ DisplaySurface *qemu_console_surface(QemuConsole *console)
+ {
+ return console->surface;
+diff --git a/ui/vnc.c b/ui/vnc.c
+index 52c6809..61ab611 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -908,96 +908,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+ return n;
+ }
+
+-static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+-{
+- /* send bitblit op to the vnc client */
+- vnc_lock_output(vs);
+- vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+- vnc_write_u8(vs, 0);
+- vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
+- vnc_write_u16(vs, src_x);
+- vnc_write_u16(vs, src_y);
+- vnc_unlock_output(vs);
+- vnc_flush(vs);
+-}
+-
+-static void vnc_dpy_copy(DisplayChangeListener *dcl,
+- int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
+- VncState *vs, *vn;
+- uint8_t *src_row;
+- uint8_t *dst_row;
+- int i, x, y, pitch, inc, w_lim, s;
+- int cmp_bytes;
+-
+- vnc_refresh_server_surface(vd);
+- QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
+- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- vs->force_update = 1;
+- vnc_update_client(vs, 1, true);
+- /* vs might be free()ed here */
+- }
+- }
+-
+- /* do bitblit op on the local surface too */
+- pitch = vnc_server_fb_stride(vd);
+- src_row = vnc_server_fb_ptr(vd, src_x, src_y);
+- dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
+- y = dst_y;
+- inc = 1;
+- if (dst_y > src_y) {
+- /* copy backwards */
+- src_row += pitch * (h-1);
+- dst_row += pitch * (h-1);
+- pitch = -pitch;
+- y = dst_y + h - 1;
+- inc = -1;
+- }
+- w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
+- if (w_lim < 0) {
+- w_lim = w;
+- } else {
+- w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT);
+- }
+- for (i = 0; i < h; i++) {
+- for (x = 0; x <= w_lim;
+- x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
+- if (x == w_lim) {
+- if ((s = w - w_lim) == 0)
+- break;
+- } else if (!x) {
+- s = (VNC_DIRTY_PIXELS_PER_BIT -
+- (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
+- s = MIN(s, w_lim);
+- } else {
+- s = VNC_DIRTY_PIXELS_PER_BIT;
+- }
+- cmp_bytes = s * VNC_SERVER_FB_BYTES;
+- if (memcmp(src_row, dst_row, cmp_bytes) == 0)
+- continue;
+- memmove(dst_row, src_row, cmp_bytes);
+- QTAILQ_FOREACH(vs, &vd->clients, next) {
+- if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT),
+- vs->dirty[y]);
+- }
+- }
+- }
+- src_row += pitch - w * VNC_SERVER_FB_BYTES;
+- dst_row += pitch - w * VNC_SERVER_FB_BYTES;
+- y += inc;
+- }
+-
+- QTAILQ_FOREACH(vs, &vd->clients, next) {
+- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
+- }
+- }
+-}
+-
+ static void vnc_mouse_set(DisplayChangeListener *dcl,
+ int x, int y, int visible)
+ {
+@@ -3131,7 +3041,6 @@ static void vnc_listen_websocket_read(void *opaque)
+ static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "vnc",
+ .dpy_refresh = vnc_refresh,
+- .dpy_gfx_copy = vnc_dpy_copy,
+ .dpy_gfx_update = vnc_dpy_update,
+ .dpy_gfx_switch = vnc_dpy_switch,
+ .dpy_gfx_check_format = qemu_pixman_check_format,
+--
+2.1.4
+
Index: head/sysutils/xen-tools47/pkg-descr
===================================================================
--- head/sysutils/xen-tools47/pkg-descr
+++ head/sysutils/xen-tools47/pkg-descr
@@ -0,0 +1,5 @@
+The xl program is the new tool for managing Xen guest domains. The program can
+be used to create, pause, and shutdown domains. It can also be used to list
+current domains, enable or pin VCPUs, and attach or detach virtual block devices
+
+WWW: https://wiki.xen.org/wiki/XL
Index: head/sysutils/xen-tools47/pkg-plist
===================================================================
--- head/sysutils/xen-tools47/pkg-plist
+++ head/sysutils/xen-tools47/pkg-plist
@@ -0,0 +1,606 @@
+bin/pygrub
+bin/xen-cpuid
+bin/xen-detect
+bin/xenalyze
+bin/xencons
+bin/xencov_split
+bin/xenstore
+bin/xenstore-chmod
+bin/xenstore-control
+bin/xenstore-exists
+bin/xenstore-list
+bin/xenstore-ls
+bin/xenstore-read
+bin/xenstore-rm
+bin/xenstore-watch
+bin/xenstore-write
+bin/xentrace_format
+etc/bash_completion.d/xl.sh
+etc/rc.d/xencommons
+etc/rc.d/xendriverdomain
+%%ETCDIR%%/README
+%%ETCDIR%%/README.incompatibilities
+%%ETCDIR%%/cpupool
+%%ETCDIR%%/scripts/block
+%%ETCDIR%%/scripts/hotplugpath.sh
+%%ETCDIR%%/scripts/vif-bridge
+%%ETCDIR%%/xl.conf
+%%ETCDIR%%/xlexample.hvm
+%%ETCDIR%%/xlexample.pvlinux
+include/_libxl_list.h
+include/_libxl_types.h
+include/_libxl_types_json.h
+include/fsimage.h
+include/fsimage_grub.h
+include/fsimage_plugin.h
+include/libxl.h
+include/libxl_event.h
+include/libxl_json.h
+include/libxl_utils.h
+include/libxl_uuid.h
+include/libxlutil.h
+include/xen/COPYING
+include/xen/arch-arm.h
+include/xen/arch-arm/hvm/save.h
+include/xen/arch-x86/cpufeatureset.h
+include/xen/arch-x86/cpuid.h
+include/xen/arch-x86/hvm/save.h
+include/xen/arch-x86/pmu.h
+include/xen/arch-x86/xen-mca.h
+include/xen/arch-x86/xen-x86_32.h
+include/xen/arch-x86/xen-x86_64.h
+include/xen/arch-x86/xen.h
+include/xen/arch-x86_32.h
+include/xen/arch-x86_64.h
+include/xen/callback.h
+include/xen/dom0_ops.h
+include/xen/domctl.h
+include/xen/elfnote.h
+include/xen/errno.h
+include/xen/event_channel.h
+include/xen/features.h
+include/xen/foreign/arm32.h
+include/xen/foreign/arm64.h
+include/xen/foreign/x86_32.h
+include/xen/foreign/x86_64.h
+include/xen/gcov.h
+include/xen/grant_table.h
+include/xen/hvm/e820.h
+include/xen/hvm/hvm_info_table.h
+include/xen/hvm/hvm_op.h
+include/xen/hvm/hvm_vcpu.h
+include/xen/hvm/hvm_xs_strings.h
+include/xen/hvm/ioreq.h
+include/xen/hvm/params.h
+include/xen/hvm/pvdrivers.h
+include/xen/hvm/save.h
+include/xen/io/blkif.h
+include/xen/io/console.h
+include/xen/io/fbif.h
+include/xen/io/fsif.h
+include/xen/io/kbdif.h
+include/xen/io/libxenvchan.h
+include/xen/io/netif.h
+include/xen/io/pciif.h
+include/xen/io/protocols.h
+include/xen/io/ring.h
+include/xen/io/tpmif.h
+include/xen/io/usbif.h
+include/xen/io/vscsiif.h
+include/xen/io/xenbus.h
+include/xen/io/xs_wire.h
+include/xen/kexec.h
+include/xen/memory.h
+include/xen/nmi.h
+include/xen/physdev.h
+include/xen/platform.h
+include/xen/pmu.h
+include/xen/sched.h
+include/xen/sys/evtchn.h
+include/xen/sys/privcmd.h
+include/xen/sysctl.h
+include/xen/tmem.h
+include/xen/trace.h
+include/xen/vcpu.h
+include/xen/version.h
+include/xen/vm_event.h
+include/xen/xen-compat.h
+include/xen/xen.h
+include/xen/xencomm.h
+include/xen/xenoprof.h
+include/xen/xsm/flask_op.h
+include/xencall.h
+include/xenctrl.h
+include/xenctrl_compat.h
+include/xenevtchn.h
+include/xenforeignmemory.h
+include/xengnttab.h
+include/xenguest.h
+include/xenstat.h
+include/xenstore-compat/xs.h
+include/xenstore-compat/xs_lib.h
+include/xenstore.h
+include/xenstore_lib.h
+include/xentoollog.h
+include/xs.h
+include/xs_lib.h
+lib/fs/ext2fs/fsimage.so
+lib/fs/fat/fsimage.so
+lib/fs/iso9660/fsimage.so
+lib/fs/reiserfs/fsimage.so
+lib/fs/ufs/fsimage.so
+lib/fs/xfs/fsimage.so
+lib/fs/zfs/fsimage.so
+lib/libfsimage.so
+lib/libfsimage.so.1.0
+lib/libfsimage.so.1.0.0
+lib/libxencall.a
+lib/libxencall.so
+lib/libxencall.so.1
+lib/libxencall.so.1.0
+lib/libxenctrl.a
+lib/libxenctrl.so
+lib/libxenctrl.so.4.7
+lib/libxenctrl.so.4.7.0
+lib/libxenevtchn.a
+lib/libxenevtchn.so
+lib/libxenevtchn.so.1
+lib/libxenevtchn.so.1.0
+lib/libxenforeignmemory.a
+lib/libxenforeignmemory.so
+lib/libxenforeignmemory.so.1
+lib/libxenforeignmemory.so.1.0
+lib/libxengnttab.a
+lib/libxengnttab.so
+lib/libxengnttab.so.1
+lib/libxengnttab.so.1.0
+lib/libxenguest.a
+lib/libxenguest.so
+lib/libxenguest.so.4.7
+lib/libxenguest.so.4.7.0
+lib/libxenlight.a
+lib/libxenlight.so
+lib/libxenlight.so.4.7
+lib/libxenlight.so.4.7.0
+lib/libxenstat.a
+lib/libxenstat.so
+lib/libxenstat.so.0
+lib/libxenstat.so.0.0
+lib/libxenstore.a
+lib/libxenstore.so
+lib/libxenstore.so.3.0
+lib/libxenstore.so.3.0.3
+lib/libxentoollog.a
+lib/libxentoollog.so
+lib/libxentoollog.so.1
+lib/libxentoollog.so.1.0
+lib/libxlutil.a
+lib/libxlutil.so
+lib/libxlutil.so.4.7
+lib/libxlutil.so.4.7.0
+%%PYTHON_SITELIBDIR%%/fsimage.so
+%%PYTHON_SITELIBDIR%%/grub/ExtLinuxConf.py
+%%PYTHON_SITELIBDIR%%/grub/ExtLinuxConf.pyc
+%%PYTHON_SITELIBDIR%%/grub/GrubConf.py
+%%PYTHON_SITELIBDIR%%/grub/GrubConf.pyc
+%%PYTHON_SITELIBDIR%%/grub/LiloConf.py
+%%PYTHON_SITELIBDIR%%/grub/LiloConf.pyc
+%%PYTHON_SITELIBDIR%%/grub/__init__.py
+%%PYTHON_SITELIBDIR%%/grub/__init__.pyc
+%%PYTHON_SITELIBDIR%%/pygrub-0.3-py%%PYTHON_VER%%.egg-info
+%%PYTHON_SITELIBDIR%%/xen-3.0-py%%PYTHON_VER%%.egg-info
+%%PYTHON_SITELIBDIR%%/xen/__init__.py
+%%PYTHON_SITELIBDIR%%/xen/__init__.pyc
+%%PYTHON_SITELIBDIR%%/xen/lowlevel/__init__.py
+%%PYTHON_SITELIBDIR%%/xen/lowlevel/__init__.pyc
+%%PYTHON_SITELIBDIR%%/xen/lowlevel/xc.so
+%%PYTHON_SITELIBDIR%%/xen/lowlevel/xs.so
+%%PYTHON_SITELIBDIR%%/xen/migration/__init__.py
+%%PYTHON_SITELIBDIR%%/xen/migration/__init__.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/legacy.py
+%%PYTHON_SITELIBDIR%%/xen/migration/legacy.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/libxc.py
+%%PYTHON_SITELIBDIR%%/xen/migration/libxc.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/libxl.py
+%%PYTHON_SITELIBDIR%%/xen/migration/libxl.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/public.py
+%%PYTHON_SITELIBDIR%%/xen/migration/public.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/tests.py
+%%PYTHON_SITELIBDIR%%/xen/migration/tests.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/verify.py
+%%PYTHON_SITELIBDIR%%/xen/migration/verify.pyc
+%%PYTHON_SITELIBDIR%%/xen/migration/xl.py
+%%PYTHON_SITELIBDIR%%/xen/migration/xl.pyc
+lib/xen/bin/convert-legacy-stream
+lib/xen/bin/libxl-save-helper
+lib/xen/bin/lsevtchn
+lib/xen/bin/pygrub
+lib/xen/bin/qemu-system-i386
+lib/xen/bin/readnotes
+lib/xen/bin/verify-stream-v2
+lib/xen/bin/xen-init-dom0
+lib/xen/bin/xenconsole
+lib/xen/bin/xenctx
+lib/xen/bin/xenpaging
+lib/xen/bin/xenpvnetboot
+lib/xen/boot/hvmloader
+man/man1/xenstore-chmod.1.gz
+man/man1/xenstore-ls.1.gz
+man/man1/xenstore.1.gz
+man/man1/xentop.1.gz
+man/man1/xentrace_format.1.gz
+man/man1/xl.1.gz
+man/man5/xl.cfg.5.gz
+man/man5/xl.conf.5.gz
+man/man5/xlcpupool.cfg.5.gz
+man/man8/xentrace.8.gz
+sbin/flask-get-bool
+sbin/flask-getenforce
+sbin/flask-label-pci
+sbin/flask-loadpolicy
+sbin/flask-set-bool
+sbin/flask-setenforce
+sbin/gdbsx
+sbin/gtracestat
+sbin/gtraceview
+sbin/kdd
+sbin/xen-bugtool
+sbin/xen-hptool
+sbin/xen-hvmcrash
+sbin/xen-hvmctx
+sbin/xen-lowmemd
+sbin/xen-mfndump
+sbin/xen-ringwatch
+sbin/xen-tmem-list-parse
+sbin/xen-livepatch
+sbin/xenbaked
+sbin/xenconsoled
+sbin/xencov
+sbin/xenlockprof
+sbin/xenmon.py
+sbin/xenperf
+sbin/xenpm
+sbin/xenpmd
+sbin/xenstored
+sbin/xentop
+sbin/xentrace
+sbin/xentrace_setmask
+sbin/xentrace_setsize
+sbin/xenwatchdogd
+sbin/xl
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/.deps
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,arch-arm,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,arch-arm.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,callback.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,dom0_ops.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,domctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,elfnote.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,event_channel.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,features.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,gcov.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,grant_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,e820.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_info_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,hvm_xs_strings.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,ioreq.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,params.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,pvdrivers.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,blkif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,console.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,fbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,fsif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,kbdif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,libxenvchan.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,netif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,pciif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,protocols.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,ring.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,tpmif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,usbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,vscsiif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,xenbus.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,io,xs_wire.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,kexec.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,memory.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,nmi.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,physdev.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,platform.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,pmu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,sched.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,sysctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,tmem.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,trace.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,version.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,vm_event.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xen-compat.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xen.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xencomm.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xenoprof.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,public,xsm,flask_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/include,xen,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/arm/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/.deps
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,cpufeatureset.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,cpuid.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,pmu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen-mca.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen-x86_32.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86,xen.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,arch-x86_32.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,callback.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,dom0_ops.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,domctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,elfnote.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,event_channel.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,features.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,gcov.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,grant_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,e820.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_info_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,hvm_xs_strings.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,ioreq.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,params.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,pvdrivers.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,blkif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,console.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,fbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,fsif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,kbdif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,libxenvchan.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,netif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,pciif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,protocols.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,ring.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,tpmif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,usbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,vscsiif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,xenbus.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,io,xs_wire.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,kexec.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,memory.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,nmi.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,physdev.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,platform.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,pmu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,sched.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,sysctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,tmem.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,trace.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,version.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,vm_event.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xen-compat.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xen.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xencomm.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xenoprof.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,public,xsm,flask_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/include,xen,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_32/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/.deps
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,cpufeatureset.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,cpuid.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,pmu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen-mca.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen-x86_64.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86,xen.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,arch-x86_64.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,callback.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,dom0_ops.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,domctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,elfnote.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,event_channel.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,features.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,gcov.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,grant_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,e820.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_info_table.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,hvm_xs_strings.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,ioreq.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,params.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,pvdrivers.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,hvm,save.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,blkif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,console.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,fbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,fsif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,kbdif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,libxenvchan.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,netif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,pciif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,protocols.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,ring.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,tpmif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,usbif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,vscsiif.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,xenbus.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,io,xs_wire.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,kexec.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,memory.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,nmi.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,physdev.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,platform.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,pmu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,sched.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,sysctl.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,tmem.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,trace.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,vcpu.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,version.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,vm_event.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xen-compat.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xen.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xencomm.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xenoprof.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,public,xsm,flask_op.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/include,xen,errno.h.html
+%%PORTDOCS%%%%DOCSDIR%%/html/hypercall/x86_64/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore-chmod.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore-ls.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xenstore.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xentop.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xentrace.8.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xentrace_format.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.1.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.cfg.5.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xl.conf.5.html
+%%PORTDOCS%%%%DOCSDIR%%/html/man/xlcpupool.cfg.5.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/amd-ucode-container.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/booting.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/booting.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/guest.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/device-tree/passthrough.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/early-printk.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/arm/passthrough.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/block-scripts.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/channel.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/console.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/coverage.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/crashdb.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/distro_mapping.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/dump-core-format.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/efi.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/grant-tables.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/hvm-emulated-unplug.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/hvmlite.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/index.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/kconfig-language.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/kconfig.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/kexec_and_kdump.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/libxl_memory.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/pci-device-reservations.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/printk-formats.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/pvh-readme.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/pvh.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/qemu-backends.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/qemu-deprivilege.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/stubdom.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/tscmode.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vbd-interface.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtd-pi.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtd.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpm-platforms.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpm.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/vtpmmgr.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/x86-xenpv-bootloader.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xen-command-line.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xen-error-handling.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenmon.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenpaging.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore-paths.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore-ring.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xenstore.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-disk-configuration.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-network-configuration.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-numa-placement.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xl-psr.html
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/xsm-flask.txt
+%%PORTDOCS%%%%DOCSDIR%%/html/misc/livepatch.html
+libdata/pkgconfig/xenlight.pc
+libdata/pkgconfig/xlutil.pc
+share/qemu-xen/qemu/QEMU,cgthree.bin
+share/qemu-xen/qemu/QEMU,tcx.bin
+share/qemu-xen/qemu/acpi-dsdt.aml
+share/qemu-xen/qemu/bamboo.dtb
+share/qemu-xen/qemu/bios-256k.bin
+share/qemu-xen/qemu/bios.bin
+share/qemu-xen/qemu/efi-e1000.rom
+share/qemu-xen/qemu/efi-eepro100.rom
+share/qemu-xen/qemu/efi-ne2k_pci.rom
+share/qemu-xen/qemu/efi-pcnet.rom
+share/qemu-xen/qemu/efi-rtl8139.rom
+share/qemu-xen/qemu/efi-virtio.rom
+share/qemu-xen/qemu/keymaps/ar
+share/qemu-xen/qemu/keymaps/bepo
+share/qemu-xen/qemu/keymaps/common
+share/qemu-xen/qemu/keymaps/cz
+share/qemu-xen/qemu/keymaps/da
+share/qemu-xen/qemu/keymaps/de
+share/qemu-xen/qemu/keymaps/de-ch
+share/qemu-xen/qemu/keymaps/en-gb
+share/qemu-xen/qemu/keymaps/en-us
+share/qemu-xen/qemu/keymaps/es
+share/qemu-xen/qemu/keymaps/et
+share/qemu-xen/qemu/keymaps/fi
+share/qemu-xen/qemu/keymaps/fo
+share/qemu-xen/qemu/keymaps/fr
+share/qemu-xen/qemu/keymaps/fr-be
+share/qemu-xen/qemu/keymaps/fr-ca
+share/qemu-xen/qemu/keymaps/fr-ch
+share/qemu-xen/qemu/keymaps/hr
+share/qemu-xen/qemu/keymaps/hu
+share/qemu-xen/qemu/keymaps/is
+share/qemu-xen/qemu/keymaps/it
+share/qemu-xen/qemu/keymaps/ja
+share/qemu-xen/qemu/keymaps/lt
+share/qemu-xen/qemu/keymaps/lv
+share/qemu-xen/qemu/keymaps/mk
+share/qemu-xen/qemu/keymaps/modifiers
+share/qemu-xen/qemu/keymaps/nl
+share/qemu-xen/qemu/keymaps/nl-be
+share/qemu-xen/qemu/keymaps/no
+share/qemu-xen/qemu/keymaps/pl
+share/qemu-xen/qemu/keymaps/pt
+share/qemu-xen/qemu/keymaps/pt-br
+share/qemu-xen/qemu/keymaps/ru
+share/qemu-xen/qemu/keymaps/sl
+share/qemu-xen/qemu/keymaps/sv
+share/qemu-xen/qemu/keymaps/th
+share/qemu-xen/qemu/keymaps/tr
+share/qemu-xen/qemu/kvmvapic.bin
+share/qemu-xen/qemu/linuxboot.bin
+share/qemu-xen/qemu/multiboot.bin
+share/qemu-xen/qemu/openbios-ppc
+share/qemu-xen/qemu/openbios-sparc32
+share/qemu-xen/qemu/openbios-sparc64
+share/qemu-xen/qemu/palcode-clipper
+share/qemu-xen/qemu/petalogix-ml605.dtb
+share/qemu-xen/qemu/petalogix-s3adsp1800.dtb
+share/qemu-xen/qemu/ppc_rom.bin
+share/qemu-xen/qemu/pxe-e1000.rom
+share/qemu-xen/qemu/pxe-eepro100.rom
+share/qemu-xen/qemu/pxe-ne2k_pci.rom
+share/qemu-xen/qemu/pxe-pcnet.rom
+share/qemu-xen/qemu/pxe-rtl8139.rom
+share/qemu-xen/qemu/pxe-virtio.rom
+share/qemu-xen/qemu/q35-acpi-dsdt.aml
+share/qemu-xen/qemu/qemu-icon.bmp
+share/qemu-xen/qemu/qemu_logo_no_text.svg
+share/qemu-xen/qemu/s390-ccw.img
+share/qemu-xen/qemu/s390-zipl.rom
+share/qemu-xen/qemu/sgabios.bin
+share/qemu-xen/qemu/slof.bin
+share/qemu-xen/qemu/spapr-rtas.bin
+share/qemu-xen/qemu/trace-events
+share/qemu-xen/qemu/u-boot.e500
+share/qemu-xen/qemu/vgabios-cirrus.bin
+share/qemu-xen/qemu/vgabios-qxl.bin
+share/qemu-xen/qemu/vgabios-stdvga.bin
+share/qemu-xen/qemu/vgabios-virtio.bin
+share/qemu-xen/qemu/vgabios-vmware.bin
+share/qemu-xen/qemu/vgabios.bin
+@dir %%ETCDIR%%/auto
+@dir /var/crash/xen
+@dir /var/db/xen/xenpaging
+@dir /var/db/xen
+@dir /var/db/xenstored
+@dir /var/log/xen
+@dir /var/run/xen

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 4, 5:19 AM (21 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16448440
Default Alt Text
D16416.diff (725 KB)

Event Timeline