[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: siginfo_t structure is not filled in the signal handler



Hi,

here is my patch for some version of qemu to get SIGINFO
and mcontext right. The special problem with qemu was
that it included <sys/ucontext.h> which was broken on
my system.. my solution was to define own includes with
all necessary defs. It has also some code to get at the
details of exception frames like addr, r/w etc.

The code is is mostly cut&paste from other GPL files and
thus GPL.


Richard


diff -urN qemu-cvs/cpu-exec.c qemu-cvs-new/cpu-exec.c
--- qemu-cvs/cpu-exec.c	Fri Mar  5 14:53:07 2004
+++ qemu-cvs-new/cpu-exec.c	Wed Mar 17 18:41:40 2004
@@ -890,19 +890,52 @@
 
 #elif defined(__mc68000)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
-                       void *puc)
+#include "l68k.h"
+
+int cpu_signal_handler(int signr, struct siginfo *info, void *xx)
 {
-    struct ucontext *uc = puc;
-    unsigned long pc;
-    int is_write;
-    
-    pc = uc->uc_mcontext.gregs[16];
-    /* XXX: compute is_write */
-    is_write = 0;
-    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
-                             is_write,
-                             &uc->uc_sigmask, puc);
+  struct Mucontext *puc=xx;
+  int format=((puc->uc_formatvec)>>12)&0xf;
+  unsigned long ea,is_write;
+  Frame *framedata = &(puc->uc_extra);
+
+#ifdef TEST_SEGV
+  printf("exception vec %d, fmt %d\n",vecnum,format);
+#endif
+  switch (format)
+    {
+      case 4: ea=framedata->fmt4.effaddr;
+	if ( (framedata->fmt4.pc) & MMU060_MA)
+	  ea=PAGEX(PAGEI(ea+4));
+	is_write = (((framedata->fmt4.pc) & MMU060_RW) == MMU060_RW_W) ||
+	  (((framedata->fmt4.pc) & MMU060_MA) == MMU060_RW_RMW );
+	break;
+      case 7: ea=framedata->fmt7.faddr;
+	is_write = (framedata->fmt7.ssw&RW_040) != 0;
+#ifdef TEST_SEGV
+       printf("segv: ssw=%x, faddr= %x, \n\twb2s=%x, wb2a=%x, wb3s=%x, wb3a=%d\n"
+              "MA=%x, RW=%x\n ",
+	      framedata->fmt7.ssw, framedata->fmt7.faddr,
+	      framedata->fmt7.wb2s, framedata->fmt7.wb2a,
+	      framedata->fmt7.wb3s, framedata->fmt7.wb3a,
+	      framedata->fmt7.ssw&MA_040, framedata->fmt7.ssw&RW_040
+	      );
+#endif
+	 if (framedata->fmt7.ssw&MA_040) {
+	     ea=PAGEX(PAGEI(ea+4));
+	     /*printf("MA set\n");*/
+	       }
+       break;
+      case 0xa: ea=framedata->fmta.daddr; break;
+      case 0xb: ea=framedata->fmtb.daddr; break;
+    default:
+      printf("illegal exception format\n");
+      exit(1);
+    }
+
+  return handle_cpu_signal(puc->uc_mcontext.gregs[16], ea,
+			   is_write,
+			   &(puc->uc_sigmask), xx);
 }
 
 #else


diff -urN qemu-cvs/dyngen.h qemu-cvs-new/dyngen.h
--- qemu-cvs/dyngen.h	Fri Mar  5 14:53:07 2004
+++ qemu-cvs-new/dyngen.h	Wed Mar 17 18:35:57 2004
@@ -98,7 +98,10 @@
 #include <asm/cachectl.h>
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-    cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
+    unsigned long _start=(start>>4)<<4;
+    unsigned long _stop=((stop+15)>>4)<<4;
+
+    cacheflush(_start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,_stop-_start);
 }
 #endif
 


diff -urN qemu-cvs/l68k.h qemu-cvs-new/l68k.h
--- qemu-cvs/l68k.h	Thu Jan  1 01:00:00 1970
+++ qemu-cvs-new/l68k.h	Wed Mar 17 18:47:12 2004
@@ -0,0 +1,206 @@
+/*
+ * m68k expcetion frame formats, mostly copied together from various
+ * Linux kernel include files.
+ */
+
+typedef union {
+    struct {
+      unsigned long  iaddr;	/* instruction address */
+    } fmt2;
+    struct {
+      unsigned long  effaddr;	/* effective address */
+    } fmt3;
+    struct {
+      unsigned long  effaddr;	/* effective address */
+      unsigned long  pc;	/* fslw or pc of faulted instr */
+    } fmt4;
+    struct {
+      unsigned long  effaddr;	/* effective address */
+      unsigned short ssw;	/* special status word */
+      unsigned short wb3s;	/* write back 3 status */
+      unsigned short wb2s;	/* write back 2 status */
+      unsigned short wb1s;	/* write back 1 status */
+      unsigned long  faddr;	/* fault address */
+      unsigned long  wb3a;	/* write back 3 address */
+      unsigned long  wb3d;	/* write back 3 data */
+      unsigned long  wb2a;	/* write back 2 address */
+      unsigned long  wb2d;	/* write back 2 data */
+      unsigned long  wb1a;	/* write back 1 address */
+      unsigned long  wb1dpd0;	/* write back 1 data/push data 0*/
+      unsigned long  pd1;	/* push data 1*/
+      unsigned long  pd2;	/* push data 2*/
+      unsigned long  pd3;	/* push data 3*/
+    } fmt7;
+    struct {
+      unsigned long  iaddr;	/* instruction address */
+      unsigned short int1[4];	/* internal registers */
+    } fmt9;
+    struct {
+      unsigned short int1;
+      unsigned short ssw;	/* special status word */
+      unsigned short isc;	/* instruction stage c */
+      unsigned short isb;	/* instruction stage b */
+      unsigned long  daddr;	/* data cycle fault address */
+      unsigned short int2[2];
+      unsigned long  dobuf;	/* data cycle output buffer */
+      unsigned short int3[2];
+    } fmta;
+    struct {
+      unsigned short int1;
+      unsigned short ssw;	/* special status word */
+      unsigned short isc;	/* instruction stage c */
+      unsigned short isb;	/* instruction stage b */
+      unsigned long  daddr;	/* data cycle fault address */
+      unsigned short int2[2];
+      unsigned long  dobuf;	/* data cycle output buffer */
+      unsigned short int3[4];
+      unsigned long  baddr;	/* stage B address */
+      unsigned short int4[2];
+      unsigned long  dibuf;	/* data cycle input buffer */
+      unsigned short int5[3];
+      unsigned	   ver : 4;	/* stack frame version # */
+      unsigned	   int6:12;
+      unsigned short int7[18];
+    } fmtb;
+} Frame;
+
+
+
+#ifndef _ASM_M68k_SIGCONTEXT_H
+#define _ASM_M68k_SIGCONTEXT_H
+
+struct sigcontext {
+	unsigned long  sc_mask; 	/* old sigmask */
+	unsigned long  sc_usp;		/* old user stack pointer */
+	unsigned long  sc_d0;
+	unsigned long  sc_d1;
+	unsigned long  sc_a0;
+	unsigned long  sc_a1;
+	unsigned short sc_sr;
+	unsigned long  sc_pc;
+	unsigned short sc_formatvec;
+	unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
+	unsigned long  sc_fpcntl[3];
+	unsigned char  sc_fpstate[216];
+};
+#endif
+
+
+
+#ifndef MUCONTEXT_H
+#define MUCONTEXT_H
+
+typedef int greg_t;
+#define NGREG 18
+typedef greg_t gregset_t[NGREG];
+
+typedef struct Mfpregset {
+	int f_pcr;
+	int f_psr;
+	int f_fpiaddr;
+	int f_fpregs[8][3];
+} Mfpregset_t;
+
+struct mcontext {
+	int version;
+	gregset_t gregs;
+	fpregset_t fpregs;
+};
+
+#define MCONTEXT_VERSION 2
+
+struct Mucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	struct mcontext	  uc_mcontext;
+	unsigned long	  uc_filler[80];
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+#define FPCONTEXT_SIZE	216
+#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
+#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
+
+
+#endif
+
+/* bits for 68040 special status word */
+#define CP_040	(0x8000)
+#define CU_040	(0x4000)
+#define CT_040	(0x2000)
+#define CM_040	(0x1000)
+#define MA_040	(0x0800)
+#define ATC_040 (0x0400)
+#define LK_040	(0x0200)
+#define RW_040	(0x0100)
+#define SIZ_040 (0x0060)
+#define TT_040	(0x0018)
+#define TM_040	(0x0007)
+
+/* bits for 68040 write back status word */
+#define WBV_040   (0x80)
+#define WBSIZ_040 (0x60)
+#define WBBYT_040 (0x20)
+#define WBWRD_040 (0x40)
+#define WBLNG_040 (0x00)
+#define WBTT_040  (0x18)
+#define WBTM_040  (0x07)
+
+/* bus access size codes */
+#define BA_SIZE_BYTE    (0x20)
+#define BA_SIZE_WORD    (0x40)
+#define BA_SIZE_LONG    (0x00)
+#define BA_SIZE_LINE    (0x60)
+
+/* bus access transfer type codes */
+#define BA_TT_MOVE16    (0x08)
+
+/* bits for 68040 MMU status register (mmusr) */
+#define MMU_B_040   (0x0800)
+#define MMU_G_040   (0x0400)
+#define MMU_S_040   (0x0080)
+#define MMU_CM_040  (0x0060)
+#define MMU_M_040   (0x0010)
+#define MMU_WP_040  (0x0004)
+#define MMU_T_040   (0x0002)
+#define MMU_R_040   (0x0001)
+
+/* bits in the 68060 fault status long word (FSLW) */
+#define	MMU060_MA	(0x08000000)	/* misaligned */
+#define	MMU060_LK	(0x02000000)	/* locked transfer */
+#define	MMU060_RW	(0x01800000)	/* read/write */
+# define MMU060_RW_W	(0x00800000)	/* write */
+# define MMU060_RW_R	(0x01000000)	/* read */
+# define MMU060_RW_RMW	(0x01800000)	/* read/modify/write */
+# define MMU060_W		(0x00800000)	/* general write, includes rmw */
+#define	MMU060_SIZ	(0x00600000)	/* transfer size */
+#define	MMU060_TT	(0x00180000)	/* transfer type (TT) bits */
+#define	MMU060_TM	(0x00070000)	/* transfer modifier (TM) bits */
+#define	MMU060_IO	(0x00008000)	/* instruction or operand */
+#define	MMU060_PBE	(0x00004000)	/* push buffer bus error */
+#define	MMU060_SBE	(0x00002000)	/* store buffer bus error */
+#define	MMU060_PTA	(0x00001000)	/* pointer A fault */
+#define	MMU060_PTB	(0x00000800)	/* pointer B fault */
+#define	MMU060_IL	(0x00000400)	/* double indirect descr fault */
+#define	MMU060_PF	(0x00000200)	/* page fault (invalid descr) */
+#define	MMU060_SP	(0x00000100)	/* supervisor protection */
+#define	MMU060_WP	(0x00000080)	/* write protection */
+#define	MMU060_TWE	(0x00000040)	/* bus error on table search */
+#define	MMU060_RE	(0x00000020)	/* bus error on read */
+#define	MMU060_WE	(0x00000010)	/* bus error on write */
+#define	MMU060_TTR	(0x00000008)	/* error caused by TTR translation */
+#define	MMU060_BPE	(0x00000004)	/* branch prediction error */
+#define	MMU060_SEE	(0x00000001)	/* software emulated error */
+
+/* cases of missing or invalid descriptors */
+#define MMU060_DESC_ERR	(MMU060_TWE | MMU060_PTA | MMU060_PTB | \
+						 MMU060_IL  | MMU060_PF)
+/* bits that indicate real errors */
+#define MMU060_ERR_BITS	(MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | \
+						 MMU060_SP  | MMU060_WP  | MMU060_RE | \
+						 MMU060_WE)
+
+#define PAGEX(addr) (4096*(addr))
+#define PAGEI(addr) ((addr)/4096)
+



Reply to: