
/*--------------------------------------------------------------------*/
/*--- x86/Linux-specific kernel interface.         vki-x86-linux.h ---*/
/*--------------------------------------------------------------------*/

/*
   This file is part of Valgrind, a dynamic binary instrumentation
   framework.

   Copyright (C) 2000-2005 Julian Seward 
      jseward@acm.org

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307, USA.

   The GNU General Public License is contained in the file COPYING.
*/

#ifndef __VKI_X86_LINUX_H
#define __VKI_X86_LINUX_H

// x86 is little-endian.
#define VKI_LITTLE_ENDIAN  1


//----------------------------------------------------------------------
// From somewhere
//----------------------------------------------------------------------

/* PAGE_SHIFT determines the page size */
#define VKI_PAGE_SHIFT	12
#define VKI_PAGE_SIZE	(1UL << VKI_PAGE_SHIFT)
#define VKI_MAX_PAGE_SHIFT      VKI_PAGE_SHIFT
#define VKI_MAX_PAGE_SIZE       VKI_PAGE_SIZE

//----------------------------------------------------------------------
// From sys/signal.h
//----------------------------------------------------------------------

#define VKI_MINSIGSTKSZ	2048

#define VKI_SIG_BLOCK          1	/* for blocking signals */
#define VKI_SIG_UNBLOCK        2	/* for unblocking signals */
#define VKI_SIG_SETMASK        3	/* for setting the signal mask */

/* Type of a signal handler.  */
typedef void __vki_signalfn_t(int);
typedef __vki_signalfn_t *__vki_sighandler_t;

#define VKI_SIG_DFL	((__vki_sighandler_t)0)	/* default signal handling */
#define VKI_SIG_IGN	((__vki_sighandler_t)1)	/* ignore signal */

#define _VKI_NSIG	128
#define _VKI_NSIG_BPW	32
#define _VKI_NSIG_WORDS	(_VKI_NSIG / _VKI_NSIG_BPW)

typedef struct {
	vki_uint32_t sig[_VKI_NSIG_WORDS];
} vki_sigset_t;

#define VKI_SIGHUP		 1
#define VKI_SIGINT		 2
#define VKI_SIGQUIT		 3
#define VKI_SIGILL		 4
#define VKI_SIGTRAP		 5
#define VKI_SIGABRT		 6
#define VKI_SIGEMT		 7
#define VKI_SIGFPE		 8
#define VKI_SIGKILL		 9
#define VKI_SIGBUS		10
#define VKI_SIGSEGV		11
#define VKI_SIGSYS		12
#define VKI_SIGPIPE		13
#define VKI_SIGALRM		14
#define VKI_SIGTERM		15
#define VKI_SIGURG		16
#define VKI_SIGSTOP		17
#define VKI_SIGTSTP		18
#define VKI_SIGCONT		19
#define VKI_SIGCHLD		20
#define VKI_SIGTTIN		21
#define VKI_SIGTTOU		22
#define VKI_SIGIO		23
#define VKI_SIGXCPU		24
#define VKI_SIGXFSZ		25
#define VKI_SIGVTALRM		26
#define VKI_SIGPROF		27
#define VKI_SIGWINCH		28
#define VKI_SIGINFO		29
#define VKI_SIGUSR1		30
#define VKI_SIGUSR2		31
#define	VKI_SIGTHR		32

#define VKI_SIGRTMIN	65
#define VKI_SIGRTMAX	126

#define VKI_SA_ONSTACK		0x0001
#define VKI_SA_RESTART		0x0002
#define VKI_SA_RESETHAND	0x0004
#define VKI_SA_NOCLDSTOP	0x0008
#define VKI_SA_NODEFER		0x0010
#define VKI_SA_NOCLDWAIT	0x0020
#define VKI_SA_SIGINFO		0x0040

#define VKI_SS_ONSTACK	0x0001
#define VKI_SS_DISABLE	0x0004

#define VKI_SA_ONESHOT          VKI_SA_RESETHAND
#define VKI_SA_NOMASK		VKI_SA_NODEFER

struct vki_sigaction {
	__vki_sighandler_t ksa_handler;
	unsigned int sa_flags;
	vki_sigset_t sa_mask;		/* mask last for extensibility */
};

typedef struct vki_sigaltstack {
	void *ss_sp;
	vki_size_t ss_size;
	int ss_flags;
} vki_stack_t;

//----------------------------------------------------------------------
// From linux-2.6.8.1/include/asm-i386/sigcontext.h
//----------------------------------------------------------------------

/* QQQ not right */
struct _vki_fpreg {
	unsigned short significand[4];
	unsigned short exponent;
};

/* QQQ not right */
struct _vki_fpxreg {
	unsigned short significand[4];
	unsigned short exponent;
	unsigned short padding[3];
};

struct _vki_xmmreg {
	unsigned long element[4];
};

struct _vki_fpstate {
	/* Regular FPU environment */
	unsigned long 	cw;
	unsigned long	sw;
	unsigned long	tag;
	unsigned long	ipoff;
	unsigned long	cssel;
	unsigned long	dataoff;
	unsigned long	datasel;
	struct _vki_fpreg	_st[8];
	unsigned short	status;
	unsigned short	magic;		/* 0xffff = regular FPU data only */

	/* FXSR FPU environment */
	unsigned long	_fxsr_env[6];	/* FXSR FPU env is ignored */
	unsigned long	mxcsr;
	unsigned long	reserved;
	struct _vki_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
	struct _vki_xmmreg	_xmm[8];
	unsigned long	padding[56];
};

struct vki_sigcontext6 {
	vki_sigset_t sc_mask;
	int	onstack;
	int	gs;
	int	fs;
	int	es;
	int	ds;
	int	edi;
	int	esi;
	int	ebp;
	int	isp;
	int	ebx;
	int	edx;
	int	ecx;
	int	eax;
	int	trapno;
	int	err;
	int	eip;
	int	cs;
	int	eflags;
	int	esp;
	int	ss;
	int	len;	/* sizeof (mcontext_t) */
	int	fpformat;
	int	ownedfp;
	int	spare1[1];
	struct _vki_fpstate fpstate;
	int	spare2[8];
};

struct vki_sigcontext {
	vki_sigset_t sc_mask;
	int	onstack;
	int	gs;
	int	fs;
	int	es;
	int	ds;
	int	edi;
	int	esi;
	int	ebp;
	int	isp;
	int	ebx;
	int	edx;
	int	ecx;
	int	eax;
	int	trapno;
	int	err;
	int	eip;
	int	cs;
	int	eflags;
	int	esp;
	int	ss;
	int	sc_fpregs[28];
	int	sc_spare[17];
};

//----------------------------------------------------------------------
// From linux-2.6.8.1/include/asm-i386/user.h
//----------------------------------------------------------------------

struct vki_user_i387_struct {
	long	cwd;
	long	swd;
	long	twd;
	long	fip;
	long	fcs;
	long	foo;
	long	fos;
	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
	long	ex_sw;
	char	pad[64];
};

struct vki_user_fxsr_struct {
        unsigned short  cwd;
        unsigned short  swd;
        unsigned short  twd;
        unsigned short  fop;
        long    fip;
        long    fcs;
        long    foo;
        long    fos;
        long    mxcsr;
        long    reserved;
        long    st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
        long    xmm_space[32];  /* 8*16 bytes for each XMM-reg = 128 bytes */
        long    padding[56];
};

/*
 * This is the old layout of "struct pt_regs", and
 * is still the layout used by user mode.
 */
struct vki_user_regs_struct {
	int fs, es, ds;
	int edi, esi, ebp, isp, ebx, edx, ecx, eax;
	int trapno, err, eip, cs, eflags, esp, ss, gs;
};


//----------------------------------------------------------------------
// From linux-2.6.8.1/include/asm-i386/elf.h
//----------------------------------------------------------------------

typedef unsigned long vki_elf_greg_t;

#define VKI_ELF_NGREG (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t))
typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG];

typedef struct vki_user_i387_struct vki_elf_fpregset_t;
typedef struct vki_user_fxsr_struct vki_elf_fpxregset_t;

#define VKI_AT_SYSINFO		32

//----------------------------------------------------------------------
// From linux-2.6.8.1/include/asm-i386/ucontext.h
//----------------------------------------------------------------------

struct vki_mcontext6 {
	int	onstack;
	int	gs;
	int	fs;
	int	es;
	int	ds;
	int	edi;
	int	esi;
	int	ebp;
	int	isp;
	int	ebx;
	int	edx;
	int	ecx;
	int	eax;
	int	trapno;
	int	err;
	int	eip;
	int	cs;
	int	eflags;
	int	esp;
	int	ss;
	int	len;
	int	fpformat;
	int	ownedfp;
	int	spare1[1];
	struct _vki_fpstate fpstate;
	int	spare2[8];
};
#define VKI_FPFMT_NODEV		0x10000
#define VKI_FPFMT_387		0x10001
#define VKI_FPFMT_XMM		0x10002

#define VKI_FPOWNED_NONE	0x20000
#define VKI_FPOWNED_FPU		0x20001
#define VKI_FPOWNED_PCB		0x20002

struct vki_mcontext {
	int	onstack;
	int	gs;
	int	fs;
	int	es;
	int	ds;
	int	edi;
	int	esi;
	int	ebp;
	int	isp;
	int	ebx;
	int	edx;
	int	ecx;
	int	eax;
	int	trapno;
	int	err;
	int	eip;
	int	cs;
	int	eflags;
	int	esp;
	int	ss;
	int	fpregs[28];
	int	spare[17];
};

struct vki_ucontext6 {
	vki_sigset_t		uc_sigmask;
	struct vki_mcontext6	uc_mcontext;
	struct vki_ucontext6    *uc_link;
	vki_stack_t		uc_stack;
	int			uc_flags;
#define	VKI_UCF_SWAPPED	1
	unsigned int		__spare__[4];
};

struct vki_ucontext {
	vki_sigset_t		uc_sigmask;
	struct vki_mcontext	uc_mcontext;
	struct vki_ucontext    *uc_link;
	vki_stack_t		uc_stack;
	unsigned int		__spare__[8];
};

#if 0

//----------------------------------------------------------------------
// From linux-2.6.8.1/include/asm-i386/ldt.h
//----------------------------------------------------------------------

/* [[Nb: This is the structure passed to the modify_ldt syscall.  Just so as
   to confuse and annoy everyone, this is _not_ the same as an
   VgLdtEntry and has to be translated into such.  The logic for doing
   so, in vg_ldt.c, is copied from the kernel sources.]] */
struct vki_user_desc {
	unsigned int  entry_number;
	unsigned long base_addr;
	unsigned int  limit;
	unsigned int  seg_32bit:1;
	unsigned int  contents:2;
	unsigned int  read_exec_only:1;
	unsigned int  limit_in_pages:1;
	unsigned int  seg_not_present:1;
	unsigned int  useable:1;
        // [[Nb: this field is not in the kernel sources, but it has always
        // been in the Valgrind sources so I will keep it there in case it's
        // important... this is an x86-defined data structure so who
        // knows;  maybe it's important to set this field to zero at some
        // point.  --njn]]
	unsigned int  reserved:25;
};

// [[Nb: for our convenience within Valgrind, use a more specific name]]
typedef struct vki_user_desc vki_modify_ldt_t;

#endif

//----------------------------------------------------------------------
// And that's it!
//----------------------------------------------------------------------

#endif // __VKI_X86_LINUX_H

/*--------------------------------------------------------------------*/
/*--- end                                                          ---*/
/*--------------------------------------------------------------------*/
