Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] 3664/1: crunch: add signal frame save/restore

Patch from Lennert Buytenhek

This patch makes the kernel save Crunch state in userland signal frames,
so that any userland signal handler can safely use the Crunch coprocessor
without corrupting the Crunch state of the code it preempted.

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

authored by

Lennert Buytenhek and committed by
Russell King
3bec6ded 562ca1e3

+53
+39
arch/arm/kernel/signal.c
··· 132 132 return ret; 133 133 } 134 134 135 + #ifdef CONFIG_CRUNCH 136 + static int preserve_crunch_context(struct crunch_sigframe *frame) 137 + { 138 + char kbuf[sizeof(*frame) + 8]; 139 + struct crunch_sigframe *kframe; 140 + 141 + /* the crunch context must be 64 bit aligned */ 142 + kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7); 143 + kframe->magic = CRUNCH_MAGIC; 144 + kframe->size = CRUNCH_STORAGE_SIZE; 145 + crunch_task_copy(current_thread_info(), &kframe->storage); 146 + return __copy_to_user(frame, kframe, sizeof(*frame)); 147 + } 148 + 149 + static int restore_crunch_context(struct crunch_sigframe *frame) 150 + { 151 + char kbuf[sizeof(*frame) + 8]; 152 + struct crunch_sigframe *kframe; 153 + 154 + /* the crunch context must be 64 bit aligned */ 155 + kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7); 156 + if (__copy_from_user(kframe, frame, sizeof(*frame))) 157 + return -1; 158 + if (kframe->magic != CRUNCH_MAGIC || 159 + kframe->size != CRUNCH_STORAGE_SIZE) 160 + return -1; 161 + crunch_task_restore(current_thread_info(), &kframe->storage); 162 + return 0; 163 + } 164 + #endif 165 + 135 166 #ifdef CONFIG_IWMMXT 136 167 137 168 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) ··· 245 214 err |= !valid_user_regs(regs); 246 215 247 216 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; 217 + #ifdef CONFIG_CRUNCH 218 + if (err == 0) 219 + err |= restore_crunch_context(&aux->crunch); 220 + #endif 248 221 #ifdef CONFIG_IWMMXT 249 222 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 250 223 err |= restore_iwmmxt_context(&aux->iwmmxt); ··· 368 333 err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 369 334 370 335 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; 336 + #ifdef CONFIG_CRUNCH 337 + if (err == 0) 338 + err |= preserve_crunch_context(&aux->crunch); 339 + #endif 371 340 #ifdef CONFIG_IWMMXT 372 341 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 373 342 err |= preserve_iwmmxt_context(&aux->iwmmxt);
+14
include/asm-arm/ucontext.h
··· 35 35 * bytes, to prevent unpredictable padding in the signal frame. 36 36 */ 37 37 38 + #ifdef CONFIG_CRUNCH 39 + #define CRUNCH_MAGIC 0x5065cf03 40 + #define CRUNCH_STORAGE_SIZE (CRUNCH_SIZE + 8) 41 + 42 + struct crunch_sigframe { 43 + unsigned long magic; 44 + unsigned long size; 45 + struct crunch_state storage; 46 + } __attribute__((__aligned__(8))); 47 + #endif 48 + 38 49 #ifdef CONFIG_IWMMXT 39 50 /* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ 40 51 #define IWMMXT_MAGIC 0x12ef842a ··· 85 74 * one of these. 86 75 */ 87 76 struct aux_sigframe { 77 + #ifdef CONFIG_CRUNCH 78 + struct crunch_sigframe crunch; 79 + #endif 88 80 #ifdef CONFIG_IWMMXT 89 81 struct iwmmxt_sigframe iwmmxt; 90 82 #endif