Skip to content

Commit 2f3a57e

Browse files
committed
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 <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-Id: <[email protected]>
1 parent 777dddc commit 2f3a57e

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

accel/tcg/cputlb.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,24 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
10731073
return val;
10741074
}
10751075

1076+
/*
1077+
* Save a potentially trashed IOTLB entry for later lookup by plugin.
1078+
*
1079+
* We also need to track the thread storage address because the RCU
1080+
* cleanup that runs when we leave the critical region (the current
1081+
* execution) is actually in a different thread.
1082+
*/
1083+
static void save_iotlb_data(CPUState *cs, hwaddr addr,
1084+
MemoryRegionSection *section, hwaddr mr_offset)
1085+
{
1086+
#ifdef CONFIG_PLUGIN
1087+
SavedIOTLB *saved = &cs->saved_iotlb;
1088+
saved->addr = addr;
1089+
saved->section = section;
1090+
saved->mr_offset = mr_offset;
1091+
#endif
1092+
}
1093+
10761094
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
10771095
int mmu_idx, uint64_t val, target_ulong addr,
10781096
uintptr_t retaddr, MemOp op)
@@ -1092,6 +1110,12 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
10921110
}
10931111
cpu->mem_io_pc = retaddr;
10941112

1113+
/*
1114+
* The memory_region_dispatch may trigger a flush/resize
1115+
* so for plugins we save the iotlb_data just in case.
1116+
*/
1117+
save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset);
1118+
10951119
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
10961120
qemu_mutex_lock_iothread();
10971121
locked = true;
@@ -1381,8 +1405,11 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
13811405
* in the softmmu lookup code (or helper). We don't handle re-fills or
13821406
* checking the victim table. This is purely informational.
13831407
*
1384-
* This should never fail as the memory access being instrumented
1385-
* should have just filled the TLB.
1408+
* This almost never fails as the memory access being instrumented
1409+
* should have just filled the TLB. The one corner case is io_writex
1410+
* which can cause TLB flushes and potential resizing of the TLBs
1411+
* loosing the information we need. In those cases we need to recover
1412+
* data from a copy of the io_tlb entry.
13861413
*/
13871414

13881415
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,
14061433
data->v.ram.hostaddr = addr + tlbe->addend;
14071434
}
14081435
return true;
1436+
} else {
1437+
SavedIOTLB *saved = &cpu->saved_iotlb;
1438+
data->is_io = true;
1439+
data->v.io.section = saved->section;
1440+
data->v.io.offset = saved->mr_offset;
1441+
return true;
14091442
}
1410-
return false;
14111443
}
14121444

14131445
#endif

include/hw/core/cpu.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ struct CPUWatchpoint {
259259
QTAILQ_ENTRY(CPUWatchpoint) entry;
260260
};
261261

262+
#ifdef CONFIG_PLUGIN
263+
/*
264+
* For plugins we sometime need to save the resolved iotlb data before
265+
* the memory regions get moved around by io_writex.
266+
*/
267+
typedef struct SavedIOTLB {
268+
hwaddr addr;
269+
MemoryRegionSection *section;
270+
hwaddr mr_offset;
271+
} SavedIOTLB;
272+
#endif
273+
262274
struct KVMState;
263275
struct kvm_run;
264276

@@ -417,7 +429,11 @@ struct CPUState {
417429

418430
DECLARE_BITMAP(plugin_mask, QEMU_PLUGIN_EV_MAX);
419431

432+
#ifdef CONFIG_PLUGIN
420433
GArray *plugin_mem_cbs;
434+
/* saved iotlb data from io_writex */
435+
SavedIOTLB saved_iotlb;
436+
#endif
421437

422438
/* TODO Move common fields from CPUArchState here. */
423439
int cpu_index;

include/qemu/typedefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ typedef struct QObject QObject;
116116
typedef struct QString QString;
117117
typedef struct RAMBlock RAMBlock;
118118
typedef struct Range Range;
119+
typedef struct SavedIOTLB SavedIOTLB;
119120
typedef struct SHPCDevice SHPCDevice;
120121
typedef struct SSIBus SSIBus;
121122
typedef struct VirtIODevice VirtIODevice;

0 commit comments

Comments
 (0)