diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 020df615bd..e9bfbc57a7 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -232,8 +232,6 @@ long arch_do_domctl( ret = ioports_permit_access(d, fp, fp + np - 1); else ret = ioports_deny_access(d, fp, fp + np - 1); - if ( !ret ) - memory_type_changed(d); break; } @@ -666,8 +664,6 @@ long arch_do_domctl( "ioport_map: error %ld denying dom%d access to [%x,%x]\n", ret, d->domain_id, fmp, fmp + np - 1); } - if ( !ret ) - memory_type_changed(d); break; } diff --git a/xen/arch/x86/include/asm/iocap.h b/xen/arch/x86/include/asm/iocap.h index eee47228d4..53d87ae8a3 100644 --- a/xen/arch/x86/include/asm/iocap.h +++ b/xen/arch/x86/include/asm/iocap.h @@ -7,10 +7,11 @@ #ifndef __X86_IOCAP_H__ #define __X86_IOCAP_H__ -#define ioports_permit_access(d, s, e) \ - rangeset_add_range((d)->arch.ioport_caps, s, e) -#define ioports_deny_access(d, s, e) \ - rangeset_remove_range((d)->arch.ioport_caps, s, e) +#include +#include + +#include + #define ioports_access_permitted(d, s, e) \ rangeset_contains_range((d)->arch.ioport_caps, s, e) @@ -18,4 +19,29 @@ (!rangeset_is_empty((d)->iomem_caps) || \ !rangeset_is_empty((d)->arch.ioport_caps)) +static inline int ioports_permit_access(struct domain *d, unsigned long s, + unsigned long e) +{ + bool flush = cache_flush_permitted(d); + int ret = rangeset_add_range(d->arch.ioport_caps, s, e); + + if ( !ret && !is_iommu_enabled(d) && !flush ) + /* See comment in iomem_permit_access(). */ + memory_type_changed(d); + + return ret; +} + +static inline int ioports_deny_access(struct domain *d, unsigned long s, + unsigned long e) +{ + int ret = rangeset_remove_range(d->arch.ioport_caps, s, e); + + if ( !ret && !is_iommu_enabled(d) && !cache_flush_permitted(d) ) + /* See comment in iomem_deny_access(). */ + memory_type_changed(d); + + return ret; +} + #endif /* __X86_IOCAP_H__ */ diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index b4919bad51..d61d66c20e 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -518,6 +518,10 @@ int epte_get_entry_emt(struct domain *d, gfn_t gfn, mfn_t mfn, return MTRR_TYPE_UNCACHABLE; } + /* + * Conditional must be kept in sync with the code in + * {iomem,ioports}_{permit,deny}_access(). + */ if ( type != p2m_mmio_direct && !is_iommu_enabled(d) && !cache_flush_permitted(d) ) { diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 452266710a..69fb9abd34 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -716,8 +716,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); else ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); - if ( !ret ) - memory_type_changed(d); break; } @@ -778,8 +776,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) "memory_map: error %ld removing dom%d access to [%lx,%lx]\n", ret, d->domain_id, mfn, mfn_end); } - /* Do this unconditionally to cover errors on above failure paths. */ - memory_type_changed(d); break; } diff --git a/xen/include/xen/iocap.h b/xen/include/xen/iocap.h index 1ca3858fc0..ffbc48b60f 100644 --- a/xen/include/xen/iocap.h +++ b/xen/include/xen/iocap.h @@ -7,13 +7,44 @@ #ifndef __XEN_IOCAP_H__ #define __XEN_IOCAP_H__ +#include #include #include +#include + +static inline int iomem_permit_access(struct domain *d, unsigned long s, + unsigned long e) +{ + bool flush = cache_flush_permitted(d); + int ret = rangeset_add_range(d->iomem_caps, s, e); + + if ( !ret && !is_iommu_enabled(d) && !flush ) + /* + * Only flush if the range(s) are empty before this addition and + * IOMMU is not enabled for the domain, otherwise it makes no + * difference for effective cache attribute calculation purposes. + */ + memory_type_changed(d); + + return ret; +} + +static inline int iomem_deny_access(struct domain *d, unsigned long s, + unsigned long e) +{ + int ret = rangeset_remove_range(d->iomem_caps, s, e); + + if ( !ret && !is_iommu_enabled(d) && !cache_flush_permitted(d) ) + /* + * Only flush if the range(s) are empty after this removal and + * IOMMU is not enabled for the domain, otherwise it makes no + * difference for effective cache attribute calculation purposes. + */ + memory_type_changed(d); + + return ret; +} -#define iomem_permit_access(d, s, e) \ - rangeset_add_range((d)->iomem_caps, s, e) -#define iomem_deny_access(d, s, e) \ - rangeset_remove_range((d)->iomem_caps, s, e) #define iomem_access_permitted(d, s, e) \ rangeset_contains_range((d)->iomem_caps, s, e)