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: