Merge tag 'x86-urgent-2022-04-03' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / x86 / lib / iomem.c
index df50451..3e2f33f 100644 (file)
@@ -22,7 +22,7 @@ static __always_inline void rep_movs(void *to, const void *from, size_t n)
                     : "memory");
 }
 
-void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+static void string_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
 {
        if (unlikely(!n))
                return;
@@ -38,9 +38,8 @@ void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
        }
        rep_movs(to, (const void *)from, n);
 }
-EXPORT_SYMBOL(memcpy_fromio);
 
-void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+static void string_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
 {
        if (unlikely(!n))
                return;
@@ -56,14 +55,64 @@ void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
        }
        rep_movs((void *)to, (const void *) from, n);
 }
+
+static void unrolled_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+{
+       const volatile char __iomem *in = from;
+       char *out = to;
+       int i;
+
+       for (i = 0; i < n; ++i)
+               out[i] = readb(&in[i]);
+}
+
+static void unrolled_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+{
+       volatile char __iomem *out = to;
+       const char *in = from;
+       int i;
+
+       for (i = 0; i < n; ++i)
+               writeb(in[i], &out[i]);
+}
+
+static void unrolled_memset_io(volatile void __iomem *a, int b, size_t c)
+{
+       volatile char __iomem *mem = a;
+       int i;
+
+       for (i = 0; i < c; ++i)
+               writeb(b, &mem[i]);
+}
+
+void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+{
+       if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO))
+               unrolled_memcpy_fromio(to, from, n);
+       else
+               string_memcpy_fromio(to, from, n);
+}
+EXPORT_SYMBOL(memcpy_fromio);
+
+void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+{
+       if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO))
+               unrolled_memcpy_toio(to, from, n);
+       else
+               string_memcpy_toio(to, from, n);
+}
 EXPORT_SYMBOL(memcpy_toio);
 
 void memset_io(volatile void __iomem *a, int b, size_t c)
 {
-       /*
-        * TODO: memset can mangle the IO patterns quite a bit.
-        * perhaps it would be better to use a dumb one:
-        */
-       memset((void *)a, b, c);
+       if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) {
+               unrolled_memset_io(a, b, c);
+       } else {
+               /*
+                * TODO: memset can mangle the IO patterns quite a bit.
+                * perhaps it would be better to use a dumb one:
+                */
+               memset((void *)a, b, c);
+       }
 }
 EXPORT_SYMBOL(memset_io);