--- /dev/null
+xen-x86-don-t-bail-early-from-clear_foreign_p2m_mapping.patch
+xen-x86-also-check-kernel-mapping-in-set_foreign_p2m_mapping.patch
+xen-gntdev-correct-dev_bus_addr-handling-in-gntdev_map_grant_pages.patch
--- /dev/null
+From dbe5283605b3bc12ca45def09cc721a0a5c853a2 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Mon, 15 Feb 2021 08:51:07 +0100
+Subject: Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
+
+From: Jan Beulich <jbeulich@suse.com>
+
+commit dbe5283605b3bc12ca45def09cc721a0a5c853a2 upstream.
+
+We may not skip setting the field in the unmap structure when
+GNTMAP_device_map is in use - such an unmap would fail to release the
+respective resources (a page ref in the hypervisor). Otoh the field
+doesn't need setting at all when GNTMAP_device_map is not in use.
+
+To record the value for unmapping, we also better don't use our local
+p2m: In particular after a subsequent change it may not have got updated
+for all the batch elements. Instead it can simply be taken from the
+respective map's results.
+
+We can additionally avoid playing this game altogether for the kernel
+part of the mappings in (x86) PV mode.
+
+This is part of XSA-361.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/xen/gntdev.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+--- a/drivers/xen/gntdev.c
++++ b/drivers/xen/gntdev.c
+@@ -309,18 +309,25 @@ int gntdev_map_grant_pages(struct gntdev
+ * to the kernel linear addresses of the struct pages.
+ * These ptes are completely different from the user ptes dealt
+ * with find_grant_ptes.
++ * Note that GNTMAP_device_map isn't needed here: The
++ * dev_bus_addr output field gets consumed only from ->map_ops,
++ * and by not requesting it when mapping we also avoid needing
++ * to mirror dev_bus_addr into ->unmap_ops (and holding an extra
++ * reference to the page in the hypervisor).
+ */
++ unsigned int flags = (map->flags & ~GNTMAP_device_map) |
++ GNTMAP_host_map;
++
+ for (i = 0; i < map->count; i++) {
+ unsigned long address = (unsigned long)
+ pfn_to_kaddr(page_to_pfn(map->pages[i]));
+ BUG_ON(PageHighMem(map->pages[i]));
+
+- gnttab_set_map_op(&map->kmap_ops[i], address,
+- map->flags | GNTMAP_host_map,
++ gnttab_set_map_op(&map->kmap_ops[i], address, flags,
+ map->grants[i].ref,
+ map->grants[i].domid);
+ gnttab_set_unmap_op(&map->kunmap_ops[i], address,
+- map->flags | GNTMAP_host_map, -1);
++ flags, -1);
+ }
+ }
+
+@@ -336,17 +343,12 @@ int gntdev_map_grant_pages(struct gntdev
+ continue;
+ }
+
++ if (map->flags & GNTMAP_device_map)
++ map->unmap_ops[i].dev_bus_addr = map->map_ops[i].dev_bus_addr;
++
+ map->unmap_ops[i].handle = map->map_ops[i].handle;
+ if (use_ptemod)
+ map->kunmap_ops[i].handle = map->kmap_ops[i].handle;
+-#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
+- else if (map->dma_vaddr) {
+- unsigned long bfn;
+-
+- bfn = pfn_to_bfn(page_to_pfn(map->pages[i]));
+- map->unmap_ops[i].dev_bus_addr = __pfn_to_phys(bfn);
+- }
+-#endif
+ }
+ return err;
+ }
--- /dev/null
+From b512e1b077e5ccdbd6e225b15d934ab12453b70a Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Mon, 15 Feb 2021 08:50:08 +0100
+Subject: Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
+
+From: Jan Beulich <jbeulich@suse.com>
+
+commit b512e1b077e5ccdbd6e225b15d934ab12453b70a upstream.
+
+We should not set up further state if either mapping failed; paying
+attention to just the user mapping's status isn't enough.
+
+Also use GNTST_okay instead of implying its value (zero).
+
+This is part of XSA-361.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/xen/p2m.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/xen/p2m.c
++++ b/arch/x86/xen/p2m.c
+@@ -712,7 +712,8 @@ int set_foreign_p2m_mapping(struct gntta
+ unsigned long mfn, pfn;
+
+ /* Do not add to override if the map failed. */
+- if (map_ops[i].status)
++ if (map_ops[i].status != GNTST_okay ||
++ (kmap_ops && kmap_ops[i].status != GNTST_okay))
+ continue;
+
+ if (map_ops[i].flags & GNTMAP_contains_pte) {
--- /dev/null
+From a35f2ef3b7376bfd0a57f7844bd7454389aae1fc Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Mon, 15 Feb 2021 08:49:34 +0100
+Subject: Xen/x86: don't bail early from clear_foreign_p2m_mapping()
+
+From: Jan Beulich <jbeulich@suse.com>
+
+commit a35f2ef3b7376bfd0a57f7844bd7454389aae1fc upstream.
+
+Its sibling (set_foreign_p2m_mapping()) as well as the sibling of its
+only caller (gnttab_map_refs()) don't clean up after themselves in case
+of error. Higher level callers are expected to do so. However, in order
+for that to really clean up any partially set up state, the operation
+should not terminate upon encountering an entry in unexpected state. It
+is particularly relevant to notice here that set_foreign_p2m_mapping()
+would skip setting up a p2m entry if its grant mapping failed, but it
+would continue to set up further p2m entries as long as their mappings
+succeeded.
+
+Arguably down the road set_foreign_p2m_mapping() may want its page state
+related WARN_ON() also converted to an error return.
+
+This is part of XSA-361.
+
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/xen/p2m.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/xen/p2m.c
++++ b/arch/x86/xen/p2m.c
+@@ -750,17 +750,15 @@ int clear_foreign_p2m_mapping(struct gnt
+ unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i]));
+ unsigned long pfn = page_to_pfn(pages[i]);
+
+- if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
++ if (mfn != INVALID_P2M_ENTRY && (mfn & FOREIGN_FRAME_BIT))
++ set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++ else
+ ret = -EINVAL;
+- goto out;
+- }
+-
+- set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+ }
+ if (kunmap_ops)
+ ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+- kunmap_ops, count);
+-out:
++ kunmap_ops, count) ?: ret;
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);