--- /dev/null
+# The loops are all 64-bit code
+CFLAGS += -m64
+CFLAGS += -I$(CURDIR)
+CFLAGS += -D SELFTEST
+
+# Use our CFLAGS for the implicit .S rule
+ASFLAGS = $(CFLAGS)
+
+PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
+EXTRA_SOURCES := validate.c ../harness.c
+
+all: $(PROGS)
+
+copyuser_64:     CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
+copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
+memcpy_64:       CPPFLAGS += -D COPY_LOOP=test_memcpy
+memcpy_power7:   CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
+
+$(PROGS): $(EXTRA_SOURCES)
+
+run_tests: all
+       @-for PROG in $(PROGS); do \
+               ./$$PROG; \
+       done;
+
+clean:
+       rm -f $(PROGS) *.o
+
+.PHONY: all run_tests clean
 
--- /dev/null
+#include <ppc-asm.h>
+
+#define CONFIG_ALTIVEC
+
+#define r1     1
+
+#define vr0     0
+#define vr1     1
+#define vr2     2
+#define vr3     3
+#define vr4     4
+#define vr5     5
+#define vr6     6
+#define vr7     7
+#define vr8     8
+#define vr9     9
+#define vr10    10
+#define vr11    11
+#define vr12    12
+#define vr13    13
+#define vr14    14
+#define vr15    15
+#define vr16    16
+#define vr17    17
+#define vr18    18
+#define vr19    19
+#define vr20    20
+#define vr21    21
+#define vr22    22
+#define vr23    23
+#define vr24    24
+#define vr25    25
+#define vr26    26
+#define vr27    27
+#define vr28    28
+#define vr29    29
+#define vr30    30
+#define vr31    31
+
+#define R14 r14
+#define R15 r15
+#define R16 r16
+#define R17 r17
+#define R18 r18
+#define R19 r19
+#define R20 r20
+#define R21 r21
+#define R22 r22
+
+#define STACKFRAMESIZE 256
+#define STK_PARAM(i)   (48 + ((i)-3)*8)
+#define STK_REG(i)     (112 + ((i)-14)*8)
+
+#define _GLOBAL(A) FUNC_START(test_ ## A)
+
+#define PPC_MTOCRF(A, B)       mtocrf A, B
+
+FUNC_START(enter_vmx_usercopy)
+       li      r3,1
+       blr
+
+FUNC_START(exit_vmx_usercopy)
+       li      r3,0
+       blr
+
+FUNC_START(enter_vmx_copy)
+       li      r3,1
+       blr
+
+FUNC_START(exit_vmx_copy)
+       blr
+
+FUNC_START(memcpy_power7)
+       blr
+
+FUNC_START(__copy_tofrom_user_power7)
+       blr
+
+FUNC_START(__copy_tofrom_user_base)
+       blr
+
+#define BEGIN_FTR_SECTION
+#define FTR_SECTION_ELSE
+#define ALT_FTR_SECTION_END_IFCLR(x)
+#define ALT_FTR_SECTION_END(x, y)
+#define END_FTR_SECTION_IFCLR(x)
 
--- /dev/null
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "../utils.h"
+
+#define MAX_LEN 8192
+#define MAX_OFFSET 16
+#define MIN_REDZONE 128
+#define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE)
+#define POISON 0xa5
+
+unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
+
+static void do_one(char *src, char *dst, unsigned long src_off,
+                  unsigned long dst_off, unsigned long len, void *redzone,
+                  void *fill)
+{
+       char *srcp, *dstp;
+       unsigned long ret;
+       unsigned long i;
+
+       srcp = src + MIN_REDZONE + src_off;
+       dstp = dst + MIN_REDZONE + dst_off;
+
+       memset(src, POISON, BUFLEN);
+       memset(dst, POISON, BUFLEN);
+       memcpy(srcp, fill, len);
+
+       ret = COPY_LOOP(dstp, srcp, len);
+       if (ret && ret != (unsigned long)dstp) {
+               printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret);
+               abort();
+       }
+
+       if (memcmp(dstp, srcp, len)) {
+               printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len);
+               printf("src: ");
+               for (i = 0; i < len; i++)
+                       printf("%02x ", srcp[i]);
+               printf("\ndst: ");
+               for (i = 0; i < len; i++)
+                       printf("%02x ", dstp[i]);
+               printf("\n");
+               abort();
+       }
+
+       if (memcmp(dst, redzone, dstp - dst)) {
+               printf("(%p,%p,%ld) redzone before corrupted\n",
+                      dstp, srcp, len);
+               abort();
+       }
+
+       if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) {
+               printf("(%p,%p,%ld) redzone after corrupted\n",
+                      dstp, srcp, len);
+               abort();
+       }
+}
+
+int test_copy_loop(void)
+{
+       char *src, *dst, *redzone, *fill;
+       unsigned long len, src_off, dst_off;
+       unsigned long i;
+
+       src = memalign(BUFLEN, BUFLEN);
+       dst = memalign(BUFLEN, BUFLEN);
+       redzone = malloc(BUFLEN);
+       fill = malloc(BUFLEN);
+
+       if (!src || !dst || !redzone || !fill) {
+               fprintf(stderr, "malloc failed\n");
+               exit(1);
+       }
+
+       memset(redzone, POISON, BUFLEN);
+
+       /* Fill with sequential bytes */
+       for (i = 0; i < BUFLEN; i++)
+               fill[i] = i & 0xff;
+
+       for (len = 1; len < MAX_LEN; len++) {
+               for (src_off = 0; src_off < MAX_OFFSET; src_off++) {
+                       for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) {
+                               do_one(src, dst, src_off, dst_off, len,
+                                      redzone, fill);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int main(void)
+{
+       return test_harness(test_copy_loop, str(COPY_LOOP));
+}