summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2012-12-13 04:13:41 +0400
committerDoug Goldstein <cardoe@cardoe.com>2013-02-10 13:56:11 -0600
commit3a3364d02457dde0aeb243b45ae6c92efa9bebff (patch)
treeeafdcf6397b794570196bed1ab8be806b416cdfa /target-xtensa
parentqxl: call dpy_gfx_resize when entering vga mode (diff)
downloadqemu-kvm-3a3364d02457dde0aeb243b45ae6c92efa9bebff.tar.gz
qemu-kvm-3a3364d02457dde0aeb243b45ae6c92efa9bebff.tar.bz2
qemu-kvm-3a3364d02457dde0aeb243b45ae6c92efa9bebff.zip
target-xtensa: fix ITLB/DTLB page protection flags
With MMU option xtensa architecture has two TLBs: ITLB and DTLB. ITLB is only used for code access, DTLB is only for data. However TLB entries in both TLBs have attribute field controlling write and exec access. These bits need to be properly masked off depending on TLB type before being used as tlb_set_page prot argument. Otherwise the following happens: (1) ITLB entry for some PFN gets invalidated (2) DTLB entry for the same PFN gets updated, attributes allow code execution (3) code at the page with that PFN is executed (possible due to step 2), entry for the TB is written into the jump cache (4) QEMU TLB entry for the PFN gets replaced with an entry for some other PFN (5) code in the TB from step 3 is executed (possible due to jump cache) and it accesses data, for which there's no DTLB entry, causing DTLB miss exception (6) re-translation of the TB from step 5 is attempted, but there's no QEMU TLB entry nor xtensa ITLB entry for that PFN, which causes ITLB miss exception at the TB start address (7) ITLB miss exception is handled by the guest, but execution is resumed from the beginning of the faulting TB (the point where ITLB miss occured), not from the point where DTLB miss occured, which is wrong. With that fix the above scenario causes ITLB miss exception (that used to be step 7) at step 3, right at the beginning of the TB. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Cc: qemu-stable@nongnu.org Signed-off-by: Blue Swirl <blauwirbel@gmail.com> (cherry picked from commit 659f807c0a700317a7a0fae7a6e6ebfe68bfbbc4)
Diffstat (limited to 'target-xtensa')
-rw-r--r--target-xtensa/helper.c3
-rw-r--r--target-xtensa/translate.c6
2 files changed, 5 insertions, 4 deletions
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index d5bb171fc..b43395c3f 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -486,7 +486,8 @@ static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb,
INST_FETCH_PRIVILEGE_CAUSE;
}
- *access = mmu_attr_to_access(entry->attr);
+ *access = mmu_attr_to_access(entry->attr) &
+ ~(dtlb ? PAGE_EXEC : PAGE_READ | PAGE_WRITE);
if (!is_access_granted(*access, is_write)) {
return dtlb ?
(is_write ?
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index b418e30c6..a57c574a8 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2679,9 +2679,9 @@ static void gen_intermediate_code_internal(
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
- memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0,
- (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0]));
+ j = gen_opc_ptr - gen_opc_buf;
+ memset(gen_opc_instr_start + lj + 1, 0,
+ (j - lj) * sizeof(gen_opc_instr_start[0]));
} else {
tb->size = dc.pc - pc_start;
tb->icount = insn_count;