2 * Userspace test harness for load_unaligned_zeropad. Creates two
3 * pages and uses mprotect to prevent access to the second page and
4 * a SEGV handler that walks the exception tables and runs the fixup
7 * The results are compared against a normal load that is that is
8 * performed while access to the second page is enabled via mprotect.
10 * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
26 #define FIXUP_SECTION ".ex_fixup"
28 #include "word-at-a-time.h"
34 static char *mem_region
;
36 static int protect_region(void)
38 if (mprotect(mem_region
+ page_size
, page_size
, PROT_NONE
)) {
46 static int unprotect_region(void)
48 if (mprotect(mem_region
+ page_size
, page_size
, PROT_READ
|PROT_WRITE
)) {
56 extern char __start___ex_table
[];
57 extern char __stop___ex_table
[];
59 #if defined(__powerpc64__)
60 #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]
61 #elif defined(__powerpc__)
62 #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
64 #error implement UCONTEXT_NIA
67 static int segv_error
;
69 static void segv_handler(int signr
, siginfo_t
*info
, void *ptr
)
71 ucontext_t
*uc
= (ucontext_t
*)ptr
;
72 unsigned long addr
= (unsigned long)info
->si_addr
;
73 unsigned long *ip
= &UCONTEXT_NIA(uc
);
74 unsigned long *ex_p
= (unsigned long *)__start___ex_table
;
76 while (ex_p
< (unsigned long *)__stop___ex_table
) {
77 unsigned long insn
, fixup
;
88 printf("No exception table match for NIA %lx ADDR %lx\n", *ip
, addr
);
92 static void setup_segv_handler(void)
94 struct sigaction action
;
96 memset(&action
, 0, sizeof(action
));
97 action
.sa_sigaction
= segv_handler
;
98 action
.sa_flags
= SA_SIGINFO
;
99 sigaction(SIGSEGV
, &action
, NULL
);
102 static int do_one_test(char *p
, int page_offset
)
104 unsigned long should
;
107 FAIL_IF(unprotect_region());
108 should
= *(unsigned long *)p
;
109 FAIL_IF(protect_region());
111 got
= load_unaligned_zeropad(p
);
114 printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset
, got
, should
);
119 static int test_body(void)
123 page_size
= getpagesize();
124 mem_region
= mmap(NULL
, page_size
* 2, PROT_READ
|PROT_WRITE
,
125 MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
127 FAIL_IF(mem_region
== MAP_FAILED
);
129 for (i
= 0; i
< page_size
; i
++)
132 memset(mem_region
+page_size
, 0, page_size
);
134 setup_segv_handler();
136 for (i
= 0; i
< page_size
; i
++)
137 FAIL_IF(do_one_test(mem_region
+i
, i
));
146 return test_harness(test_body
, "load_unaligned_zeropad");