[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 2/3] arch, arm32: add the XEN_DOMCTL_memory_mapping hypercall
This commit introduces a first attempt of implementation of the XEN_DOMCTL_memory_mapping hypercall for arm32. The following warnings must be taken into consideration: . currently, the hypercall simply performs an 1:1 mapping of I/O memory ranges (mfn == gfn); . the range of I/O memory addresses is mapped all at once with map_mmio_regions(); . the hypercall takes for granted that any I/O memory range can be mapped to a domU if the current domain is dom0. Signed-off-by: Arianna Avanzini <avanzini.arianna@xxxxxxxxx> Cc: Dario Faggioli <dario.faggioli@xxxxxxxxxx> Cc: Paolo Valente <paolo.valente@xxxxxxxxxx> Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> Cc: Julien Grall <julien.grall@xxxxxxxxxx> Cc: Eric Trudeau <etrudeau@xxxxxxxxxxxx> Cc: Viktor Kleinik <viktor.kleinik@xxxxxxxxxxxxxxx> --- xen/arch/arm/arm32/domctl.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/p2m.c | 9 ++++++ xen/include/asm-arm/p2m.h | 2 ++ 3 files changed, 85 insertions(+) diff --git a/xen/arch/arm/arm32/domctl.c b/xen/arch/arm/arm32/domctl.c index c2ca4d3..67cf734 100644 --- a/xen/arch/arm/arm32/domctl.c +++ b/xen/arch/arm/arm32/domctl.c @@ -10,8 +10,11 @@ #include <xen/errno.h> #include <xen/sched.h> #include <xen/hypercall.h> +#include <xen/iocap.h> #include <public/domctl.h> +#include "cpu.h" + long subarch_do_domctl(struct xen_domctl *domctl, struct domain *d, XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { @@ -19,6 +22,77 @@ long subarch_do_domctl(struct xen_domctl *domctl, struct domain *d, { case XEN_DOMCTL_set_address_size: return domctl->u.address_size.size == 32 ? 0 : -EINVAL; + case XEN_DOMCTL_memory_mapping: + { + unsigned long gfn = domctl->u.memory_mapping.first_gfn; + unsigned long mfn = domctl->u.memory_mapping.first_mfn; + unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns; + int add = domctl->u.memory_mapping.add_mapping; + long int ret; + + ret = -EINVAL; + if ( (mfn + nr_mfns - 1) < mfn || /* wrap? */ + ((mfn | (mfn + nr_mfns - 1)) >> (paddr_bits - PAGE_SHIFT)) || + (gfn + nr_mfns - 1) < gfn ) /* wrap? */ + return ret; + + ret = -EPERM; + /* + * NOTE: dom0 seems to have empty iomem_caps but to be however able to + * access I/O memory ranges. The following check takes for granted + * that any iomem range can be mapped to a domU if the current + * domain is dom0. + */ + if ( current->domain->domain_id != 0 && + !iomem_access_permitted(current->domain, mfn, mfn + nr_mfns - 1) ) + return ret; + + ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, add); + if ( ret ) + return ret; + + if ( add ) + { + printk(XENLOG_G_INFO + "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n", + d->domain_id, gfn, mfn, nr_mfns); + ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); + if ( !ret ) + { + /* 1:1 iomem mapping (gfn == mfn) */ + ret = map_mmio_regions(d, gfn, gfn + nr_mfns - 1, mfn); + if ( ret ) + { + printk(XENLOG_G_WARNING + "memory_map:fail: dom%d gfn=%lx mfn=%lx\n", + d->domain_id, gfn, mfn); + if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) && + is_hardware_domain(current->domain) ) + printk(XENLOG_ERR + "memory_map: failed to deny dom%d access " + "to [%lx,%lx]\n", + d->domain_id, mfn, mfn + nr_mfns - 1); + } + } + } + else + { + printk(XENLOG_G_INFO + "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n", + d->domain_id, gfn, mfn, nr_mfns); + + add = unmap_mmio_regions(d, gfn, gfn + nr_mfns - 1, mfn); + ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); + if ( ret && add ) + ret = -EIO; + if ( ret && is_hardware_domain(current->domain) ) + printk(XENLOG_ERR + "memory_map: error %ld %s dom%d access to [%lx,%lx]\n", + ret, add ? "removing" : "denying", d->domain_id, + mfn, mfn + nr_mfns - 1); + } + return ret; + } default: return -ENOSYS; } diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index d00c882..710f74e 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -461,6 +461,15 @@ int map_mmio_regions(struct domain *d, maddr, MATTR_DEV, p2m_mmio_direct); } +int unmap_mmio_regions(struct domain *d, + paddr_t start_gaddr, + paddr_t end_gaddr, + paddr_t maddr) +{ + return apply_p2m_changes(d, REMOVE, start_gaddr, end_gaddr, + maddr, MATTR_DEV, p2m_mmio_direct); +} + int guest_physmap_add_entry(struct domain *d, unsigned long gpfn, unsigned long mfn, diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 3b39c45..907ce4a 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -88,6 +88,8 @@ int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end); * address maddr. */ int map_mmio_regions(struct domain *d, paddr_t start_gaddr, paddr_t end_gaddr, paddr_t maddr); +int unmap_mmio_regions(struct domain *d, paddr_t start_gaddr, + paddr_t end_gaddr, paddr_t maddr); int guest_physmap_add_entry(struct domain *d, unsigned long gfn, -- 1.8.5.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |