1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Userspace test harness for load_unaligned_zeropad. Creates two
4 * pages and uses mprotect to prevent access to the second page and
5 * a SEGV handler that walks the exception tables and runs the fixup
8 * The results are compared against a normal load that is that is
9 * performed while access to the second page is enabled via mprotect.
11 * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM
22 #define FIXUP_SECTION ".ex_fixup"
24 static inline unsigned long __fls(unsigned long x
);
26 #include "word-at-a-time.h"
30 static inline unsigned long __fls(unsigned long x
)
34 asm (PPC_CNTLZL
"%0,%1" : "=r" (lz
) : "r" (x
));
35 return sizeof(unsigned long) - 1 - lz
;
39 static char *mem_region
;
41 static int protect_region(void)
43 if (mprotect(mem_region
+ page_size
, page_size
, PROT_NONE
)) {
51 static int unprotect_region(void)
53 if (mprotect(mem_region
+ page_size
, page_size
, PROT_READ
|PROT_WRITE
)) {
61 extern char __start___ex_table
[];
62 extern char __stop___ex_table
[];
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 struct extbl_entry
*entry
= (struct extbl_entry
*)__start___ex_table
;
76 while (entry
< (struct extbl_entry
*)__stop___ex_table
) {
77 unsigned long insn
, fixup
;
79 insn
= (unsigned long)&entry
->insn
+ entry
->insn
;
80 fixup
= (unsigned long)&entry
->fixup
+ entry
->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
);
121 static int test_body(void)
125 page_size
= getpagesize();
126 mem_region
= mmap(NULL
, page_size
* 2, PROT_READ
|PROT_WRITE
,
127 MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
129 FAIL_IF(mem_region
== MAP_FAILED
);
131 for (i
= 0; i
< page_size
; i
++)
134 memset(mem_region
+page_size
, 0, page_size
);
136 setup_segv_handler();
138 for (i
= 0; i
< page_size
; i
++)
139 FAIL_IF(do_one_test(mem_region
+i
, i
));
146 return test_harness(test_body
, "load_unaligned_zeropad");