xen: don't require virtio with grants for non-PV guests

Commit fa1f57421e ("xen/virtio: Enable restricted memory access using
Xen grant mappings") introduced a new requirement for using virtio
devices: the backend now needs to support the VIRTIO_F_ACCESS_PLATFORM
feature.

This is an undue requirement for non-PV guests, as those can be operated
with existing backends without any problem, as long as those backends
are running in dom0.

Per default allow virtio devices without grant support for non-PV
guests.

On Arm require VIRTIO_F_ACCESS_PLATFORM for devices having been listed
in the device tree to use grants.

Add a new config item to always force use of grants for virtio.

Fixes: fa1f57421e ("xen/virtio: Enable restricted memory access using Xen grant mappings")
Reported-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Tested-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> # Arm64 guest using Xen
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Link: https://lore.kernel.org/r/20220622063838.8854-4-jgross@suse.com
Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
Juergen Gross 2022-06-22 08:38:38 +02:00
parent a870544ca9
commit 251e90e7e3
7 changed files with 38 additions and 11 deletions

View File

@ -34,6 +34,7 @@
#include <linux/timekeeping.h> #include <linux/timekeeping.h>
#include <linux/timekeeper_internal.h> #include <linux/timekeeper_internal.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/virtio_anchor.h>
#include <linux/mm.h> #include <linux/mm.h>
@ -443,7 +444,8 @@ static int __init xen_guest_init(void)
if (!xen_domain()) if (!xen_domain())
return 0; return 0;
xen_set_restricted_virtio_memory_access(); if (IS_ENABLED(CONFIG_XEN_VIRTIO))
virtio_set_mem_acc_cb(xen_virtio_mem_acc);
if (!acpi_disabled) if (!acpi_disabled)
xen_acpi_guest_init(); xen_acpi_guest_init();

View File

@ -4,6 +4,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/virtio_anchor.h>
#include <xen/features.h> #include <xen/features.h>
#include <xen/events.h> #include <xen/events.h>
@ -195,7 +196,8 @@ static void __init xen_hvm_guest_init(void)
if (xen_pv_domain()) if (xen_pv_domain())
return; return;
xen_set_restricted_virtio_memory_access(); if (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT))
virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
init_hvm_pv_info(); init_hvm_pv_info();

View File

@ -31,6 +31,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/edd.h> #include <linux/edd.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/virtio_anchor.h>
#include <xen/xen.h> #include <xen/xen.h>
#include <xen/events.h> #include <xen/events.h>
@ -109,7 +110,9 @@ static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc);
static void __init xen_pv_init_platform(void) static void __init xen_pv_init_platform(void)
{ {
xen_set_restricted_virtio_memory_access(); /* PV guests can't operate virtio devices without grants. */
if (IS_ENABLED(CONFIG_XEN_VIRTIO))
virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP)); populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));

View File

@ -355,4 +355,13 @@ config XEN_VIRTIO
If in doubt, say n. If in doubt, say n.
config XEN_VIRTIO_FORCE_GRANT
bool "Require Xen virtio support to use grants"
depends on XEN_VIRTIO
help
Require virtio for Xen guests to use grant mappings.
This will avoid the need to give the backend the right to map all
of the guest memory. This will need support on the backend side
(e.g. qemu or kernel, depending on the virtio device types used).
endmenu endmenu

View File

@ -12,6 +12,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/xarray.h> #include <linux/xarray.h>
#include <linux/virtio_anchor.h>
#include <linux/virtio.h>
#include <xen/xen.h> #include <xen/xen.h>
#include <xen/xen-ops.h> #include <xen/xen-ops.h>
#include <xen/grant_table.h> #include <xen/grant_table.h>
@ -287,6 +289,14 @@ bool xen_is_grant_dma_device(struct device *dev)
return has_iommu; return has_iommu;
} }
bool xen_virtio_mem_acc(struct virtio_device *dev)
{
if (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT))
return true;
return xen_is_grant_dma_device(dev->dev.parent);
}
void xen_grant_setup_dma_ops(struct device *dev) void xen_grant_setup_dma_ops(struct device *dev)
{ {
struct xen_grant_dma_data *data; struct xen_grant_dma_data *data;

View File

@ -5,6 +5,7 @@
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/virtio_anchor.h>
#include <xen/features.h> #include <xen/features.h>
#include <asm/xen/interface.h> #include <asm/xen/interface.h>
#include <xen/interface/vcpu.h> #include <xen/interface/vcpu.h>
@ -217,6 +218,7 @@ static inline void xen_preemptible_hcall_end(void) { }
#ifdef CONFIG_XEN_GRANT_DMA_OPS #ifdef CONFIG_XEN_GRANT_DMA_OPS
void xen_grant_setup_dma_ops(struct device *dev); void xen_grant_setup_dma_ops(struct device *dev);
bool xen_is_grant_dma_device(struct device *dev); bool xen_is_grant_dma_device(struct device *dev);
bool xen_virtio_mem_acc(struct virtio_device *dev);
#else #else
static inline void xen_grant_setup_dma_ops(struct device *dev) static inline void xen_grant_setup_dma_ops(struct device *dev)
{ {
@ -225,6 +227,13 @@ static inline bool xen_is_grant_dma_device(struct device *dev)
{ {
return false; return false;
} }
struct virtio_device;
static inline bool xen_virtio_mem_acc(struct virtio_device *dev)
{
return false;
}
#endif /* CONFIG_XEN_GRANT_DMA_OPS */ #endif /* CONFIG_XEN_GRANT_DMA_OPS */
#endif /* INCLUDE_XEN_OPS_H */ #endif /* INCLUDE_XEN_OPS_H */

View File

@ -52,14 +52,6 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
extern u64 xen_saved_max_mem_size; extern u64 xen_saved_max_mem_size;
#endif #endif
#include <linux/virtio_anchor.h>
static inline void xen_set_restricted_virtio_memory_access(void)
{
if (IS_ENABLED(CONFIG_XEN_VIRTIO) && xen_domain())
virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
}
#ifdef CONFIG_XEN_UNPOPULATED_ALLOC #ifdef CONFIG_XEN_UNPOPULATED_ALLOC
int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages); int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages);
void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages); void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages);