qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v5] tcg-aarch64: Properly detect SIGSEGV writes


From: Richard Henderson
Subject: [Qemu-devel] [PATCH v5] tcg-aarch64: Properly detect SIGSEGV writes
Date: Wed, 16 Apr 2014 08:14:25 -0700

Since the kernel doesn't pass any info on the reason for the fault,
disassemble the instruction to detect a store.

Signed-off-by: Richard Henderson <address@hidden>
---

Rather than spam the rest of the reviewed patch series to the list,
I'm just sending the update of the one patch that had issues.

>From v4, Claudio correctly diagnosed that I had missed the 128-bit
stores.  Unfortunately, opcode 2 is used for both loads and stores,
so one has to use a different mask for them.

Previous revisions had a comment about how some of these tests could
be merged.  Adding another 7 for the 128-bit stores seemed a bridge
too far, so I did some easy merging.

There are two groups of insns that differ only in pre-/post-/no-increment,
or that vary only in fields that don't matter (register input vs immediate
input).  I no longer try to distinguish those.

In the case of C3.3.8-12, there are combinations of bits 10, 11, 21 that
are not valid insns.  But since we don't really need to be a full
disassembler I think that'll be fine for now.

With any luck the kernel patch that passes the relevent data down from
the trap will be accepted upstream soon, and this will just be legacy.


r~

---
 user-exec.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/user-exec.c b/user-exec.c
index bc58056..8ed6fec 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -465,16 +465,29 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 
 #elif defined(__aarch64__)
 
-int cpu_signal_handler(int host_signum, void *pinfo,
-                       void *puc)
+int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {
     siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
-    uint64_t pc;
-    int is_write = 0; /* XXX how to determine? */
+    uintptr_t pc = uc->uc_mcontext.pc;
+    uint32_t insn = *(uint32_t *)pc;
+    bool is_write;
 
-    pc = uc->uc_mcontext.pc;
-    return handle_cpu_signal(pc, (uint64_t)info->si_addr,
+    /* XXX: need kernel patch to get write flag faster.  */
+    is_write = (   (insn & 0xbfff0000) == 0x0c000000   /* C3.3.1 */
+                || (insn & 0xbfe00000) == 0x0c800000   /* C3.3.2 */
+                || (insn & 0xbfdf0000) == 0x0d000000   /* C3.3.3 */
+                || (insn & 0xbfc00000) == 0x0d800000   /* C3.3.4 */
+                || (insn & 0x3f400000) == 0x08000000   /* C3.3.6 */
+                || (insn & 0x3bc00000) == 0x39000000   /* C3.3.13 */
+                || (insn & 0x3fc00000) == 0x3d800000   /* ... 128bit */
+                /* Ingore bits 10, 11 & 21, controlling indexing.  */
+                || (insn & 0x3bc00000) == 0x38000000   /* C3.3.8-12 */
+                || (insn & 0x3fe00000) == 0x3c800000   /* ... 128bit */
+                /* Ignore bits 23 & 24, controlling indexing.  */
+                || (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
+
+    return handle_cpu_signal(pc, (uintptr_t)info->si_addr,
                              is_write, &uc->uc_sigmask, puc);
 }
 
-- 
1.9.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]