This core backing function is uniform; what varies across architectures
are the attributes passed and hence the wrappers around it. Yet of course
extra checking or special handling may be needed per arch, so introduce a
suitable hook. Permit such a hook to return both adjusted and un-adjusted
(for the page offset) pointers.

Signed-off-by: Jan Beulich <[email protected]>
---
Declarations (or inline counterparts) aren't being moved around, to avoid
the need to touch source files using the functions. Quite possibly they
want to consistently go into xen/io.h and asm/io.h.

Of course ioremap.c could also go into lib/.

For RISC-V the wrappers likely should become inline functions?

PPC doesn't reference any of the functions just yet, so gets only a
declaration.

For Arm, a TODO item is deliberately retained, yet seeing the use of
ioremap_wc() in domain building (which by itself is questionable, see next
patch) I wonder if that's even feasible as long as we don't have
memremap() or alike.

--- a/xen/arch/arm/include/asm/io.h
+++ b/xen/arch/arm/include/asm/io.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
+#include <xen/mm-types.h>
+
 #if defined(CONFIG_ARM_32)
 # include <asm/arm32/io.h>
 #elif defined(CONFIG_ARM_64)
@@ -9,6 +11,16 @@
 # error "unknown ARM variant"
 #endif
 
+#ifdef CONFIG_MPU
+void __iomem *mpu_ioremap_attr(paddr_t start, size_t len, pte_attr_t flags);
+#define arch_ioremap_attr mpu_ioremap_attr
+#else
+/*
+ * ioremap_attr() should only be used to remap device address ranges.
+ * TODO: Add an arch hook to verify this assumption.
+ */
+#endif
+
 #endif
 /*
  * Local variables:
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -5,6 +5,7 @@
 #include <asm/page.h>
 #include <public/xen.h>
 #include <xen/pdx.h>
+#include <xen/vmap.h>
 
 #if defined(CONFIG_ARM_32)
 # include <asm/arm32/mm.h>
@@ -200,13 +201,12 @@ extern int prepare_secondary_mm(int cpu)
 extern void setup_frametable_mappings(paddr_t ps, paddr_t pe);
 /* Helper function to setup memory management */
 void setup_mm_helper(void);
-/* map a physical range in virtual memory */
-void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned int attributes);
 
 static inline void __iomem *ioremap_nocache(paddr_t start, size_t len)
 {
     return ioremap_attr(start, len, PAGE_HYPERVISOR_NOCACHE);
 }
+#define ioremap ioremap_nocache
 
 static inline void __iomem *ioremap_cache(paddr_t start, size_t len)
 {
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -455,11 +455,6 @@ unsigned long get_upper_mfn_bound(void)
     return max_page - 1;
 }
 
-void *ioremap(paddr_t pa, size_t len)
-{
-    return ioremap_attr(pa, len, PAGE_HYPERVISOR_NOCACHE);
-}
-
 /*
  * Local variables:
  * mode: C
--- a/xen/arch/arm/mmu/pt.c
+++ b/xen/arch/arm/mmu/pt.c
@@ -206,23 +206,6 @@ void clear_fixmap(unsigned int map)
     BUG_ON(res != 0);
 }
 
-/*
- * This function should only be used to remap device address ranges
- * TODO: add a check to verify this assumption
- */
-void *ioremap_attr(paddr_t start, size_t len, unsigned int attributes)
-{
-    mfn_t mfn = _mfn(PFN_DOWN(start));
-    unsigned int offs = start & (PAGE_SIZE - 1);
-    unsigned int nr = PFN_UP(offs + len);
-    void *ptr = __vmap(&mfn, nr, 1, 1, attributes, VMAP_DEFAULT);
-
-    if ( ptr == NULL )
-        return NULL;
-
-    return ptr + offs;
-}
-
 static int create_xen_table(lpae_t *entry)
 {
     mfn_t mfn;
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -9,6 +9,8 @@
 #include <xen/sizes.h>
 #include <xen/spinlock.h>
 #include <xen/types.h>
+
+#include <asm/io.h>
 #include <asm/mpu.h>
 #include <asm/mpu/mm.h>
 #include <asm/page.h>
@@ -593,7 +595,7 @@ void free_init_memory(void)
     spin_unlock(&xen_mpumap_lock);
 }
 
-void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned int flags)
+void __iomem *mpu_ioremap_attr(paddr_t start, size_t len, pte_attr_t flags)
 {
     paddr_t start_pg = round_pgdown(start);
     paddr_t end_pg = round_pgup(start_pg + len);
--- a/xen/arch/ppc/include/asm/io.h
+++ b/xen/arch/ppc/include/asm/io.h
@@ -13,4 +13,6 @@
 #define writew(v,c)     ({ (void)(v); (void)(c); BUG_ON("unimplemented"); })
 #define writel(v,c)     ({ (void)(v); (void)(c); BUG_ON("unimplemented"); })
 
+void __iomem *ioremap(paddr_t pa, size_t len);
+
 #endif /* __ASM_PPC_IO_H__ */
--- a/xen/arch/riscv/include/asm/io.h
+++ b/xen/arch/riscv/include/asm/io.h
@@ -41,6 +41,7 @@
 #include <xen/macros.h>
 #include <xen/types.h>
 
+void __iomem *ioremap(paddr_t pa, size_t len);
 void __iomem *ioremap_cache(paddr_t pa, size_t len);
 void __iomem *ioremap_wc(paddr_t pa, size_t len);
 
--- a/xen/arch/riscv/mm.c
+++ b/xen/arch/riscv/mm.c
@@ -587,20 +587,6 @@ void *__init arch_vmap_virt_end(void)
     return (void *)(VMAP_VIRT_START + VMAP_VIRT_SIZE);
 }
 
-static void __iomem *ioremap_attr(paddr_t pa, size_t len,
-                                  pte_attr_t attributes)
-{
-    mfn_t mfn = _mfn(PFN_DOWN(pa));
-    unsigned int offs = pa & (PAGE_SIZE - 1);
-    unsigned int nr = PFN_UP(offs + len);
-    void *ptr = __vmap(&mfn, nr, 1, 1, attributes, VMAP_DEFAULT);
-
-    if ( ptr == NULL )
-        return NULL;
-
-    return ptr + offs;
-}
-
 void __iomem *ioremap_cache(paddr_t pa, size_t len)
 {
     return ioremap_attr(pa, len, PAGE_HYPERVISOR);
--- a/xen/arch/x86/include/asm/io.h
+++ b/xen/arch/x86/include/asm/io.h
@@ -47,6 +47,9 @@ __OUT(b,"b",char)
 __OUT(w,"w",short)
 __OUT(l,,int)
 
+void __iomem *x86_ioremap_attr(paddr_t pa, size_t len, pte_attr_t attr);
+#define arch_ioremap_attr x86_ioremap_attr
+
 /*
  * Boolean indicator and function used to handle platform specific I/O port
  * emulation.
--- a/xen/arch/x86/include/asm/mm.h
+++ b/xen/arch/x86/include/asm/mm.h
@@ -611,7 +611,15 @@ void destroy_perdomain_mapping(struct do
                                unsigned int nr);
 void free_perdomain_mappings(struct domain *d);
 
-void __iomem *ioremap_wc(paddr_t pa, size_t len);
+static inline void __iomem *ioremap(paddr_t pa, size_t len)
+{
+    return ioremap_attr(pa, len, PAGE_HYPERVISOR_UCMINUS);
+}
+
+static inline void __iomem *ioremap_wc(paddr_t pa, size_t len)
+{
+    return ioremap_attr(pa, len, PAGE_HYPERVISOR_WC);
+}
 
 extern int memory_add(unsigned long spfn, unsigned long epfn, unsigned int 
pxm);
 
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -6166,41 +6166,15 @@ void *__init arch_vmap_virt_end(void)
     return fix_to_virt(__end_of_fixed_addresses);
 }
 
-void __iomem *ioremap(paddr_t pa, size_t len)
+void __iomem *x86_ioremap_attr(paddr_t pa, size_t len, pte_attr_t attr)
 {
-    mfn_t mfn = _mfn(PFN_DOWN(pa));
-    void *va;
-
-    WARN_ON(page_is_ram_type(mfn_x(mfn), RAM_TYPE_CONVENTIONAL));
+    WARN_ON(page_is_ram_type(PFN_DOWN(pa), RAM_TYPE_CONVENTIONAL));
 
     /* The low first Mb is always mapped. */
-    if ( !((pa + len - 1) >> 20) )
-        va = __va(pa);
-    else
-    {
-        unsigned int offs = pa & (PAGE_SIZE - 1);
-        unsigned int nr = PFN_UP(offs + len);
-
-        va = __vmap(&mfn, nr, 1, 1, PAGE_HYPERVISOR_UCMINUS, VMAP_DEFAULT);
-        if ( va )
-            va += offs;
-    }
-
-    return (void __force __iomem *)va;
-}
-
-void __iomem *__init ioremap_wc(paddr_t pa, size_t len)
-{
-    mfn_t mfn = _mfn(PFN_DOWN(pa));
-    unsigned int offs = pa & (PAGE_SIZE - 1);
-    unsigned int nr = PFN_UP(offs + len);
-    void *va;
-
-    WARN_ON(page_is_ram_type(mfn_x(mfn), RAM_TYPE_CONVENTIONAL));
-
-    va = __vmap(&mfn, nr, 1, 1, PAGE_HYPERVISOR_WC, VMAP_DEFAULT);
+    if ( !((pa + len - 1) >> 20) && attr == PAGE_HYPERVISOR_UCMINUS )
+        return (void __force __iomem *)__va(pa);
 
-    return (void __force __iomem *)(va ? va + offs : NULL);
+    return NULL;
 }
 
 int create_perdomain_mapping(struct domain *d, unsigned long va,
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_GRANT_TABLE) += grant_table
 obj-y += guestcopy.o
 obj-y += gzip/
 obj-$(CONFIG_HYPFS) += hypfs.o
+obj-y += ioremap.o
 obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
 obj-y += irq.o
 obj-y += kernel.o
--- /dev/null
+++ b/xen/common/ioremap.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/vmap.h>
+
+#include <asm/io.h>
+
+void __iomem *ioremap_attr(paddr_t pa, size_t len, pte_attr_t attr)
+{
+    void __iomem *ptr = NULL;
+    unsigned int offs = PAGE_OFFSET(pa);
+
+#ifdef arch_ioremap_attr
+    ptr = arch_ioremap_attr(pa, len, attr);
+    if ( PAGE_OFFSET(ptr) )
+        return ptr;
+#endif
+
+    if ( IS_ENABLED(CONFIG_HAS_VMAP) && !ptr )
+    {
+        mfn_t mfn = _mfn(PFN_DOWN(pa));
+
+        ptr = (void __force __iomem *)__vmap(&mfn, PFN_UP(offs + len), 1, 1,
+                                             attr, VMAP_DEFAULT);
+    }
+
+    if ( !ptr )
+        return NULL;
+
+    return ptr + offs;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -121,9 +121,10 @@ void vfree(void *va);
  *
  * @param pa  Physical base address of the MMIO region.
  * @param len Length of the MMIO region in octets.
+ * @param attr Attributes for the mapping.
  * @return Pointer to the mapped area on success; NULL otherwise.
  */
-void __iomem *ioremap(paddr_t pa, size_t len);
+void __iomem *ioremap_attr(paddr_t pa, size_t len, pte_attr_t attr);
 
 /* Return the number of pages in the mapping starting at address 'va' */
 unsigned int vmap_size(const void *va);


Reply via email to