diff mbox

[04/35] tcg-s390: Compute is_write in cpu_signal_handler.

Message ID 1275678883-7082-5-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson June 4, 2010, 7:14 p.m. UTC
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 cpu-exec.c |   42 +++++++++++++++++++++++++++++++++++++++---
 1 files changed, 39 insertions(+), 3 deletions(-)

Comments

Aurelien Jarno June 9, 2010, 10:54 p.m. UTC | #1
On Fri, Jun 04, 2010 at 12:14:12PM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  cpu-exec.c |   42 +++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 39 insertions(+), 3 deletions(-)

Thanks, applied.

> diff --git a/cpu-exec.c b/cpu-exec.c
> index c776605..026980a 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -1156,11 +1156,47 @@ int cpu_signal_handler(int host_signum, void *pinfo,
>      siginfo_t *info = pinfo;
>      struct ucontext *uc = puc;
>      unsigned long pc;
> -    int is_write;
> +    uint16_t *pinsn;
> +    int is_write = 0;
>  
>      pc = uc->uc_mcontext.psw.addr;
> -    /* XXX: compute is_write */
> -    is_write = 0;
> +
> +    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
> +       of the normal 2 arguments.  The 3rd argument contains the "int_code"
> +       from the hardware which does in fact contain the is_write value.
> +       The rt signal handler, as far as I can tell, does not give this value
> +       at all.  Not that we could get to it from here even if it were.  */
> +    /* ??? This is not even close to complete, since it ignores all
> +       of the read-modify-write instructions.  */
> +    pinsn = (uint16_t *)pc;
> +    switch (pinsn[0] >> 8) {
> +    case 0x50: /* ST */
> +    case 0x42: /* STC */
> +    case 0x40: /* STH */
> +        is_write = 1;
> +        break;
> +    case 0xc4: /* RIL format insns */
> +        switch (pinsn[0] & 0xf) {
> +        case 0xf: /* STRL */
> +        case 0xb: /* STGRL */
> +        case 0x7: /* STHRL */
> +            is_write = 1;
> +        }
> +        break;
> +    case 0xe3: /* RXY format insns */
> +        switch (pinsn[2] & 0xff) {
> +        case 0x50: /* STY */
> +        case 0x24: /* STG */
> +        case 0x72: /* STCY */
> +        case 0x70: /* STHY */
> +        case 0x8e: /* STPQ */
> +        case 0x3f: /* STRVH */
> +        case 0x3e: /* STRV */
> +        case 0x2f: /* STRVG */
> +            is_write = 1;
> +        }
> +        break;
> +    }
>      return handle_cpu_signal(pc, (unsigned long)info->si_addr,
>                               is_write, &uc->uc_sigmask, puc);
>  }
> -- 
> 1.7.0.1
> 
> 
>
diff mbox

Patch

diff --git a/cpu-exec.c b/cpu-exec.c
index c776605..026980a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -1156,11 +1156,47 @@  int cpu_signal_handler(int host_signum, void *pinfo,
     siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
-    int is_write;
+    uint16_t *pinsn;
+    int is_write = 0;
 
     pc = uc->uc_mcontext.psw.addr;
-    /* XXX: compute is_write */
-    is_write = 0;
+
+    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
+       of the normal 2 arguments.  The 3rd argument contains the "int_code"
+       from the hardware which does in fact contain the is_write value.
+       The rt signal handler, as far as I can tell, does not give this value
+       at all.  Not that we could get to it from here even if it were.  */
+    /* ??? This is not even close to complete, since it ignores all
+       of the read-modify-write instructions.  */
+    pinsn = (uint16_t *)pc;
+    switch (pinsn[0] >> 8) {
+    case 0x50: /* ST */
+    case 0x42: /* STC */
+    case 0x40: /* STH */
+        is_write = 1;
+        break;
+    case 0xc4: /* RIL format insns */
+        switch (pinsn[0] & 0xf) {
+        case 0xf: /* STRL */
+        case 0xb: /* STGRL */
+        case 0x7: /* STHRL */
+            is_write = 1;
+        }
+        break;
+    case 0xe3: /* RXY format insns */
+        switch (pinsn[2] & 0xff) {
+        case 0x50: /* STY */
+        case 0x24: /* STG */
+        case 0x72: /* STCY */
+        case 0x70: /* STHY */
+        case 0x8e: /* STPQ */
+        case 0x3f: /* STRVH */
+        case 0x3e: /* STRV */
+        case 0x2f: /* STRVG */
+            is_write = 1;
+        }
+        break;
+    }
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write, &uc->uc_sigmask, puc);
 }