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

Commit 6f602afd authored by Thomas Meyer's avatar Thomas Meyer Committed by Richard Weinberger
Browse files

um: Fix FP register size for XSTATE/XSAVE

parent 569dbb88
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <asm/types.h>
#include <asm/page.h>
#include <asm/segment.h>
#include <sysdep/ptrace_user.h>

struct thread_info {
	struct task_struct	*task;		/* main task structure */
@@ -22,6 +23,8 @@ struct thread_info {
					 	   0-0xBFFFFFFF for user
						   0-0xFFFFFFFF for kernel */
	struct thread_info	*real_thread;    /* Points to non-IRQ stack */
	unsigned long aux_fp_regs[FP_SIZE];	/* auxiliary fp_regs to save/restore
						   them out-of-band */
};

#define INIT_THREAD_INFO(tsk)			\
+1 −1
Original line number Diff line number Diff line
@@ -278,7 +278,7 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
extern void userspace(struct uml_pt_regs *regs);
extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs);
extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
			  unsigned long stack);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
+2 −2
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ void new_thread_handler(void)
	 * callback returns only if the kernel thread execs a process
	 */
	n = fn(arg);
	userspace(&current->thread.regs.regs);
	userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
}

/* Called magically, see new_thread_handler above */
@@ -150,7 +150,7 @@ void fork_handler(void)

	current->thread.prev_sched = NULL;

	userspace(&current->thread.regs.regs);
	userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
}

int copy_thread(unsigned long clone_flags, unsigned long sp,
+8 −9
Original line number Diff line number Diff line
@@ -88,12 +88,11 @@ void wait_stub_done(int pid)

extern unsigned long current_stub_stack(void);

static void get_skas_faultinfo(int pid, struct faultinfo *fi)
static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
{
	int err;
	unsigned long fpregs[FP_SIZE];

	err = get_fp_registers(pid, fpregs);
	err = get_fp_registers(pid, aux_fp_regs);
	if (err < 0) {
		printk(UM_KERN_ERR "save_fp_registers returned %d\n",
		       err);
@@ -113,7 +112,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi)
	 */
	memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));

	err = put_fp_registers(pid, fpregs);
	err = put_fp_registers(pid, aux_fp_regs);
	if (err < 0) {
		printk(UM_KERN_ERR "put_fp_registers returned %d\n",
		       err);
@@ -121,9 +120,9 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi)
	}
}

static void handle_segv(int pid, struct uml_pt_regs * regs)
static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
{
	get_skas_faultinfo(pid, &regs->faultinfo);
	get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs);
	segv(regs->faultinfo, 0, 1, NULL);
}

@@ -332,7 +331,7 @@ int start_userspace(unsigned long stub_stack)
	return err;
}

void userspace(struct uml_pt_regs *regs)
void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
{
	int err, status, op, pid = userspace_pid[0];
	/* To prevent races if using_sysemu changes under us.*/
@@ -407,11 +406,11 @@ void userspace(struct uml_pt_regs *regs)
			case SIGSEGV:
				if (PTRACE_FULL_FAULTINFO) {
					get_skas_faultinfo(pid,
							   &regs->faultinfo);
							   &regs->faultinfo, aux_fp_regs);
					(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
							     regs);
				}
				else handle_segv(pid, regs);
				else handle_segv(pid, regs, aux_fp_regs);
				break;
			case SIGTRAP + 0x80:
			        handle_trap(pid, regs, local_using_sysemu);
+12 −6
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 */

#include <errno.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#ifdef __i386__
#include <sys/user.h>
@@ -31,7 +32,7 @@ int save_fp_registers(int pid, unsigned long *fp_regs)

	if (have_xstate_support) {
		iov.iov_base = fp_regs;
		iov.iov_len = sizeof(struct _xstate);
		iov.iov_len = FP_SIZE * sizeof(unsigned long);
		if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
			return -errno;
		return 0;
@@ -51,10 +52,9 @@ int restore_fp_registers(int pid, unsigned long *fp_regs)
{
#ifdef PTRACE_SETREGSET
	struct iovec iov;

	if (have_xstate_support) {
		iov.iov_base = fp_regs;
		iov.iov_len = sizeof(struct _xstate);
		iov.iov_len = FP_SIZE * sizeof(unsigned long);
		if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
			return -errno;
		return 0;
@@ -125,13 +125,19 @@ int put_fp_registers(int pid, unsigned long *regs)
void arch_init_registers(int pid)
{
#ifdef PTRACE_GETREGSET
	struct _xstate fp_regs;
	void * fp_regs;
	struct iovec iov;

	iov.iov_base = &fp_regs;
	iov.iov_len = sizeof(struct _xstate);
	fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
	if(fp_regs == NULL)
		return;

	iov.iov_base = fp_regs;
	iov.iov_len = FP_SIZE * sizeof(unsigned long);
	if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
		have_xstate_support = 1;

	free(fp_regs);
#endif
}
#endif
Loading