/*
 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
 * Licensed under the GPL
 */

#include "linux/signal.h"
#include "linux/ptrace.h"
#include "asm/current.h"
#include "asm/ucontext.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"
#include "frame_kern.h"
#include "signal_user.h"
#include "sigcontext.h"
#include "registers.h"
#include "mode.h"

#ifdef CONFIG_MODE_SKAS

#include "skas.h"

static int copy_sc_from_user_skas(struct pt_regs *regs,
				  struct sigcontext *from)
{
  	struct sigcontext sc;
	unsigned long fpregs[HOST_FP_SIZE];
	int err;

	err = copy_from_user(&sc, from, sizeof(sc));
	err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
	if(err)
		return(err);

	REGS_GS(regs->regs.skas.regs) = sc.gs;
	REGS_FS(regs->regs.skas.regs) = sc.fs;
	REGS_ES(regs->regs.skas.regs) = sc.es;
	REGS_DS(regs->regs.skas.regs) = sc.ds;
	REGS_EDI(regs->regs.skas.regs) = sc.edi;
	REGS_ESI(regs->regs.skas.regs) = sc.esi;
	REGS_EBP(regs->regs.skas.regs) = sc.ebp;
	REGS_SP(regs->regs.skas.regs) = sc.esp;
	REGS_EBX(regs->regs.skas.regs) = sc.ebx;
	REGS_EDX(regs->regs.skas.regs) = sc.edx;
	REGS_ECX(regs->regs.skas.regs) = sc.ecx;
	REGS_EAX(regs->regs.skas.regs) = sc.eax;
	REGS_IP(regs->regs.skas.regs) = sc.eip;
	REGS_CS(regs->regs.skas.regs) = sc.cs;
	REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
	REGS_SS(regs->regs.skas.regs) = sc.ss;

	err = restore_fp_registers(userspace_pid[0], fpregs);
	if(err < 0){
	  	printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
		       "errno = %d\n", err);
		return(1);
	}

	return(0);
}

int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
                         struct pt_regs *regs)
{
  	struct sigcontext sc;
	unsigned long fpregs[HOST_FP_SIZE];
	struct faultinfo * fi = &current->thread.arch.faultinfo;
	int err;

	sc.gs = REGS_GS(regs->regs.skas.regs);
	sc.fs = REGS_FS(regs->regs.skas.regs);
	sc.es = REGS_ES(regs->regs.skas.regs);
	sc.ds = REGS_DS(regs->regs.skas.regs);
	sc.edi = REGS_EDI(regs->regs.skas.regs);
	sc.esi = REGS_ESI(regs->regs.skas.regs);
	sc.ebp = REGS_EBP(regs->regs.skas.regs);
	sc.esp = REGS_SP(regs->regs.skas.regs);
	sc.ebx = REGS_EBX(regs->regs.skas.regs);
	sc.edx = REGS_EDX(regs->regs.skas.regs);
	sc.ecx = REGS_ECX(regs->regs.skas.regs);
	sc.eax = REGS_EAX(regs->regs.skas.regs);
	sc.eip = REGS_IP(regs->regs.skas.regs);
	sc.cs = REGS_CS(regs->regs.skas.regs);
	sc.eflags = REGS_EFLAGS(regs->regs.skas.regs);
	sc.esp_at_signal = regs->regs.skas.regs[UESP];
	sc.ss = regs->regs.skas.regs[SS];
        sc.cr2 = fi->cr2;
        sc.err = fi->error_code;
        sc.trapno = fi->trap_no;

	err = save_fp_registers(userspace_pid[0], fpregs);
	if(err < 0){
	  	printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
		       "errno = %d\n", err);
		return(1);
	}
	to_fp = (to_fp ? to_fp : (struct _fpstate *) (to + 1));
	sc.fpstate = to_fp;

	if(err)
	  	return(err);

	return(copy_to_user(to, &sc, sizeof(sc)) ||
	       copy_to_user(to_fp, fpregs, sizeof(fpregs)));
}
#endif

#ifdef CONFIG_MODE_TT

/* These copy a sigcontext to/from userspace.  They copy the fpstate pointer,
 * blowing away the old, good one.  So, that value is saved, and then restored
 * after the sigcontext copy.  In copy_from, the variable holding the saved
 * fpstate pointer, and the sigcontext that it should be restored to are both
 * in the kernel, so we can just restore using an assignment.  In copy_to, the
 * saved pointer is in the kernel, but the sigcontext is in userspace, so we
 * copy_to_user it.
 */
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
			 int fpsize)
{
	struct _fpstate *to_fp, *from_fp;
	unsigned long sigs;
	int err;

	to_fp = to->fpstate;
	sigs = to->oldmask;
	err = copy_from_user(to, from, sizeof(*to));
	from_fp = to->fpstate;
	to->oldmask = sigs;
	to->fpstate = to_fp;
	if(to_fp != NULL)
		err |= copy_from_user(to_fp, from_fp, fpsize);
	return(err);
}

int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
		       struct sigcontext *from, int fpsize)
{
	struct _fpstate *to_fp, *from_fp;
	int err;

	to_fp =	(fp ? fp : (struct _fpstate *) (to + 1));
	from_fp = from->fpstate;
	err = copy_to_user(to, from, sizeof(*to));
	if(from_fp != NULL){
		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
		err |= copy_to_user(to_fp, from_fp, fpsize);
	}
	return(err);
}
#endif

static int copy_sc_from_user(struct pt_regs *to, void __user *from)
{
	int ret;

	ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
					       sizeof(struct _fpstate)),
			  copy_sc_from_user_skas(to, from));
	return(ret);
}

static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
			   struct pt_regs *from)
{
	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
					      sizeof(*fp)),
                           copy_sc_to_user_skas(to, fp, from)));
}

static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
				 sigset_t *set, unsigned long sp)
{
	int err = 0;

	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs);
	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
	return(err);
}

struct sigframe
{
	char *pretcode;
	int sig;
	struct sigcontext sc;
	struct _fpstate fpstate;
	unsigned long extramask[_NSIG_WORDS-1];
	char retcode[8];
};

struct rt_sigframe
{
	char *pretcode;
	int sig;
	struct siginfo *pinfo;
	void *puc;
	struct siginfo info;
	struct ucontext uc;
	struct _fpstate fpstate;
	char retcode[8];
};

int setup_signal_stack_sc(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs *regs,
			  sigset_t *mask)
{
	struct sigframe __user *frame;
	void *restorer;
	int err = 0;

	stack_top &= -8UL;
	frame = (struct sigframe *) stack_top - 1;
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return 1;

	restorer = (void *) frame->retcode;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	err |= __put_user(restorer, &frame->pretcode);
	err |= __put_user(sig, &frame->sig);
	err |= copy_sc_to_user(&frame->sc, NULL, regs);
	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
	if (_NSIG_WORDS > 1)
		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
				      sizeof(frame->extramask));

	/*
	 * This is popl %eax ; movl $,%eax ; int $0x80
	 *
	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
	 * reasons and because gdb uses it as a signature to notice
	 * signal handler stack frames.
	 */
	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));

	if(err)
		return(err);

	PT_REGS_SP(regs) = (unsigned long) frame;
	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_EAX(regs) = (unsigned long) sig;
	PT_REGS_EDX(regs) = (unsigned long) 0;
	PT_REGS_ECX(regs) = (unsigned long) 0;

	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
		ptrace_notify(SIGTRAP);
	return(0);
}

int setup_signal_stack_si(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs *regs,
			  siginfo_t *info, sigset_t *mask)
{
	struct rt_sigframe __user *frame;
	void *restorer;
	int err = 0;

	stack_top &= -8UL;
	frame = (struct rt_sigframe *) stack_top - 1;
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return 1;

	restorer = (void *) frame->retcode;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	err |= __put_user(restorer, &frame->pretcode);
	err |= __put_user(sig, &frame->sig);
	err |= __put_user(&frame->info, &frame->pinfo);
	err |= __put_user(&frame->uc, &frame->puc);
	err |= copy_siginfo_to_user(&frame->info, info);
	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
				     PT_REGS_SP(regs));

	/*
	 * This is movl $,%eax ; int $0x80
	 *
	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
	 * reasons and because gdb uses it as a signature to notice
	 * signal handler stack frames.
	 */
	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));

	if(err)
		return(err);

	PT_REGS_SP(regs) = (unsigned long) frame;
	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_EAX(regs) = (unsigned long) sig;
	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;

	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
		ptrace_notify(SIGTRAP);
	return(0);
}

long sys_sigreturn(struct pt_regs regs)
{
	unsigned long sp = PT_REGS_SP(&current->thread.regs);
	struct sigframe __user *frame = (struct sigframe *)(sp - 8);
	sigset_t set;
	struct sigcontext __user *sc = &frame->sc;
	unsigned long __user *oldmask = &sc->oldmask;
	unsigned long __user *extramask = frame->extramask;
	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);

	if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
	   copy_from_user(&set.sig[1], extramask, sig_size))
		goto segfault;

	sigdelsetmask(&set, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if(copy_sc_from_user(&current->thread.regs, sc))
		goto segfault;

	/* Avoid ERESTART handling */
	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
	return(PT_REGS_SYSCALL_RET(&current->thread.regs));

 segfault:
	force_sig(SIGSEGV, current);
	return 0;
}

long sys_rt_sigreturn(struct pt_regs regs)
{
	unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
	struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
	sigset_t set;
	struct ucontext __user *uc = &frame->uc;
	int sig_size = _NSIG_WORDS * sizeof(unsigned long);

	if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
		goto segfault;

	sigdelsetmask(&set, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
		goto segfault;

	/* Avoid ERESTART handling */
	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
	return(PT_REGS_SYSCALL_RET(&current->thread.regs));

 segfault:
	force_sig(SIGSEGV, current);
	return 0;
}

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
