[PATCH] ARM: Move signal return code into vector page

Move the signal return code into the vector page instead of placing
it on the user mode stack, which will allow us to avoid flushing
the instruction cache on signals, as well as eventually allowing
non-exec stack.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+39 -9
+18 -9
arch/arm/kernel/signal.c
··· 19 #include <asm/unistd.h> 20 21 #include "ptrace.h" 22 23 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 24 ··· 36 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) 37 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) 38 39 - static const unsigned long retcodes[4] = { 40 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, 41 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN 42 }; ··· 501 if (ka->sa.sa_flags & SA_SIGINFO) 502 idx += 2; 503 504 - if (__put_user(retcodes[idx], rc)) 505 return 1; 506 507 - /* 508 - * Ensure that the instruction cache sees 509 - * the return code written onto the stack. 510 - */ 511 - flush_icache_range((unsigned long)rc, 512 - (unsigned long)(rc + 1)); 513 514 - retcode = ((unsigned long)rc) + thumb; 515 } 516 517 regs->ARM_r0 = usig;
··· 19 #include <asm/unistd.h> 20 21 #include "ptrace.h" 22 + #include "signal.h" 23 24 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 25 ··· 35 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) 36 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) 37 38 + const unsigned long sigreturn_codes[4] = { 39 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, 40 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN 41 }; ··· 500 if (ka->sa.sa_flags & SA_SIGINFO) 501 idx += 2; 502 503 + if (__put_user(sigreturn_codes[idx], rc)) 504 return 1; 505 506 + if (cpsr & MODE32_BIT) { 507 + /* 508 + * 32-bit code can use the new high-page 509 + * signal return code support. 510 + */ 511 + retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; 512 + } else { 513 + /* 514 + * Ensure that the instruction cache sees 515 + * the return code written onto the stack. 516 + */ 517 + flush_icache_range((unsigned long)rc, 518 + (unsigned long)(rc + 1)); 519 520 + retcode = ((unsigned long)rc) + thumb; 521 + } 522 } 523 524 regs->ARM_r0 = usig;
+12
arch/arm/kernel/signal.h
···
··· 1 + /* 2 + * linux/arch/arm/kernel/signal.h 3 + * 4 + * Copyright (C) 2005 Russell King. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + #define KERN_SIGRETURN_CODE 0xffff0500 11 + 12 + extern const unsigned long sigreturn_codes[4];
+9
arch/arm/kernel/traps.c
··· 30 #include <asm/traps.h> 31 32 #include "ptrace.h" 33 34 const char *processor_modes[]= 35 { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , ··· 684 memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); 685 memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); 686 memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); 687 flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); 688 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 689 }
··· 30 #include <asm/traps.h> 31 32 #include "ptrace.h" 33 + #include "signal.h" 34 35 const char *processor_modes[]= 36 { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , ··· 683 memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); 684 memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); 685 memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); 686 + 687 + /* 688 + * Copy signal return handlers into the vector page, and 689 + * set sigreturn to be a pointer to these. 690 + */ 691 + memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, 692 + sizeof(sigreturn_codes)); 693 + 694 flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); 695 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 696 }