···116116117117#endif118118119119+/*120120+ * We use load_unaligned_zero() in a selftest, which builds a userspace121121+ * program. Some linker scripts seem to discard the .fixup section, so allow122122+ * the test code to use a different section name.123123+ */124124+#ifndef FIXUP_SECTION125125+#define FIXUP_SECTION ".fixup"126126+#endif127127+119128static inline unsigned long load_unaligned_zeropad(const void *addr)120129{121130 unsigned long ret, offset, tmp;···132123 asm(133124 "1: " PPC_LL "%[ret], 0(%[addr])\n"134125 "2:\n"135135- ".section .fixup,\"ax\"\n"126126+ ".section " FIXUP_SECTION ",\"ax\"\n"136127 "3: "137128#ifdef __powerpc64__138129 "clrrdi %[tmp], %[addr], 3\n\t"···164155165156 return ret;166157}158158+159159+#undef FIXUP_SECTION167160168161#endif /* _ASM_WORD_AT_A_TIME_H */
+1-1
tools/testing/selftests/powerpc/Makefile
···13131414export CC CFLAGS15151616-TARGETS = pmu copyloops mm tm1616+TARGETS = pmu copyloops mm tm primitives17171818endif1919
···11+/*22+ * Userspace test harness for load_unaligned_zeropad. Creates two33+ * pages and uses mprotect to prevent access to the second page and44+ * a SEGV handler that walks the exception tables and runs the fixup55+ * routine.66+ *77+ * The results are compared against a normal load that is that is88+ * performed while access to the second page is enabled via mprotect.99+ *1010+ * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM1111+ *1212+ * This program is free software; you can redistribute it and/or1313+ * modify it under the terms of the GNU General Public License1414+ * as published by the Free Software Foundation; either version1515+ * 2 of the License, or (at your option) any later version.1616+ */1717+1818+#include <stdlib.h>1919+#include <string.h>2020+#include <stdio.h>2121+#include <stdbool.h>2222+#include <signal.h>2323+#include <unistd.h>2424+#include <sys/mman.h>2525+2626+#define FIXUP_SECTION ".ex_fixup"2727+2828+#include "word-at-a-time.h"2929+3030+#include "utils.h"3131+3232+3333+static int page_size;3434+static char *mem_region;3535+3636+static int protect_region(void)3737+{3838+ if (mprotect(mem_region + page_size, page_size, PROT_NONE)) {3939+ perror("mprotect");4040+ return 1;4141+ }4242+4343+ return 0;4444+}4545+4646+static int unprotect_region(void)4747+{4848+ if (mprotect(mem_region + page_size, page_size, PROT_READ|PROT_WRITE)) {4949+ perror("mprotect");5050+ return 1;5151+ }5252+5353+ return 0;5454+}5555+5656+extern char __start___ex_table[];5757+extern char __stop___ex_table[];5858+5959+#if defined(__powerpc64__)6060+#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]6161+#elif defined(__powerpc__)6262+#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]6363+#else6464+#error implement UCONTEXT_NIA6565+#endif6666+6767+static int segv_error;6868+6969+static void segv_handler(int signr, siginfo_t *info, void *ptr)7070+{7171+ ucontext_t *uc = (ucontext_t *)ptr;7272+ unsigned long addr = (unsigned long)info->si_addr;7373+ unsigned long *ip = &UCONTEXT_NIA(uc);7474+ unsigned long *ex_p = (unsigned long *)__start___ex_table;7575+7676+ while (ex_p < (unsigned long *)__stop___ex_table) {7777+ unsigned long insn, fixup;7878+7979+ insn = *ex_p++;8080+ fixup = *ex_p++;8181+8282+ if (insn == *ip) {8383+ *ip = fixup;8484+ return;8585+ }8686+ }8787+8888+ printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);8989+ segv_error++;9090+}9191+9292+static void setup_segv_handler(void)9393+{9494+ struct sigaction action;9595+9696+ memset(&action, 0, sizeof(action));9797+ action.sa_sigaction = segv_handler;9898+ action.sa_flags = SA_SIGINFO;9999+ sigaction(SIGSEGV, &action, NULL);100100+}101101+102102+static int do_one_test(char *p, int page_offset)103103+{104104+ unsigned long should;105105+ unsigned long got;106106+107107+ FAIL_IF(unprotect_region());108108+ should = *(unsigned long *)p;109109+ FAIL_IF(protect_region());110110+111111+ got = load_unaligned_zeropad(p);112112+113113+ if (should != got)114114+ printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should);115115+116116+ return 0;117117+}118118+119119+static int test_body(void)120120+{121121+ unsigned long i;122122+123123+ page_size = getpagesize();124124+ mem_region = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,125125+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);126126+127127+ FAIL_IF(mem_region == MAP_FAILED);128128+129129+ for (i = 0; i < page_size; i++)130130+ mem_region[i] = i;131131+132132+ memset(mem_region+page_size, 0, page_size);133133+134134+ setup_segv_handler();135135+136136+ for (i = 0; i < page_size; i++)137137+ FAIL_IF(do_one_test(mem_region+i, i));138138+139139+ FAIL_IF(segv_error);140140+141141+ return 0;142142+}143143+144144+int main(void)145145+{146146+ return test_harness(test_body, "load_unaligned_zeropad");147147+}