exec: make iotlb RCU-friendly

After the previous patch, TLBs will be flushed on every change to
the memory mapping. This patch augments that with synchronization
of the MemoryRegionSections referred to in the iotlb array.

With this change, it is guaranteed that iotlb_to_region will access
the correct memory map, even once the TLB will be accessed outside
the BQL.

Backports commit 9d82b5a792236db31a75b9db5c93af69ac07c7c5 from qemu
This commit is contained in:
Paolo Bonzini 2018-02-12 15:20:15 -05:00 committed by Lioncash
parent 2348a02a8d
commit a46accd252
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
7 changed files with 21 additions and 12 deletions

View file

@ -21,6 +21,8 @@
#include "tcg.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
#include "exec/memory-internal.h"
#include "uc_priv.h"
@ -289,6 +291,9 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
void cpu_reload_memory_map(CPUState *cpu)
{
/* The TLB is protected by the iothread lock. */
/* The CPU and TLB are protected by the iothread lock. */
AddressSpaceDispatch *d = cpu->as->dispatch;
cpu->memory_dispatch = d;
tlb_flush(cpu, 1);
}

View file

@ -218,8 +218,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
}
sz = size;
section = address_space_translate_for_iotlb(cpu->as, paddr,
&xlat, &sz);
section = address_space_translate_for_iotlb(cpu, paddr, &xlat, &sz);
assert(sz >= TARGET_PAGE_SIZE);
#if defined(DEBUG_TLB)
@ -304,7 +303,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
}
}
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(cpu->as, pd);
mr = iotlb_to_region(cpu, pd);
if (memory_region_is_unassigned(cpu->uc, mr)) {
CPUClass *cc = CPU_GET_CLASS(env1->uc, cpu);

View file

@ -371,11 +371,12 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
}
MemoryRegionSection *
address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
hwaddr *plen)
address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr,
hwaddr *xlat, hwaddr *plen)
{
MemoryRegionSection *section;
section = address_space_translate_internal(as->dispatch, addr, xlat, plen, false);
section = address_space_translate_internal(cpu->memory_dispatch,
addr, xlat, plen, false);
assert(!section->mr->iommu_ops);
return section;
@ -1428,9 +1429,11 @@ static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as,
return phys_section_add(map, &section);
}
MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index)
MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index)
{
return as->dispatch->map.sections[index & ~TARGET_PAGE_MASK].mr;
MemoryRegionSection *sections = cpu->memory_dispatch->map.sections;
return sections[index & ~TARGET_PAGE_MASK].mr;
}
void phys_mem_clean(struct uc_struct* uc)

View file

@ -34,7 +34,7 @@ void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr);
MemoryRegionSection *
address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr, hwaddr *xlat,
hwaddr *plen);
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
MemoryRegionSection *section,

View file

@ -334,7 +334,8 @@ extern uintptr_t tci_tb_ptr;
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
struct MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index);
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
hwaddr index);
bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
uint64_t *pvalue, unsigned size);
bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,

View file

@ -230,6 +230,7 @@ struct CPUState {
sigjmp_buf jmp_env;
AddressSpace *as;
struct AddressSpaceDispatch *memory_dispatch;
MemoryListener *tcg_as_listener;
void *env_ptr; /* CPUArchState */

View file

@ -163,7 +163,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
{
uint64_t val;
CPUState *cpu = ENV_GET_CPU(env);
MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
cpu->mem_io_pc = retaddr;
@ -663,7 +663,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
uintptr_t retaddr)
{
CPUState *cpu = ENV_GET_CPU(env);
MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
if (mr != &(cpu->uc->io_mem_rom) && mr != &(cpu->uc->io_mem_notdirty)