diff options
author | Alex Bennée <alex.bennee@linaro.org> | 2020-07-13 21:04:10 +0100 |
---|---|---|
committer | Alex Bennée <alex.bennee@linaro.org> | 2020-07-15 11:52:43 +0100 |
commit | 2f3a57ee47df970d19fa5b324d44aab857d43517 (patch) | |
tree | b39673bfb5f3c67c13a513e07ffe33e089724b73 /accel/tcg | |
parent | 777dddc501fa31bc9afff6de5e55dbf799e1703b (diff) | |
download | qemu-2f3a57ee47df970d19fa5b324d44aab857d43517.zip qemu-2f3a57ee47df970d19fa5b324d44aab857d43517.tar.gz qemu-2f3a57ee47df970d19fa5b324d44aab857d43517.tar.bz2 |
cputlb: ensure we save the IOTLB data in case of reset
Any write to a device might cause a re-arrangement of memory
triggering a TLB flush and potential re-size of the TLB invalidating
previous entries. This would cause users of qemu_plugin_get_hwaddr()
to see the warning:
invalid use of qemu_plugin_get_hwaddr
because of the failed tlb_lookup which should always succeed. To
prevent this we save the IOTLB data in case it is later needed by a
plugin doing a lookup.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20200713200415.26214-7-alex.bennee@linaro.org>
Diffstat (limited to 'accel/tcg')
-rw-r--r-- | accel/tcg/cputlb.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 1e81535..d370aed 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1073,6 +1073,24 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, return val; } +/* + * Save a potentially trashed IOTLB entry for later lookup by plugin. + * + * We also need to track the thread storage address because the RCU + * cleanup that runs when we leave the critical region (the current + * execution) is actually in a different thread. + */ +static void save_iotlb_data(CPUState *cs, hwaddr addr, + MemoryRegionSection *section, hwaddr mr_offset) +{ +#ifdef CONFIG_PLUGIN + SavedIOTLB *saved = &cs->saved_iotlb; + saved->addr = addr; + saved->section = section; + saved->mr_offset = mr_offset; +#endif +} + static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, int mmu_idx, uint64_t val, target_ulong addr, uintptr_t retaddr, MemOp op) @@ -1092,6 +1110,12 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, } cpu->mem_io_pc = retaddr; + /* + * The memory_region_dispatch may trigger a flush/resize + * so for plugins we save the iotlb_data just in case. + */ + save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset); + if (mr->global_locking && !qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); locked = true; @@ -1381,8 +1405,11 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, * in the softmmu lookup code (or helper). We don't handle re-fills or * checking the victim table. This is purely informational. * - * This should never fail as the memory access being instrumented - * should have just filled the TLB. + * This almost never fails as the memory access being instrumented + * should have just filled the TLB. The one corner case is io_writex + * which can cause TLB flushes and potential resizing of the TLBs + * loosing the information we need. In those cases we need to recover + * data from a copy of the io_tlb entry. */ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, @@ -1406,8 +1433,13 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, data->v.ram.hostaddr = addr + tlbe->addend; } return true; + } else { + SavedIOTLB *saved = &cpu->saved_iotlb; + data->is_io = true; + data->v.io.section = saved->section; + data->v.io.offset = saved->mr_offset; + return true; } - return false; } #endif |