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

Merge branch 'for-linus-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:
"This contains a nice FPU fixup from Eli Cooper for UML"

* 'for-linus-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
um: add extended processor state save/restore support
um: extend fpstate to _xstate to support YMM registers
um: fix FPU state preservation around signal handlers

+95 -50
+2
arch/um/include/shared/registers.h
··· 9 9 #include <sysdep/ptrace.h> 10 10 #include <sysdep/archsetjmp.h> 11 11 12 + extern int save_i387_registers(int pid, unsigned long *fp_regs); 13 + extern int restore_i387_registers(int pid, unsigned long *fp_regs); 12 14 extern int save_fp_registers(int pid, unsigned long *fp_regs); 13 15 extern int restore_fp_registers(int pid, unsigned long *fp_regs); 14 16 extern int save_fpx_registers(int pid, unsigned long *fp_regs);
+1 -1
arch/um/kernel/process.c
··· 398 398 { 399 399 int cpu = current_thread_info()->cpu; 400 400 401 - return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu); 401 + return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu); 402 402 } 403 403
+20 -8
arch/um/os-Linux/signal.c
··· 29 29 30 30 static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) 31 31 { 32 - struct uml_pt_regs r; 32 + struct uml_pt_regs *r; 33 33 int save_errno = errno; 34 34 35 - r.is_user = 0; 35 + r = malloc(sizeof(struct uml_pt_regs)); 36 + if (!r) 37 + panic("out of memory"); 38 + 39 + r->is_user = 0; 36 40 if (sig == SIGSEGV) { 37 41 /* For segfaults, we want the data from the sigcontext. */ 38 - get_regs_from_mc(&r, mc); 39 - GET_FAULTINFO_FROM_MC(r.faultinfo, mc); 42 + get_regs_from_mc(r, mc); 43 + GET_FAULTINFO_FROM_MC(r->faultinfo, mc); 40 44 } 41 45 42 46 /* enable signals if sig isn't IRQ signal */ 43 47 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM)) 44 48 unblock_signals(); 45 49 46 - (*sig_info[sig])(sig, si, &r); 50 + (*sig_info[sig])(sig, si, r); 47 51 48 52 errno = save_errno; 53 + 54 + free(r); 49 55 } 50 56 51 57 /* ··· 89 83 90 84 static void timer_real_alarm_handler(mcontext_t *mc) 91 85 { 92 - struct uml_pt_regs regs; 86 + struct uml_pt_regs *regs; 87 + 88 + regs = malloc(sizeof(struct uml_pt_regs)); 89 + if (!regs) 90 + panic("out of memory"); 93 91 94 92 if (mc != NULL) 95 - get_regs_from_mc(&regs, mc); 96 - timer_handler(SIGALRM, NULL, &regs); 93 + get_regs_from_mc(regs, mc); 94 + timer_handler(SIGALRM, NULL, regs); 95 + 96 + free(regs); 97 97 } 98 98 99 99 void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
+47 -2
arch/x86/um/os-Linux/registers.c
··· 11 11 #endif 12 12 #include <longjmp.h> 13 13 #include <sysdep/ptrace_user.h> 14 + #include <sys/uio.h> 15 + #include <asm/sigcontext.h> 16 + #include <linux/elf.h> 14 17 15 - int save_fp_registers(int pid, unsigned long *fp_regs) 18 + int have_xstate_support; 19 + 20 + int save_i387_registers(int pid, unsigned long *fp_regs) 16 21 { 17 22 if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 18 23 return -errno; 19 24 return 0; 20 25 } 21 26 22 - int restore_fp_registers(int pid, unsigned long *fp_regs) 27 + int save_fp_registers(int pid, unsigned long *fp_regs) 28 + { 29 + struct iovec iov; 30 + 31 + if (have_xstate_support) { 32 + iov.iov_base = fp_regs; 33 + iov.iov_len = sizeof(struct _xstate); 34 + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 35 + return -errno; 36 + return 0; 37 + } else { 38 + return save_i387_registers(pid, fp_regs); 39 + } 40 + } 41 + 42 + int restore_i387_registers(int pid, unsigned long *fp_regs) 23 43 { 24 44 if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 25 45 return -errno; 26 46 return 0; 47 + } 48 + 49 + int restore_fp_registers(int pid, unsigned long *fp_regs) 50 + { 51 + struct iovec iov; 52 + 53 + if (have_xstate_support) { 54 + iov.iov_base = fp_regs; 55 + iov.iov_len = sizeof(struct _xstate); 56 + if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 57 + return -errno; 58 + return 0; 59 + } else { 60 + return restore_i387_registers(pid, fp_regs); 61 + } 27 62 } 28 63 29 64 #ifdef __i386__ ··· 120 85 return restore_fp_registers(pid, regs); 121 86 } 122 87 88 + void arch_init_registers(int pid) 89 + { 90 + struct _xstate fp_regs; 91 + struct iovec iov; 92 + 93 + iov.iov_base = &fp_regs; 94 + iov.iov_len = sizeof(struct _xstate); 95 + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) 96 + have_xstate_support = 1; 97 + } 123 98 #endif 124 99 125 100 unsigned long get_thread_reg(int reg, jmp_buf *buf)
+3 -2
arch/x86/um/ptrace_32.c
··· 194 194 int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 195 195 struct user_i387_struct fpregs; 196 196 197 - err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 197 + err = save_i387_registers(userspace_pid[cpu], 198 + (unsigned long *) &fpregs); 198 199 if (err) 199 200 return err; 200 201 ··· 215 214 if (n > 0) 216 215 return -EFAULT; 217 216 218 - return restore_fp_registers(userspace_pid[cpu], 217 + return restore_i387_registers(userspace_pid[cpu], 219 218 (unsigned long *) &fpregs); 220 219 } 221 220
+8 -8
arch/x86/um/ptrace_64.c
··· 222 222 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 223 223 { 224 224 int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 225 - long fpregs[HOST_FP_SIZE]; 225 + struct user_i387_struct fpregs; 226 226 227 - BUG_ON(sizeof(*buf) != sizeof(fpregs)); 228 - err = save_fp_registers(userspace_pid[cpu], fpregs); 227 + err = save_i387_registers(userspace_pid[cpu], 228 + (unsigned long *) &fpregs); 229 229 if (err) 230 230 return err; 231 231 232 - n = copy_to_user(buf, fpregs, sizeof(fpregs)); 232 + n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 233 233 if (n > 0) 234 234 return -EFAULT; 235 235 ··· 239 239 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 240 240 { 241 241 int n, cpu = ((struct thread_info *) child->stack)->cpu; 242 - long fpregs[HOST_FP_SIZE]; 242 + struct user_i387_struct fpregs; 243 243 244 - BUG_ON(sizeof(*buf) != sizeof(fpregs)); 245 - n = copy_from_user(fpregs, buf, sizeof(fpregs)); 244 + n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 246 245 if (n > 0) 247 246 return -EFAULT; 248 247 249 - return restore_fp_registers(userspace_pid[cpu], fpregs); 248 + return restore_i387_registers(userspace_pid[cpu], 249 + (unsigned long *) &fpregs); 250 250 } 251 251 252 252 long subarch_ptrace(struct task_struct *child, long request,
+1 -3
arch/x86/um/shared/sysdep/ptrace_64.h
··· 57 57 #define UPT_SYSCALL_ARG5(r) UPT_R8(r) 58 58 #define UPT_SYSCALL_ARG6(r) UPT_R9(r) 59 59 60 - static inline void arch_init_registers(int pid) 61 - { 62 - } 60 + extern void arch_init_registers(int pid); 63 61 64 62 #endif
+12 -25
arch/x86/um/signal.c
··· 225 225 } else 226 226 #endif 227 227 { 228 - struct user_i387_struct fp; 229 - 230 - err = copy_from_user(&fp, (void *)sc.fpstate, 231 - sizeof(struct user_i387_struct)); 228 + err = copy_from_user(regs->regs.fp, (void *)sc.fpstate, 229 + sizeof(struct _xstate)); 232 230 if (err) 233 231 return 1; 234 - 235 - err = restore_fp_registers(pid, (unsigned long *) &fp); 236 - if (err < 0) { 237 - printk(KERN_ERR "copy_sc_from_user - " 238 - "restore_fp_registers failed, errno = %d\n", 239 - -err); 240 - return 1; 241 - } 242 232 } 243 233 return 0; 244 234 } 245 235 246 236 static int copy_sc_to_user(struct sigcontext __user *to, 247 - struct _fpstate __user *to_fp, struct pt_regs *regs, 237 + struct _xstate __user *to_fp, struct pt_regs *regs, 248 238 unsigned long mask) 249 239 { 250 240 struct sigcontext sc; ··· 300 310 return 1; 301 311 } 302 312 303 - err = convert_fxsr_to_user(to_fp, &fpx); 313 + err = convert_fxsr_to_user(&to_fp->fpstate, &fpx); 304 314 if (err) 305 315 return 1; 306 316 307 - err |= __put_user(fpx.swd, &to_fp->status); 308 - err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); 317 + err |= __put_user(fpx.swd, &to_fp->fpstate.status); 318 + err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic); 309 319 if (err) 310 320 return 1; 311 321 312 - if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, 322 + if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx, 313 323 sizeof(struct user_fxsr_struct))) 314 324 return 1; 315 325 } else 316 326 #endif 317 327 { 318 - struct user_i387_struct fp; 319 - 320 - err = save_fp_registers(pid, (unsigned long *) &fp); 321 - if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) 328 + if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate))) 322 329 return 1; 323 330 } 324 331 ··· 324 337 325 338 #ifdef CONFIG_X86_32 326 339 static int copy_ucontext_to_user(struct ucontext __user *uc, 327 - struct _fpstate __user *fp, sigset_t *set, 340 + struct _xstate __user *fp, sigset_t *set, 328 341 unsigned long sp) 329 342 { 330 343 int err = 0; ··· 340 353 char __user *pretcode; 341 354 int sig; 342 355 struct sigcontext sc; 343 - struct _fpstate fpstate; 356 + struct _xstate fpstate; 344 357 unsigned long extramask[_NSIG_WORDS-1]; 345 358 char retcode[8]; 346 359 }; ··· 353 366 void __user *puc; 354 367 struct siginfo info; 355 368 struct ucontext uc; 356 - struct _fpstate fpstate; 369 + struct _xstate fpstate; 357 370 char retcode[8]; 358 371 }; 359 372 ··· 482 495 char __user *pretcode; 483 496 struct ucontext uc; 484 497 struct siginfo info; 485 - struct _fpstate fpstate; 498 + struct _xstate fpstate; 486 499 }; 487 500 488 501 int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+1 -1
arch/x86/um/user-offsets.c
··· 50 50 DEFINE(HOST_GS, GS); 51 51 DEFINE(HOST_ORIG_AX, ORIG_EAX); 52 52 #else 53 - DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); 53 + DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); 54 54 DEFINE_LONGS(HOST_BX, RBX); 55 55 DEFINE_LONGS(HOST_CX, RCX); 56 56 DEFINE_LONGS(HOST_DI, RDI);