#include "log.h"
#include "asm/restorer.h"
#include <compel/asm/fpu.h>
#include "asm/compat.h"
#include <compel/plugins/std/syscall-codes.h>

#ifdef CR_NOGLIBC
# include <compel/plugins/std/string.h>
#endif
#include "cpu.h"

asm (	"	.pushsection .text				\n"
	"	.global restore_rt_sigaction			\n"
	"	.code32						\n"
	"restore_rt_sigaction:					\n"
	"	mov %edx, %esi					\n"
	"	mov $0, %edx					\n"
	"	movl $"__stringify(__NR32_rt_sigaction)",%eax	\n"
	"	int $0x80					\n"
	"	ret						\n"
	"	.popsection					\n"
	"	.code64");
extern char restore_rt_sigaction;

/*
 * Call raw rt_sigaction syscall through int80 - so the ABI kernel choses
 * to deliver this signal would be i386.
 */
int arch_compat_rt_sigaction(void *stack32, int sig, rt_sigaction_t_compat *act)
{
	int ret;
	struct syscall_args32 arg = {};
	unsigned long act_stack = (unsigned long)stack32;

	/* To make sure the 32-bit stack was allocated in caller */
	if (act_stack >= (uint32_t)-1) {
		pr_err("compat rt_sigaction without 32-bit stack\n");
		return -1;
	}

	/*
	 * To be sure, that sigaction pointer lies under 4G,
	 * coping it on the bottom of the stack.
	 */
	memcpy(stack32, act, sizeof(rt_sigaction_t_compat));
	arg.nr		= __NR32_rt_sigaction;
	arg.arg0	= sig;
	arg.arg1	= (uint32_t)act_stack;			/* act */
	arg.arg2	= 0;					/* oldact */
	arg.arg3	= (uint32_t)sizeof(act->rt_sa_mask);	/* sigsetsize */

	do_full_int80(&arg);
	asm volatile ("\t movl %%eax,%0\n" : "=r"(ret));
	return ret;
}

