All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: laurent@vivier.eu, "Philippe Mathieu-Daudé" <f4bug@amsat.org>
Subject: [PATCH v2 03/41] accel/tcg: Split out handle_sigsegv_accerr_write
Date: Sat, 18 Sep 2021 11:44:49 -0700	[thread overview]
Message-ID: <20210918184527.408540-4-richard.henderson@linaro.org> (raw)
In-Reply-To: <20210918184527.408540-1-richard.henderson@linaro.org>

This is the major portion of handle_cpu_signal which is specific
to tcg, handling the page protections for the translations.
Most of the rest will migrate to linux-user/ shortly.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Pass guest address to handle_sigsegv_accerr_write.
---
 include/exec/exec-all.h |  12 +++++
 accel/tcg/user-exec.c   | 103 ++++++++++++++++++++++++----------------
 2 files changed, 74 insertions(+), 41 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index e54f8e5d65..5f94d799aa 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -673,6 +673,18 @@ static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
  */
 MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write);
 
+/**
+ * handle_sigsegv_accerr_write:
+ * @cpu: the cpu context
+ * @old_set: the sigset_t from the signal ucontext_t
+ * @host_pc: the host pc, adjusted for the signal
+ * @host_addr: the host address of the fault
+ *
+ * Return true if the write fault has been handled, and should be re-tried.
+ */
+bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set,
+                                 uintptr_t host_pc, abi_ptr guest_addr);
+
 /**
  * cpu_signal_handler
  * @signum: host signal number
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index e94f1fed00..6f4fc01b60 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -114,6 +114,54 @@ MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write)
     return is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
 }
 
+/**
+ * handle_sigsegv_accerr_write:
+ * @cpu: the cpu context
+ * @old_set: the sigset_t from the signal ucontext_t
+ * @host_pc: the host pc, adjusted for the signal
+ * @guest_addr: the guest address of the fault
+ *
+ * Return true if the write fault has been handled, and should be re-tried.
+ *
+ * Note that it is important that we don't call page_unprotect() unless
+ * this is really a "write to nonwriteable page" fault, because
+ * page_unprotect() assumes that if it is called for an access to
+ * a page that's writeable this means we had two threads racing and
+ * another thread got there first and already made the page writeable;
+ * so we will retry the access. If we were to call page_unprotect()
+ * for some other kind of fault that should really be passed to the
+ * guest, we'd end up in an infinite loop of retrying the faulting access.
+ */
+bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set,
+                                 uintptr_t host_pc, abi_ptr guest_addr)
+{
+    switch (page_unprotect(guest_addr, host_pc)) {
+    case 0:
+        /*
+         * Fault not caused by a page marked unwritable to protect
+         * cached translations, must be the guest binary's problem.
+         */
+        return false;
+    case 1:
+        /*
+         * Fault caused by protection of cached translation; TBs
+         * invalidated, so resume execution.  Retain helper_retaddr
+         * for a possible second fault.
+         */
+        return true;
+    case 2:
+        /*
+         * Fault caused by protection of cached translation, and the
+         * currently executing TB was modified and must be exited
+         * immediately.  Clear helper_retaddr for next execution.
+         */
+        cpu_exit_tb_from_sighandler(cpu, old_set);
+        /* NORETURN */
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /*
  * 'pc' is the host PC at which the exception was raised.
  * 'address' is the effective address of the memory exception.
@@ -125,8 +173,9 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
 {
     CPUState *cpu = current_cpu;
     CPUClass *cc;
-    unsigned long address = (unsigned long)info->si_addr;
+    unsigned long host_addr = (unsigned long)info->si_addr;
     MMUAccessType access_type = adjust_signal_pc(&pc, is_write);
+    abi_ptr guest_addr;
 
     /* For synchronous signals we expect to be coming from the vCPU
      * thread (so current_cpu should be valid) and either from running
@@ -143,49 +192,21 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
 
 #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
-           pc, address, is_write, *(unsigned long *)old_set);
+           pc, host_addr, is_write, *(unsigned long *)old_set);
 #endif
-    /* XXX: locking issue */
-    /* Note that it is important that we don't call page_unprotect() unless
-     * this is really a "write to nonwriteable page" fault, because
-     * page_unprotect() assumes that if it is called for an access to
-     * a page that's writeable this means we had two threads racing and
-     * another thread got there first and already made the page writeable;
-     * so we will retry the access. If we were to call page_unprotect()
-     * for some other kind of fault that should really be passed to the
-     * guest, we'd end up in an infinite loop of retrying the faulting
-     * access.
-     */
-    if (is_write && info->si_signo == SIGSEGV && info->si_code == SEGV_ACCERR &&
-        h2g_valid(address)) {
-        switch (page_unprotect(h2g(address), pc)) {
-        case 0:
-            /* Fault not caused by a page marked unwritable to protect
-             * cached translations, must be the guest binary's problem.
-             */
-            break;
-        case 1:
-            /* Fault caused by protection of cached translation; TBs
-             * invalidated, so resume execution.  Retain helper_retaddr
-             * for a possible second fault.
-             */
-            return 1;
-        case 2:
-            /* Fault caused by protection of cached translation, and the
-             * currently executing TB was modified and must be exited
-             * immediately.  Clear helper_retaddr for next execution.
-             */
-            cpu_exit_tb_from_sighandler(cpu, old_set);
-            /* NORETURN */
-
-        default:
-            g_assert_not_reached();
-        }
-    }
 
     /* Convert forcefully to guest address space, invalid addresses
        are still valid segv ones */
-    address = h2g_nocheck(address);
+    guest_addr = h2g_nocheck(host_addr);
+
+    /* XXX: locking issue */
+    if (is_write &&
+        info->si_signo == SIGSEGV &&
+        info->si_code == SEGV_ACCERR &&
+        h2g_valid(host_addr) &&
+        handle_sigsegv_accerr_write(cpu, old_set, pc, guest_addr)) {
+        return 1;
+    }
 
     /*
      * There is no way the target can handle this other than raising
@@ -194,7 +215,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
     sigprocmask(SIG_SETMASK, old_set, NULL);
 
     cc = CPU_GET_CLASS(cpu);
-    cc->tcg_ops->tlb_fill(cpu, address, 0, access_type,
+    cc->tcg_ops->tlb_fill(cpu, guest_addr, 0, access_type,
                           MMU_USER_IDX, false, pc);
     g_assert_not_reached();
 }
-- 
2.25.1



  parent reply	other threads:[~2021-09-18 18:48 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-18 18:44 [PATCH v2 00/41] linux-user: Streamline handling of SIGSEGV Richard Henderson
2021-09-18 18:44 ` [PATCH v2 01/41] accel/tcg: Split out adjust_signal_pc Richard Henderson
2021-09-18 18:44 ` [PATCH v2 02/41] accel/tcg: Move clear_helper_retaddr to cpu loop Richard Henderson
2021-09-19 19:35   ` Warner Losh
2021-09-18 18:44 ` Richard Henderson [this message]
2021-09-18 18:44 ` [PATCH v2 04/41] accel/tcg: Fold cpu_exit_tb_from_sighandler into caller Richard Henderson
2021-09-18 18:44 ` [PATCH v2 05/41] configure: Merge riscv32 and riscv64 host architectures Richard Henderson
2021-09-19 17:56   ` Philippe Mathieu-Daudé
2021-09-19 22:57   ` Alistair Francis
2021-09-18 18:44 ` [PATCH v2 06/41] linux-user: Reorg handling for SIGSEGV Richard Henderson
2021-09-19 18:02   ` Philippe Mathieu-Daudé
2021-09-19 19:01   ` Warner Losh
2021-09-19 23:01   ` Alistair Francis
2021-09-18 18:44 ` [PATCH v2 07/41] linux-user/host/x86: Populate host_signal.h Richard Henderson
2021-09-18 18:44 ` [PATCH v2 08/41] linux-user/host/ppc: " Richard Henderson
2021-09-19 19:34   ` Warner Losh
2021-09-18 18:44 ` [PATCH v2 09/41] linux-user/host/alpha: " Richard Henderson
2021-09-19 18:03   ` Philippe Mathieu-Daudé
2021-09-19 18:07     ` Richard Henderson
2021-09-19 18:11       ` Philippe Mathieu-Daudé
2021-09-19 18:13   ` Philippe Mathieu-Daudé
2021-09-18 18:44 ` [PATCH v2 10/41] linux-user/host/sparc: " Richard Henderson
2021-09-18 18:44 ` [PATCH v2 11/41] linux-user/host/arm: " Richard Henderson
2021-09-18 18:44 ` [PATCH v2 12/41] linux-user/host/aarch64: " Richard Henderson
2021-09-18 18:44 ` [PATCH v2 13/41] linux-user/host/s390: " Richard Henderson
2021-09-19 18:07   ` Philippe Mathieu-Daudé
2021-09-18 18:45 ` [PATCH v2 14/41] linux-user/host/mips: " Richard Henderson
2021-09-19 18:08   ` Philippe Mathieu-Daudé
2021-09-18 18:45 ` [PATCH v2 15/41] linux-user/host/riscv: " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 16/41] target/arm: Fixup comment re handle_cpu_signal Richard Henderson
2021-09-18 18:45 ` [PATCH v2 17/41] linux-user/host/riscv: Improve host_signal_write Richard Henderson
2021-09-18 18:45 ` [PATCH v2 18/41] linux-user/signal: Drop HOST_SIGNAL_PLACEHOLDER Richard Henderson
2021-09-19 18:18   ` Philippe Mathieu-Daudé
2021-09-19 18:59   ` Warner Losh
2021-09-18 18:45 ` [PATCH v2 19/41] hw/core: Add TCGCPUOps.record_sigsegv Richard Henderson
2021-09-19 18:22   ` Philippe Mathieu-Daudé
2021-09-19 18:24     ` Philippe Mathieu-Daudé
2021-09-19 18:32       ` Richard Henderson
2021-09-18 18:45 ` [PATCH v2 20/41] linux-user: Add raise_sigsegv Richard Henderson
2021-09-19 18:26   ` Philippe Mathieu-Daudé
2021-09-19 18:35   ` Richard Henderson
2021-09-19 18:43     ` Philippe Mathieu-Daudé
2021-09-19 18:53       ` Warner Losh
2021-09-18 18:45 ` [PATCH v2 21/41] target/alpha: Make alpha_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 22/41] target/arm: Use raise_sigsegv for mte tag lookup Richard Henderson
2021-09-18 18:45 ` [PATCH v2 23/41] target/arm: Implement arm_cpu_record_sigsegv Richard Henderson
2021-09-18 18:45 ` [PATCH v2 24/41] target/cris: Make cris_cpu_tlb_fill sysemu only Richard Henderson
2021-09-19 18:28   ` Philippe Mathieu-Daudé
2021-09-18 18:45 ` [PATCH v2 25/41] target/hexagon: Remove hexagon_cpu_tlb_fill Richard Henderson
2021-09-18 18:45 ` [PATCH v2 26/41] target/hppa: Make hppa_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 27/41] target/i386: Implement x86_cpu_record_sigsegv Richard Henderson
2021-09-19 18:32   ` Philippe Mathieu-Daudé
2021-09-19 18:59   ` Warner Losh
2021-09-18 18:45 ` [PATCH v2 28/41] target/m68k: Make m68k_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 29/41] target/microblaze: Make mb_cpu_tlb_fill " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 30/41] target/mips: Make mips_cpu_tlb_fill " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 31/41] target/nios2: Make nios2_cpu_tlb_fill " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 32/41] linux-user/openrisc: Adjust signal for EXCP_RANGE, EXCP_FPE Richard Henderson
2021-09-18 18:45 ` [PATCH v2 33/41] target/openrisc: Make openrisc_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 34/41] target/ppc: Implement ppc_cpu_record_sigsegv Richard Henderson
2021-09-19 18:37   ` Philippe Mathieu-Daudé
2021-09-18 18:45 ` [PATCH v2 35/41] target/riscv: Make riscv_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 36/41] target/s390x: Use probe_access_flags in s390_probe_access Richard Henderson
2021-09-18 18:45 ` [PATCH v2 37/41] target/s390x: Implement s390_cpu_record_sigsegv Richard Henderson
2021-09-19 18:39   ` Philippe Mathieu-Daudé
2021-09-18 18:45 ` [PATCH v2 38/41] target/sh4: Make sh4_cpu_tlb_fill sysemu only Richard Henderson
2021-09-18 18:45 ` [PATCH v2 39/41] target/sparc: Make sparc_cpu_tlb_fill " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 40/41] target/xtensa: Make xtensa_cpu_tlb_fill " Richard Henderson
2021-09-18 18:45 ` [PATCH v2 41/41] accel/tcg: Restrict TCGCPUOps::tlb_fill() to sysemu Richard Henderson
2021-09-19 18:40   ` Philippe Mathieu-Daudé
2021-09-19 10:38 ` [PATCH v2 00/41] linux-user: Streamline handling of SIGSEGV Philippe Mathieu-Daudé

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210918184527.408540-4-richard.henderson@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=f4bug@amsat.org \
    --cc=laurent@vivier.eu \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.