aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-08-02 13:03:22 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-02 13:03:22 +0100
commit488ddf337984fdfe97a62f6d136f3334b62f9018 (patch)
treeefdfead5c03d4e2678a01e24bf1c47695d95678a
parent46cd42551ff33c23e021e47d40655ece3215f875 (diff)
downloadqemu-arm-488ddf337984fdfe97a62f6d136f3334b62f9018.tar.gz
accel/tcg: tb_gen_code(): Create single-insn TB for execution from non-RAM
If get_page_addr_code() returns -1, this indicates that there is no RAM page we can read a full TB from. Instead we must create a TB which contains a single instruction and which we do not cache, so it is executed only once. Since this means we can now have TBs which are not in any page list, we also need to make tb_phys_invalidate() handle them (by not trying to remove them from a nonexistent page list). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Emilio G. Cota <cota@braap.org> Tested-by: C├ędric Le Goater <clg@kaod.org> Message-id: 20180710160013.26559-5-peter.maydell@linaro.org
-rw-r--r--accel/tcg/translate-all.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index ff7d0145f4..898c3bb3d1 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1493,7 +1493,7 @@ static void tb_phys_invalidate__locked(TranslationBlock *tb)
*/
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
{
- if (page_addr == -1) {
+ if (page_addr == -1 && tb->page_addr[0] != -1) {
page_lock_tb(tb);
do_tb_phys_invalidate(tb, true);
page_unlock_tb(tb);
@@ -1608,6 +1608,17 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
assert_memory_lock();
+ if (phys_pc == -1) {
+ /*
+ * If the TB is not associated with a physical RAM page then
+ * it must be a temporary one-insn TB, and we have nothing to do
+ * except fill in the page_addr[] fields.
+ */
+ assert(tb->cflags & CF_NOCACHE);
+ tb->page_addr[0] = tb->page_addr[1] = -1;
+ return tb;
+ }
+
/*
* Add the TB to the page list, acquiring first the pages's locks.
* We keep the locks held until after inserting the TB in the hash table,
@@ -1677,6 +1688,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
phys_pc = get_page_addr_code(env, pc);
+ if (phys_pc == -1) {
+ /* Generate a temporary TB with 1 insn in it */
+ cflags &= ~CF_COUNT_MASK;
+ cflags |= CF_NOCACHE | 1;
+ }
+
buffer_overflow:
tb = tb_alloc(pc);
if (unlikely(!tb)) {