-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/powerpc/64: Test exception cases in copy_tofrom_user
This adds a set of test cases to test the behaviour of copy_tofrom_user when exceptions are encountered accessing the source or destination. Currently, copy_tofrom_user does not always copy as many bytes as possible when an exception occurs on a store to the destination, and that is reflected in failures in these tests. Based on a test program from Anton Blanchard. [paulus@ozlabs.org - test all three paths, wrote commit description, made EX_TABLE create an exception table.] Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
- Loading branch information
Michael Ellerman
committed
Aug 7, 2018
1 parent
98c45f5
commit 2679f63
Showing
6 changed files
with
188 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
tools/testing/selftests/powerpc/copyloops/copy_tofrom_user_reference.S
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include <asm/ppc_asm.h> | ||
|
||
_GLOBAL(copy_tofrom_user_reference) | ||
cmpdi r5,0 | ||
beq 4f | ||
|
||
mtctr r5 | ||
|
||
1: lbz r6,0(r4) | ||
2: stb r6,0(r3) | ||
addi r3,r3,1 | ||
addi r4,r4,1 | ||
bdnz 1b | ||
|
||
3: mfctr r3 | ||
blr | ||
|
||
4: mr r3,r5 | ||
blr | ||
|
||
.section __ex_table,"a" | ||
.llong 1b,3b | ||
.llong 2b,3b | ||
.text |
124 changes: 124 additions & 0 deletions
124
tools/testing/selftests/powerpc/copyloops/exc_validate.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <stdio.h> | ||
#include <signal.h> | ||
#include <unistd.h> | ||
#include <sys/mman.h> | ||
|
||
#include "utils.h" | ||
|
||
extern char __start___ex_table[]; | ||
extern char __stop___ex_table[]; | ||
|
||
#if defined(__powerpc64__) | ||
#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] | ||
#elif defined(__powerpc__) | ||
#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP] | ||
#else | ||
#error implement UCONTEXT_NIA | ||
#endif | ||
|
||
static void segv_handler(int signr, siginfo_t *info, void *ptr) | ||
{ | ||
ucontext_t *uc = (ucontext_t *)ptr; | ||
unsigned long addr = (unsigned long)info->si_addr; | ||
unsigned long *ip = &UCONTEXT_NIA(uc); | ||
unsigned long *ex_p = (unsigned long *)__start___ex_table; | ||
|
||
while (ex_p < (unsigned long *)__stop___ex_table) { | ||
unsigned long insn, fixup; | ||
|
||
insn = *ex_p++; | ||
fixup = *ex_p++; | ||
|
||
if (insn == *ip) { | ||
*ip = fixup; | ||
return; | ||
} | ||
} | ||
|
||
printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr); | ||
abort(); | ||
} | ||
|
||
static void setup_segv_handler(void) | ||
{ | ||
struct sigaction action; | ||
|
||
memset(&action, 0, sizeof(action)); | ||
action.sa_sigaction = segv_handler; | ||
action.sa_flags = SA_SIGINFO; | ||
sigaction(SIGSEGV, &action, NULL); | ||
} | ||
|
||
unsigned long COPY_LOOP(void *to, const void *from, unsigned long size); | ||
unsigned long test_copy_tofrom_user_reference(void *to, const void *from, unsigned long size); | ||
|
||
static int total_passed; | ||
static int total_failed; | ||
|
||
static void do_one_test(char *dstp, char *srcp, unsigned long len) | ||
{ | ||
unsigned long got, expected; | ||
|
||
got = COPY_LOOP(dstp, srcp, len); | ||
expected = test_copy_tofrom_user_reference(dstp, srcp, len); | ||
|
||
if (got != expected) { | ||
total_failed++; | ||
printf("FAIL from=%p to=%p len=%ld returned %ld, expected %ld\n", | ||
srcp, dstp, len, got, expected); | ||
//abort(); | ||
} else | ||
total_passed++; | ||
} | ||
|
||
//#define MAX_LEN 512 | ||
#define MAX_LEN 16 | ||
|
||
int test_copy_exception(void) | ||
{ | ||
int page_size; | ||
static char *p, *q; | ||
unsigned long src, dst, len; | ||
|
||
page_size = getpagesize(); | ||
p = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE, | ||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | ||
|
||
if (p == MAP_FAILED) { | ||
perror("mmap"); | ||
exit(1); | ||
} | ||
|
||
memset(p, 0, page_size); | ||
|
||
setup_segv_handler(); | ||
|
||
if (mprotect(p + page_size, page_size, PROT_NONE)) { | ||
perror("mprotect"); | ||
exit(1); | ||
} | ||
|
||
q = p + page_size - MAX_LEN; | ||
|
||
for (src = 0; src < MAX_LEN; src++) { | ||
for (dst = 0; dst < MAX_LEN; dst++) { | ||
for (len = 0; len < MAX_LEN+1; len++) { | ||
// printf("from=%p to=%p len=%ld\n", q+dst, q+src, len); | ||
do_one_test(q+dst, q+src, len); | ||
} | ||
} | ||
} | ||
|
||
printf("Totals:\n"); | ||
printf(" Pass: %d\n", total_passed); | ||
printf(" Fail: %d\n", total_failed); | ||
|
||
return 0; | ||
} | ||
|
||
int main(void) | ||
{ | ||
return test_harness(test_copy_exception, str(COPY_LOOP)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include <asm/ppc_asm.h> | ||
|
||
FUNC_START(enter_vmx_usercopy) | ||
li r3,1 | ||
blr | ||
|
||
FUNC_START(exit_vmx_usercopy) | ||
li r3,0 | ||
blr | ||
|
||
FUNC_START(enter_vmx_ops) | ||
li r3,1 | ||
blr | ||
|
||
FUNC_START(exit_vmx_ops) | ||
blr | ||
|
||
FUNC_START(__copy_tofrom_user_base) | ||
blr |