Index: MOVED =================================================================== --- MOVED +++ MOVED @@ -10355,3 +10355,5 @@ 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 Index: emulators/xen-kernel/Makefile =================================================================== --- /dev/null +++ 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 - -.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 Index: emulators/xen-kernel/distinfo =================================================================== --- /dev/null +++ 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: emulators/xen-kernel/files/0001-IOMMU-handle-IOMMU-mapping-and-unmapping-failures.patch =================================================================== --- /dev/null +++ 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 -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 -Reviewed-by: Kevin Tian -Reviewed-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0001-gnttab-Fix-handling-of-dev_bus_addr-during-unmap.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0001-p2m-Always-check-to-see-if-removing-a-p2m-entry-actu.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Reviewed-by: Jan Beulich ---- -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: emulators/xen-kernel/files/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch =================================================================== --- /dev/null +++ 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 -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 -Reviewed-by: Andrew Cooper -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: emulators/xen-kernel/files/0001-x86-compat-fix-compilation-errors-with-clang-6.patch =================================================================== --- /dev/null +++ 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 -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é ---- -Cc: Andrew Cooper -Cc: George Dunlap -Cc: Ian Jackson -Cc: Jan Beulich -Cc: Konrad Rzeszutek Wilk -Cc: Stefano Stabellini -Cc: Tim Deegan -Cc: Wei Liu ---- -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: emulators/xen-kernel/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch @@ -1,27 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/0001-x86-drop-unneeded-__packed-attributes.patch =================================================================== --- /dev/null +++ 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?= -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é -Reviewed-by: Jan Beulich -Reviewed-by: Boris Ostrovsky ---- - 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: emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch =================================================================== --- /dev/null +++ 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 -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 -Reviewed-by: Wei Liu -Acked-by: Jan Beulich -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 - #include --#include /* mark_regs_dirty() */ - #include /* current_cpu_info */ - #include /* 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 = ®s->r9; break; - case 10: p = ®s->r10; break; - case 11: p = ®s->r11; break; -- case 12: mark_regs_dirty(regs); p = ®s->r12; break; -- case 13: mark_regs_dirty(regs); p = ®s->r13; break; -- case 14: mark_regs_dirty(regs); p = ®s->r14; break; -- case 15: mark_regs_dirty(regs); p = ®s->r15; break; -+ case 12: p = ®s->r12; break; -+ case 13: p = ®s->r13; break; -+ case 14: p = ®s->r14; break; -+ case 15: p = ®s->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: emulators/xen-kernel/files/0001-x86-limit-linear-page-table-use-to-a-single-level.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: Jan Beulich -Signed-off-by: George Dunlap ---- - 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< -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 -Reviewed-by: Jan Beulich -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: emulators/xen-kernel/files/0001-xen-logdirty-prevent-preemption-if-finished.patch =================================================================== --- /dev/null +++ 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 -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é ---- - 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: emulators/xen-kernel/files/0002-build-clang-fix-XSM-dummy-policy-when-using-clang-4..patch =================================================================== --- /dev/null +++ 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 -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é ---- -Cc: Daniel De Graaf ---- - 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: emulators/xen-kernel/files/0002-gnttab-fix-unmap-pin-accounting-race.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0002-gnttab-never-create-host-mapping-unless-asked-to.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0002-p2m-Check-return-value-of-p2m_set_entry-when-decreas.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Reviewed-by: Jan Beulich ---- -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<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: emulators/xen-kernel/files/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch =================================================================== --- /dev/null +++ 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 -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 -Reviewed-by: Andrew Cooper -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 -+> `= ` -+ -+> 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 - > `= ` - -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: emulators/xen-kernel/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch @@ -1,66 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: George Dunlap - ---- 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: emulators/xen-kernel/files/0002-x86-mm-Disable-PV-linear-pagetables-by-default.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Reviewed-by: Andrew Cooper ---- -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 -+> `= ` -+ -+> 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: emulators/xen-kernel/files/0002-xen-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch =================================================================== --- /dev/null +++ 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 -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é -Cc: Tim Deegan -Cc: Jan Beulich -Cc: Andrew Cooper ---- -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: emulators/xen-kernel/files/0003-gnttab-Avoid-potential-double-put-of-maptrack-entry.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0003-gnttab-correct-logic-to-get-page-references-during-m.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: George Dunlap -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0003-x86-MSI-disallow-redundant-enabling.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/0003-x86-MSI-disallow-redundant-enabling.patch @@ -1,55 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper -Reviewed-by: George Dunlap - ---- 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: emulators/xen-kernel/files/0004-gnttab-__gnttab_unmap_common_complete-is-all-or-noth.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/0004-gnttab-correct-maptrack-table-accesses.patch =================================================================== --- /dev/null +++ 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 -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 -Reviewed-by: George Dunlap ---- - 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: emulators/xen-kernel/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch @@ -1,124 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: George Dunlap - ---- 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: emulators/xen-kernel/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch @@ -1,37 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/kconf_arch.patch =================================================================== --- /dev/null +++ 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: emulators/xen-kernel/files/xen.4th =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xen.4th @@ -1,99 +0,0 @@ -\ Copyright (c) 2015 Devin Teske -\ 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: emulators/xen-kernel/files/xsa212.patch =================================================================== --- /dev/null +++ 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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa213-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa213-4.7.patch @@ -1,173 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper -Acked-by: Julien Grall - ---- 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 = ¤t->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 - -+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: emulators/xen-kernel/files/xsa214.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa214.patch @@ -1,41 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa215.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa215.patch @@ -1,37 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa217.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa217.patch @@ -1,41 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Acked-by: George Dunlap -Reviewed-by: Konrad Rzeszutek Wilk - ---- 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: emulators/xen-kernel/files/xsa219-4.8.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa219-4.8.patch @@ -1,151 +0,0 @@ -From 3986b845e87c3f963227ece86bb633450761ec18 Mon Sep 17 00:00:00 2001 -From: Andrew Cooper -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 -Signed-off-by: Andrew Cooper -Reviewed-by: Jan Beulich -Reviewed-by: Tim Deegan ---- - 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: emulators/xen-kernel/files/xsa220-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa220-4.7.patch @@ -1,133 +0,0 @@ -From: Jan Beulich -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, 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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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 - #include - #include -+#include - #include - #include - #include -@@ -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: emulators/xen-kernel/files/xsa221.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa221.patch @@ -1,194 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich - ---- 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: emulators/xen-kernel/files/xsa222-1-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa222-1-4.7.patch @@ -1,119 +0,0 @@ -From: Andrew Cooper -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 -Signed-off-by: Andrew Cooper -Reviewed-by: Jan Beulich - ---- 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: emulators/xen-kernel/files/xsa222-2-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa222-2-4.7.patch @@ -1,412 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Signed-off-by: Julien Grall -Reviewed-by: Andrew Cooper - ---- 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<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 - #include - - /* -@@ -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: emulators/xen-kernel/files/xsa226-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa226-4.7.patch @@ -1,133 +0,0 @@ -From: Andrew Cooper -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 -Signed-off-by: Andrew Cooper -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:, 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 - > `= ` - -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: emulators/xen-kernel/files/xsa227.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa227.patch @@ -1,52 +0,0 @@ -From fa7268b94f8a0a7792ee12d5b8e23a60e52a3a84 Mon Sep 17 00:00:00 2001 -From: Andrew Cooper -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 -Reviewed-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/xsa228-4.8.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa228-4.8.patch @@ -1,198 +0,0 @@ -From cb91f4c43bd4158daa6561c73921a6455176f278 Mon Sep 17 00:00:00 2001 -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Signed-off-by: Ian Jackson ---- - 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: emulators/xen-kernel/files/xsa230.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa230.patch @@ -1,38 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: Andrew Cooper -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: emulators/xen-kernel/files/xsa231-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa231-4.7.patch @@ -1,108 +0,0 @@ -From: George Dunlap -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 -Signed-off-by: George Dunlap -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa232.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa232.patch @@ -1,23 +0,0 @@ -From: Andrew Cooper -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 -Signed-off-by: Andrew Cooper -Reviewed-by: Jan Beulich - ---- 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: emulators/xen-kernel/files/xsa233.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa233.patch @@ -1,52 +0,0 @@ -From: Juergen Gross -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 -Signed-off-by: Juergen Gross -Reviewed-by: Ian Jackson - ---- 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: emulators/xen-kernel/files/xsa234-4.8.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa234-4.8.patch @@ -1,185 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa236-4.9.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa236-4.9.patch @@ -1,66 +0,0 @@ -From: Jan Beulich -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 -Signed-off-by: Jan Beulich -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/files/xsa238.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa238.patch @@ -1,45 +0,0 @@ -From cdc2887076b19b39fab9faec495082586f3113df Mon Sep 17 00:00:00 2001 -From: XenProject Security Team -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 -Reviewed-by: Jan Beulich ---- - 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: emulators/xen-kernel/files/xsa239.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa239.patch @@ -1,46 +0,0 @@ -From: Jan Beulich -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é -Reviewed-by: Roger Pau Monné -Signed-off-by: Jan Beulich - ---- 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: emulators/xen-kernel/files/xsa241-4.8.patch =================================================================== --- /dev/null +++ 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 -Suggested-by: George Dunlap -Signed-off-by: Jan Beulich -Reviewed-by: George Dunlap - ---- a/xen/arch/arm/smp.c -+++ b/xen/arch/arm/smp.c -@@ -1,4 +1,5 @@ - #include -+#include - #include - #include - #include ---- 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 - #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: emulators/xen-kernel/files/xsa242-4.9.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa242-4.9.patch @@ -1,43 +0,0 @@ -From: Jan Beulich -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 - ---- 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: emulators/xen-kernel/files/xsa243-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa243-4.7.patch @@ -1,93 +0,0 @@ -From: Andrew Cooper -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 -Acked-by: Tim Deegan - -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: emulators/xen-kernel/files/xsa244-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa244-4.7.patch @@ -1,51 +0,0 @@ -From: Andrew Cooper -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 -Reviewed-by: Jan Beulich - ---- 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: emulators/xen-kernel/files/xsa246-4.7.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa246-4.7.patch @@ -1,74 +0,0 @@ -From: Julien Grall -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 -Signed-off-by: Jan Beulich -Reviewed-by: George Dunlap - ---- 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)<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: emulators/xen-kernel/files/xsa248-4.8.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa248-4.8.patch @@ -1,162 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: Tim Deegan -Reviewed-by: George Dunlap - ---- 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: emulators/xen-kernel/files/xsa249.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa249.patch @@ -1,42 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: George Dunlap -Reviewed-by: Tim Deegan ---- -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: emulators/xen-kernel/files/xsa250.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa250.patch @@ -1,67 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: Tim Deegan - ---- 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: emulators/xen-kernel/files/xsa251-4.8.patch =================================================================== --- /dev/null +++ emulators/xen-kernel/files/xsa251-4.8.patch @@ -1,21 +0,0 @@ -From: Jan Beulich -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 -Reviewed-by: Andrew Cooper - ---- 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: emulators/xen-kernel/pkg-descr =================================================================== --- /dev/null +++ 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: emulators/xen-kernel/pkg-message =================================================================== --- /dev/null +++ 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: emulators/xen/Makefile =================================================================== --- emulators/xen/Makefile +++ /dev/null @@ -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 Index: emulators/xen/pkg-descr =================================================================== --- emulators/xen/pkg-descr +++ /dev/null @@ -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: sysutils/xen-tools/Makefile =================================================================== --- /dev/null +++ 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 - -.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 Index: sysutils/xen-tools/distinfo =================================================================== --- /dev/null +++ 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: sysutils/xen-tools/files/0001-Backport-of-commit-858dba.patch =================================================================== --- /dev/null +++ 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 -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: sysutils/xen-tools/files/0001-libs-xenstore-set-correct-FreeBSD-device.patch =================================================================== --- /dev/null +++ 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 -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é -Acked-by: Wei Liu ---- - 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: sysutils/xen-tools/files/0001-libxl-fix-creation-of-pkgconf-install-dir.patch =================================================================== --- /dev/null +++ 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 -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é -Acked-by: Wei Liu -Release-acked-by: Wei Liu ---- - 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: sysutils/xen-tools/files/0001-tools-configure-fix-pkg-config-install-path-for-Free.patch =================================================================== --- /dev/null +++ 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 -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é -Reported-by: Alexander Nusov -Acked-by: Wei Liu -Release-acked-by: Wei Liu ---- - 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: sysutils/xen-tools/files/0001-xenstored-apply-a-write-transaction-rate-limit.patch =================================================================== --- /dev/null +++ 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 -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 - -Backported to 4.8 (not entirely trivial). - -Reported-by: Juergen Gross -Signed-off-by: George Dunlap -Acked-by: Ian Jackson ---- - 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 - #include - #include -+#include - - #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: sysutils/xen-tools/files/0002-xenstored-Log-when-the-write-transaction-rate-limit-.patch =================================================================== --- /dev/null +++ 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 -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 -Signed-off-by: Ian Jackson ---- - 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 - #include - #include -+#include - - #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: sysutils/xen-tools/files/iasl-qemuu.patch =================================================================== --- /dev/null +++ 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: sysutils/xen-tools/files/kdd.patch =================================================================== --- /dev/null +++ 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é -Signed-off-by: Tim Deegan ---- - 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: sysutils/xen-tools/files/var_paths.patch =================================================================== --- /dev/null +++ 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: sysutils/xen-tools/files/xsa211-qemuu-4.7.patch =================================================================== --- /dev/null +++ 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 -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 ---- - 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: sysutils/xen-tools/pkg-descr =================================================================== --- /dev/null +++ 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: sysutils/xen-tools/pkg-plist =================================================================== --- /dev/null +++ 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