Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d8eb502 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 23a3e178 a78ff111
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -9,6 +9,8 @@
#include <sysdep/ptrace.h>
#include <sysdep/ptrace.h>
#include <sysdep/archsetjmp.h>
#include <sysdep/archsetjmp.h>


extern int save_i387_registers(int pid, unsigned long *fp_regs);
extern int restore_i387_registers(int pid, unsigned long *fp_regs);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern int save_fpx_registers(int pid, unsigned long *fp_regs);
extern int save_fpx_registers(int pid, unsigned long *fp_regs);
+1 −1
Original line number Original line Diff line number Diff line
@@ -398,6 +398,6 @@ int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
{
	int cpu = current_thread_info()->cpu;
	int cpu = current_thread_info()->cpu;


	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
	return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
}
}
+20 −8
Original line number Original line Diff line number Diff line
@@ -29,23 +29,29 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {


static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
{
{
	struct uml_pt_regs r;
	struct uml_pt_regs *r;
	int save_errno = errno;
	int save_errno = errno;


	r.is_user = 0;
	r = malloc(sizeof(struct uml_pt_regs));
	if (!r)
		panic("out of memory");

	r->is_user = 0;
	if (sig == SIGSEGV) {
	if (sig == SIGSEGV) {
		/* For segfaults, we want the data from the sigcontext. */
		/* For segfaults, we want the data from the sigcontext. */
		get_regs_from_mc(&r, mc);
		get_regs_from_mc(r, mc);
		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
		GET_FAULTINFO_FROM_MC(r->faultinfo, mc);
	}
	}


	/* enable signals if sig isn't IRQ signal */
	/* enable signals if sig isn't IRQ signal */
	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
		unblock_signals();
		unblock_signals();


	(*sig_info[sig])(sig, si, &r);
	(*sig_info[sig])(sig, si, r);


	errno = save_errno;
	errno = save_errno;

	free(r);
}
}


/*
/*
@@ -83,11 +89,17 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)


static void timer_real_alarm_handler(mcontext_t *mc)
static void timer_real_alarm_handler(mcontext_t *mc)
{
{
	struct uml_pt_regs regs;
	struct uml_pt_regs *regs;

	regs = malloc(sizeof(struct uml_pt_regs));
	if (!regs)
		panic("out of memory");


	if (mc != NULL)
	if (mc != NULL)
		get_regs_from_mc(&regs, mc);
		get_regs_from_mc(regs, mc);
	timer_handler(SIGALRM, NULL, &regs);
	timer_handler(SIGALRM, NULL, regs);

	free(regs);
}
}


void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
+47 −2
Original line number Original line Diff line number Diff line
@@ -11,21 +11,56 @@
#endif
#endif
#include <longjmp.h>
#include <longjmp.h>
#include <sysdep/ptrace_user.h>
#include <sysdep/ptrace_user.h>
#include <sys/uio.h>
#include <asm/sigcontext.h>
#include <linux/elf.h>


int save_fp_registers(int pid, unsigned long *fp_regs)
int have_xstate_support;

int save_i387_registers(int pid, unsigned long *fp_regs)
{
{
	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
		return -errno;
		return -errno;
	return 0;
	return 0;
}
}


int restore_fp_registers(int pid, unsigned long *fp_regs)
int save_fp_registers(int pid, unsigned long *fp_regs)
{
	struct iovec iov;

	if (have_xstate_support) {
		iov.iov_base = fp_regs;
		iov.iov_len = sizeof(struct _xstate);
		if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
			return -errno;
		return 0;
	} else {
		return save_i387_registers(pid, fp_regs);
	}
}

int restore_i387_registers(int pid, unsigned long *fp_regs)
{
{
	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
		return -errno;
		return -errno;
	return 0;
	return 0;
}
}


int restore_fp_registers(int pid, unsigned long *fp_regs)
{
	struct iovec iov;

	if (have_xstate_support) {
		iov.iov_base = fp_regs;
		iov.iov_len = sizeof(struct _xstate);
		if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
			return -errno;
		return 0;
	} else {
		return restore_i387_registers(pid, fp_regs);
	}
}

#ifdef __i386__
#ifdef __i386__
int have_fpx_regs = 1;
int have_fpx_regs = 1;
int save_fpx_registers(int pid, unsigned long *fp_regs)
int save_fpx_registers(int pid, unsigned long *fp_regs)
@@ -85,6 +120,16 @@ int put_fp_registers(int pid, unsigned long *regs)
	return restore_fp_registers(pid, regs);
	return restore_fp_registers(pid, regs);
}
}


void arch_init_registers(int pid)
{
	struct _xstate fp_regs;
	struct iovec iov;

	iov.iov_base = &fp_regs;
	iov.iov_len = sizeof(struct _xstate);
	if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
		have_xstate_support = 1;
}
#endif
#endif


unsigned long get_thread_reg(int reg, jmp_buf *buf)
unsigned long get_thread_reg(int reg, jmp_buf *buf)
+3 −2
Original line number Original line Diff line number Diff line
@@ -194,7 +194,8 @@ static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *c
	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
	struct user_i387_struct fpregs;
	struct user_i387_struct fpregs;


	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
	err = save_i387_registers(userspace_pid[cpu],
				  (unsigned long *) &fpregs);
	if (err)
	if (err)
		return err;
		return err;


@@ -214,7 +215,7 @@ static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *c
	if (n > 0)
	if (n > 0)
		return -EFAULT;
		return -EFAULT;


	return restore_fp_registers(userspace_pid[cpu],
	return restore_i387_registers(userspace_pid[cpu],
				    (unsigned long *) &fpregs);
				    (unsigned long *) &fpregs);
}
}


Loading