From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: lvivier@redhat.com, peter.maydell@linaro.org,
alex.bennee@linaro.org, pbonzini@redhat.com
Subject: [Qemu-devel] [PATCH 5/5] tcg: Release mmap_lock on translation fault
Date: Tue, 9 Jul 2019 11:20:49 +0200 [thread overview]
Message-ID: <20190709092049.13771-6-richard.henderson@linaro.org> (raw)
In-Reply-To: <20190709092049.13771-1-richard.henderson@linaro.org>
Turn helper_retaddr into a multi-state flag that may now also
indicate when we're performing a read on behalf of the translator.
In this case, release the mmap_lock before the longjmp back to
the main cpu loop, and thereby avoid a failing assert therein.
Fixes: https://bugs.launchpad.net/qemu/+bug/1832353
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/cpu_ldst_useronly_template.h | 20 +++++--
accel/tcg/user-exec.c | 65 ++++++++++++++++-------
2 files changed, 62 insertions(+), 23 deletions(-)
diff --git a/include/exec/cpu_ldst_useronly_template.h b/include/exec/cpu_ldst_useronly_template.h
index d663826ac2..35caae8ca6 100644
--- a/include/exec/cpu_ldst_useronly_template.h
+++ b/include/exec/cpu_ldst_useronly_template.h
@@ -64,12 +64,18 @@
static inline RES_TYPE
glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr)
{
-#if !defined(CODE_ACCESS)
+#ifdef CODE_ACCESS
+ RES_TYPE ret;
+ set_helper_retaddr(1);
+ ret = glue(glue(ld, USUFFIX), _p)(g2h(ptr));
+ clear_helper_retaddr();
+ return ret;
+#else
trace_guest_mem_before_exec(
env_cpu(env), ptr,
trace_mem_build_info(SHIFT, false, MO_TE, false));
-#endif
return glue(glue(ld, USUFFIX), _p)(g2h(ptr));
+#endif
}
#ifndef CODE_ACCESS
@@ -90,12 +96,18 @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
static inline int
glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, abi_ptr ptr)
{
-#if !defined(CODE_ACCESS)
+#ifdef CODE_ACCESS
+ int ret;
+ set_helper_retaddr(1);
+ ret = glue(glue(ld, USUFFIX), _p)(g2h(ptr));
+ clear_helper_retaddr();
+ return ret;
+#else
trace_guest_mem_before_exec(
env_cpu(env), ptr,
trace_mem_build_info(SHIFT, true, MO_TE, false));
-#endif
return glue(glue(lds, SUFFIX), _p)(g2h(ptr));
+#endif
}
#ifndef CODE_ACCESS
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 4384b59a4d..5adea629de 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -64,27 +64,55 @@ 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;
- MMUAccessType access_type;
+ MMUAccessType access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
- /* We must handle PC addresses from two different sources:
- * a call return address and a signal frame address.
- *
- * Within cpu_restore_state_from_tb we assume the former and adjust
- * the address by -GETPC_ADJ so that the address is within the call
- * insn so that addr does not accidentally match the beginning of the
- * next guest insn.
- *
- * However, when the PC comes from the signal frame, it points to
- * the actual faulting host insn and not a call insn. Subtracting
- * GETPC_ADJ in that case may accidentally match the previous guest insn.
- *
- * So for the later case, adjust forward to compensate for what
- * will be done later by cpu_restore_state_from_tb.
- */
- if (helper_retaddr) {
+ switch (helper_retaddr) {
+ default:
+ /*
+ * Fault during host memory operation within a helper function.
+ * The helper's host return address, saved here, gives us a
+ * pointer into the generated code that will unwind to the
+ * correct guest pc.
+ */
pc = helper_retaddr;
- } else {
+ break;
+
+ case 0:
+ /*
+ * Fault during host memory operation within generated code.
+ * (Or, a unrelated bug within qemu, but we can't tell from here).
+ *
+ * We take the host pc from the signal frame. However, we cannot
+ * use that value directly. Within cpu_restore_state_from_tb, we
+ * assume PC comes from GETPC(), as used by the helper functions,
+ * so we adjust the address by -GETPC_ADJ to form an address that
+ * is within the call insn, so that the address does not accidentially
+ * match the beginning of the next guest insn. However, when the
+ * pc comes fromt he signal frame it points to the actual faulting
+ * host memory insn and not a call insn.
+ *
+ * Therefore, adjust to compensate for what will be done later
+ * by cpu_restore_state_from_tb.
+ */
pc += GETPC_ADJ;
+ break;
+
+ case 1:
+ /*
+ * Fault during host read for translation, or loosely, "execution".
+ *
+ * The guest pc is already pointing to the start of the TB for which
+ * code is being generated. If the guest translator manages the
+ * page crossings correctly, this is exactly the correct address
+ * (and if it doesn't there's little we can do about that here).
+ * Therefore, do not trigger the unwinder.
+ *
+ * Like tb_gen_code, release the memory lock before cpu_loop_exit.
+ */
+ pc = 0;
+ access_type = MMU_INST_FETCH;
+ mmap_unlock();
+ break;
}
/* For synchronous signals we expect to be coming from the vCPU
@@ -155,7 +183,6 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
clear_helper_retaddr();
cc = CPU_GET_CLASS(cpu);
- access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
g_assert_not_reached();
}
--
2.17.1
next prev parent reply other threads:[~2019-07-09 9:27 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-09 9:20 [Qemu-devel] [PATCH 0/5] tcg: Fix mmap_lock assertion failure, take 2 Richard Henderson
2019-07-09 9:20 ` [Qemu-devel] [PATCH 1/5] include/qemu/atomic.h: Add signal_barrier Richard Henderson
2019-07-09 10:03 ` Alex Bennée
2019-07-09 9:20 ` [Qemu-devel] [PATCH 2/5] tcg: Introduce set/clear_helper_retaddr Richard Henderson
2019-07-09 10:07 ` Alex Bennée
2019-07-09 10:16 ` Richard Henderson
2019-07-09 10:43 ` Alex Bennée
2019-07-09 9:20 ` [Qemu-devel] [PATCH 3/5] tcg: Remove cpu_ld*_code_ra Richard Henderson
2019-07-09 10:09 ` Alex Bennée
2019-07-09 9:20 ` [Qemu-devel] [PATCH 4/5] tcg: Remove duplicate #if !defined(CODE_ACCESS) Richard Henderson
2019-07-09 10:11 ` Alex Bennée
2019-07-09 9:20 ` Richard Henderson [this message]
2019-07-09 10:37 ` [Qemu-devel] [PATCH 5/5] tcg: Release mmap_lock on translation fault Alex Bennée
2019-07-09 11:04 ` [Qemu-devel] [PATCH 0/5] tcg: Fix mmap_lock assertion failure, take 2 no-reply
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=20190709092049.13771-6-richard.henderson@linaro.org \
--to=richard.henderson@linaro.org \
--cc=alex.bennee@linaro.org \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).