Merge remote-tracking branch 'qemu-kvm/memory/dma' into staging

* qemu-kvm/memory/dma: (23 commits)
  pci: honor PCI_COMMAND_MASTER
  pci: give each device its own address space
  memory: add address_space_destroy()
  dma: make dma access its own address space
  memory: per-AddressSpace dispatch
  s390: avoid reaching into memory core internals
  memory: use AddressSpace for MemoryListener filtering
  memory: move tcg flush into a tcg memory listener
  memory: move address_space_memory and address_space_io out of memory core
  memory: manage coalesced mmio via a MemoryListener
  xen: drop no-op MemoryListener callbacks
  kvm: drop no-op MemoryListener callbacks
  xen_pt: drop no-op MemoryListener callbacks
  vfio: drop no-op MemoryListener callbacks
  memory: drop no-op MemoryListener callbacks
  memory: provide defaults for MemoryListener operations
  memory: maintain a list of address spaces
  memory: export AddressSpace
  memory: prepare AddressSpace for exporting
  xen_pt: use separate MemoryListeners for memory and I/O
  ...
This commit is contained in:
Anthony Liguori 2012-10-22 13:26:07 -05:00
commit d3e2efc5b5
21 changed files with 485 additions and 472 deletions

View File

@ -21,11 +21,11 @@
#include "cpu.h"
#include "exec-all.h"
#include "memory.h"
#include "exec-memory.h"
#include "cputlb.h"
#define WANT_EXEC_OBSOLETE
#include "exec-obsolete.h"
#include "memory-internal.h"
//#define DEBUG_TLB
//#define DEBUG_TLB_CHECK
@ -252,7 +252,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
if (size != TARGET_PAGE_SIZE) {
tlb_add_large_page(env, vaddr, size);
}
section = phys_page_find(paddr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
#if defined(DEBUG_TLB)
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
" prot=%x idx=%d pd=0x%08lx\n",

View File

@ -26,7 +26,8 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
target_ulong vaddr);
void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
uintptr_t length);
MemoryRegionSection *phys_page_find(target_phys_addr_t index);
MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d,
target_phys_addr_t index);
void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length);
void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
extern int tlb_flush_count;

View File

@ -14,7 +14,8 @@
/* #define DEBUG_IOMMU */
static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len)
static void do_dma_memory_set(AddressSpace *as,
dma_addr_t addr, uint8_t c, dma_addr_t len)
{
#define FILLBUF_SIZE 512
uint8_t fillbuf[FILLBUF_SIZE];
@ -23,7 +24,7 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len)
memset(fillbuf, c, FILLBUF_SIZE);
while (len > 0) {
l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
cpu_physical_memory_rw(addr, fillbuf, l, true);
address_space_rw(as, addr, fillbuf, l, true);
len -= l;
addr += l;
}
@ -36,7 +37,7 @@ int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
if (dma_has_iommu(dma)) {
return iommu_dma_memory_set(dma, addr, c, len);
}
do_dma_memory_set(addr, c, len);
do_dma_memory_set(dma->as, addr, c, len);
return 0;
}
@ -332,8 +333,7 @@ int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
plen = len;
}
cpu_physical_memory_rw(paddr, buf, plen,
dir == DMA_DIRECTION_FROM_DEVICE);
address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE);
len -= plen;
addr += plen;
@ -366,7 +366,7 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
plen = len;
}
do_dma_memory_set(paddr, c, plen);
do_dma_memory_set(dma->as, paddr, c, plen);
len -= plen;
addr += plen;
@ -375,13 +375,14 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
return 0;
}
void dma_context_init(DMAContext *dma, DMATranslateFunc translate,
void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
DMAMapFunc map, DMAUnmapFunc unmap)
{
#ifdef DEBUG_IOMMU
fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n",
dma, translate, map, unmap);
#endif
dma->as = as;
dma->translate = translate;
dma->map = map;
dma->unmap = unmap;
@ -407,14 +408,13 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
/*
* If this is true, the virtual region is contiguous,
* but the translated physical region isn't. We just
* clamp *len, much like cpu_physical_memory_map() does.
* clamp *len, much like address_space_map() does.
*/
if (plen < *len) {
*len = plen;
}
buf = cpu_physical_memory_map(paddr, &plen,
dir == DMA_DIRECTION_FROM_DEVICE);
buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
*len = plen;
return buf;
@ -428,8 +428,7 @@ void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len,
return;
}
cpu_physical_memory_unmap(buffer, len,
dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
}

17
dma.h
View File

@ -11,6 +11,7 @@
#define DMA_H
#include <stdio.h>
#include "memory.h"
#include "hw/hw.h"
#include "block.h"
#include "kvm.h"
@ -61,6 +62,7 @@ typedef void DMAUnmapFunc(DMAContext *dma,
dma_addr_t access_len);
struct DMAContext {
AddressSpace *as;
DMATranslateFunc *translate;
DMAMapFunc *map;
DMAUnmapFunc *unmap;
@ -93,7 +95,7 @@ static inline void dma_barrier(DMAContext *dma, DMADirection dir)
static inline bool dma_has_iommu(DMAContext *dma)
{
return !!dma;
return dma && dma->translate;
}
/* Checks that the given range of addresses is valid for DMA. This is
@ -120,8 +122,7 @@ static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
{
if (!dma_has_iommu(dma)) {
/* Fast-path for no IOMMU */
cpu_physical_memory_rw(addr, buf, len,
dir == DMA_DIRECTION_FROM_DEVICE);
address_space_rw(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
return 0;
} else {
return iommu_dma_memory_rw(dma, addr, buf, len, dir);
@ -179,8 +180,7 @@ static inline void *dma_memory_map(DMAContext *dma,
target_phys_addr_t xlen = *len;
void *p;
p = cpu_physical_memory_map(addr, &xlen,
dir == DMA_DIRECTION_FROM_DEVICE);
p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
*len = xlen;
return p;
} else {
@ -196,9 +196,8 @@ static inline void dma_memory_unmap(DMAContext *dma,
DMADirection dir, dma_addr_t access_len)
{
if (!dma_has_iommu(dma)) {
cpu_physical_memory_unmap(buffer, (target_phys_addr_t)len,
dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
address_space_unmap(dma->as, buffer, (target_phys_addr_t)len,
dir == DMA_DIRECTION_FROM_DEVICE, access_len);
} else {
iommu_dma_memory_unmap(dma, buffer, len, dir, access_len);
}
@ -242,7 +241,7 @@ DEFINE_LDST_DMA(q, q, 64, be);
#undef DEFINE_LDST_DMA
void dma_context_init(DMAContext *dma, DMATranslateFunc translate,
void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
DMAMapFunc map, DMAUnmapFunc unmap);
struct ScatterGatherEntry {

View File

@ -33,11 +33,8 @@ MemoryRegion *get_system_memory(void);
*/
MemoryRegion *get_system_io(void);
/* Set the root memory region. This region is the system memory map. */
void set_system_memory_map(MemoryRegion *mr);
/* Set the I/O memory region. This region is the I/O memory map. */
void set_system_io_map(MemoryRegion *mr);
extern AddressSpace address_space_memory;
extern AddressSpace address_space_io;
#endif

317
exec.c
View File

@ -59,8 +59,7 @@
#include "cputlb.h"
#define WANT_EXEC_OBSOLETE
#include "exec-obsolete.h"
#include "memory-internal.h"
//#define DEBUG_TB_INVALIDATE
//#define DEBUG_FLUSH
@ -102,6 +101,9 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
static MemoryRegion *system_memory;
static MemoryRegion *system_io;
AddressSpace address_space_io;
AddressSpace address_space_memory;
MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
static MemoryRegion io_mem_subpage_ram;
@ -170,7 +172,6 @@ uintptr_t qemu_host_page_mask;
static void *l1_map[V_L1_SIZE];
#if !defined(CONFIG_USER_ONLY)
typedef struct PhysPageEntry PhysPageEntry;
static MemoryRegionSection *phys_sections;
static unsigned phys_sections_nb, phys_sections_nb_alloc;
@ -179,22 +180,12 @@ static uint16_t phys_section_notdirty;
static uint16_t phys_section_rom;
static uint16_t phys_section_watch;
struct PhysPageEntry {
uint16_t is_leaf : 1;
/* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */
uint16_t ptr : 15;
};
/* Simple allocator for PhysPageEntry nodes */
static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
#define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1)
/* This is a multi-level map on the physical address space.
The bottom level has pointers to MemoryRegionSections. */
static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
static void io_mem_init(void);
static void memory_map_init(void);
@ -442,18 +433,19 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index,
}
}
static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb,
static void phys_page_set(AddressSpaceDispatch *d,
target_phys_addr_t index, target_phys_addr_t nb,
uint16_t leaf)
{
/* Wildly overreserve - it doesn't matter much. */
phys_map_node_reserve(3 * P_L2_LEVELS);
phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
}
MemoryRegionSection *phys_page_find(target_phys_addr_t index)
MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, target_phys_addr_t index)
{
PhysPageEntry lp = phys_map;
PhysPageEntry lp = d->phys_map;
PhysPageEntry *p;
int i;
uint16_t s_index = phys_section_unassigned;
@ -1486,7 +1478,7 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr)
ram_addr_t ram_addr;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr)
|| (section->mr->rom_device && section->mr->readable))) {
return;
@ -2224,9 +2216,9 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
lp->ptr = PHYS_MAP_NODE_NIL;
}
static void destroy_all_mappings(void)
static void destroy_all_mappings(AddressSpaceDispatch *d)
{
destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1);
destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
phys_map_nodes_reset();
}
@ -2246,12 +2238,12 @@ static void phys_sections_clear(void)
phys_sections_nb = 0;
}
static void register_subpage(MemoryRegionSection *section)
static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
{
subpage_t *subpage;
target_phys_addr_t base = section->offset_within_address_space
& TARGET_PAGE_MASK;
MemoryRegionSection *existing = phys_page_find(base >> TARGET_PAGE_BITS);
MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS);
MemoryRegionSection subsection = {
.offset_within_address_space = base,
.size = TARGET_PAGE_SIZE,
@ -2263,7 +2255,7 @@ static void register_subpage(MemoryRegionSection *section)
if (!(existing->mr->subpage)) {
subpage = subpage_init(base);
subsection.mr = &subpage->iomem;
phys_page_set(base >> TARGET_PAGE_BITS, 1,
phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
phys_section_add(&subsection));
} else {
subpage = container_of(existing->mr, subpage_t, iomem);
@ -2274,7 +2266,7 @@ static void register_subpage(MemoryRegionSection *section)
}
static void register_multipage(MemoryRegionSection *section)
static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section)
{
target_phys_addr_t start_addr = section->offset_within_address_space;
ram_addr_t size = section->size;
@ -2284,13 +2276,13 @@ static void register_multipage(MemoryRegionSection *section)
assert(size);
addr = start_addr;
phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS,
phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS,
section_index);
}
void cpu_register_physical_memory_log(MemoryRegionSection *section,
bool readonly)
static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
{
AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
MemoryRegionSection now = *section, remain = *section;
if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
@ -2298,7 +2290,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space)
- now.offset_within_address_space,
now.size);
register_subpage(&now);
register_subpage(d, &now);
remain.size -= now.size;
remain.offset_within_address_space += now.size;
remain.offset_within_region += now.size;
@ -2307,10 +2299,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
now = remain;
if (remain.offset_within_region & ~TARGET_PAGE_MASK) {
now.size = TARGET_PAGE_SIZE;
register_subpage(&now);
register_subpage(d, &now);
} else {
now.size &= TARGET_PAGE_MASK;
register_multipage(&now);
register_multipage(d, &now);
}
remain.size -= now.size;
remain.offset_within_address_space += now.size;
@ -2318,23 +2310,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section,
}
now = remain;
if (now.size) {
register_subpage(&now);
register_subpage(d, &now);
}
}
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
{
if (kvm_enabled())
kvm_coalesce_mmio_region(addr, size);
}
void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
{
if (kvm_enabled())
kvm_uncoalesce_mmio_region(addr, size);
}
void qemu_flush_coalesced_mmio_buffer(void)
{
if (kvm_enabled())
@ -3182,18 +3161,24 @@ static void io_mem_init(void)
"watch", UINT64_MAX);
}
static void mem_begin(MemoryListener *listener)
{
AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
destroy_all_mappings(d);
d->phys_map.ptr = PHYS_MAP_NODE_NIL;
}
static void core_begin(MemoryListener *listener)
{
destroy_all_mappings();
phys_sections_clear();
phys_map.ptr = PHYS_MAP_NODE_NIL;
phys_section_unassigned = dummy_section(&io_mem_unassigned);
phys_section_notdirty = dummy_section(&io_mem_notdirty);
phys_section_rom = dummy_section(&io_mem_rom);
phys_section_watch = dummy_section(&io_mem_watch);
}
static void core_commit(MemoryListener *listener)
static void tcg_commit(MemoryListener *listener)
{
CPUArchState *env;
@ -3205,38 +3190,6 @@ static void core_commit(MemoryListener *listener)
}
}
static void core_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
cpu_register_physical_memory_log(section, section->readonly);
}
static void core_region_del(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void core_region_nop(MemoryListener *listener,
MemoryRegionSection *section)
{
cpu_register_physical_memory_log(section, section->readonly);
}
static void core_log_start(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void core_log_stop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void core_log_sync(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void core_log_global_start(MemoryListener *listener)
{
cpu_physical_memory_set_dirty_tracking(1);
@ -3247,26 +3200,6 @@ static void core_log_global_stop(MemoryListener *listener)
cpu_physical_memory_set_dirty_tracking(0);
}
static void core_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}
static void core_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}
static void io_begin(MemoryListener *listener)
{
}
static void io_commit(MemoryListener *listener)
{
}
static void io_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@ -3285,90 +3218,63 @@ static void io_region_del(MemoryListener *listener,
isa_unassign_ioport(section->offset_within_address_space, section->size);
}
static void io_region_nop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void io_log_start(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void io_log_stop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void io_log_sync(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void io_log_global_start(MemoryListener *listener)
{
}
static void io_log_global_stop(MemoryListener *listener)
{
}
static void io_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}
static void io_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}
static MemoryListener core_memory_listener = {
.begin = core_begin,
.commit = core_commit,
.region_add = core_region_add,
.region_del = core_region_del,
.region_nop = core_region_nop,
.log_start = core_log_start,
.log_stop = core_log_stop,
.log_sync = core_log_sync,
.log_global_start = core_log_global_start,
.log_global_stop = core_log_global_stop,
.eventfd_add = core_eventfd_add,
.eventfd_del = core_eventfd_del,
.priority = 0,
.priority = 1,
};
static MemoryListener io_memory_listener = {
.begin = io_begin,
.commit = io_commit,
.region_add = io_region_add,
.region_del = io_region_del,
.region_nop = io_region_nop,
.log_start = io_log_start,
.log_stop = io_log_stop,
.log_sync = io_log_sync,
.log_global_start = io_log_global_start,
.log_global_stop = io_log_global_stop,
.eventfd_add = io_eventfd_add,
.eventfd_del = io_eventfd_del,
.priority = 0,
};
static MemoryListener tcg_memory_listener = {
.commit = tcg_commit,
};
void address_space_init_dispatch(AddressSpace *as)
{
AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1);
d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
d->listener = (MemoryListener) {
.begin = mem_begin,
.region_add = mem_add,
.region_nop = mem_add,
.priority = 0,
};
as->dispatch = d;
memory_listener_register(&d->listener, as);
}
void address_space_destroy_dispatch(AddressSpace *as)
{
AddressSpaceDispatch *d = as->dispatch;
memory_listener_unregister(&d->listener);
destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
g_free(d);
as->dispatch = NULL;
}
static void memory_map_init(void)
{
system_memory = g_malloc(sizeof(*system_memory));
memory_region_init(system_memory, "system", INT64_MAX);
set_system_memory_map(system_memory);
address_space_init(&address_space_memory, system_memory);
address_space_memory.name = "memory";
system_io = g_malloc(sizeof(*system_io));
memory_region_init(system_io, "io", 65536);
set_system_io_map(system_io);
address_space_init(&address_space_io, system_io);
address_space_io.name = "I/O";
memory_listener_register(&core_memory_listener, system_memory);
memory_listener_register(&io_memory_listener, system_io);
memory_listener_register(&core_memory_listener, &address_space_memory);
memory_listener_register(&io_memory_listener, &address_space_io);
memory_listener_register(&tcg_memory_listener, &address_space_memory);
}
MemoryRegion *get_system_memory(void)
@ -3438,9 +3344,10 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr,
xen_modified_memory(addr, length);
}
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write)
void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf,
int len, bool is_write)
{
AddressSpaceDispatch *d = as->dispatch;
int l;
uint8_t *ptr;
uint32_t val;
@ -3452,7 +3359,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
l = (page + TARGET_PAGE_SIZE) - addr;
if (l > len)
l = len;
section = phys_page_find(page >> TARGET_PAGE_BITS);
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
if (is_write) {
if (!memory_region_is_ram(section->mr)) {
@ -3523,10 +3430,36 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
}
}
void address_space_write(AddressSpace *as, target_phys_addr_t addr,
const uint8_t *buf, int len)
{
address_space_rw(as, addr, (uint8_t *)buf, len, true);
}
/**
* address_space_read: read from an address space.
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
* @buf: buffer with the data transferred
*/
void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len)
{
address_space_rw(as, addr, buf, len, false);
}
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write)
{
return address_space_rw(&address_space_memory, addr, buf, len, is_write);
}
/* used for ROM loading : can write in RAM and ROM */
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
AddressSpaceDispatch *d = address_space_memory.dispatch;
int l;
uint8_t *ptr;
target_phys_addr_t page;
@ -3537,7 +3470,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
l = (page + TARGET_PAGE_SIZE) - addr;
if (l > len)
l = len;
section = phys_page_find(page >> TARGET_PAGE_BITS);
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr) ||
memory_region_is_romd(section->mr))) {
@ -3611,10 +3544,12 @@ static void cpu_notify_map_clients(void)
* Use cpu_register_map_client() to know when retrying the map operation is
* likely to succeed.
*/
void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t *plen,
int is_write)
void *address_space_map(AddressSpace *as,
target_phys_addr_t addr,
target_phys_addr_t *plen,
bool is_write)
{
AddressSpaceDispatch *d = as->dispatch;
target_phys_addr_t len = *plen;
target_phys_addr_t todo = 0;
int l;
@ -3629,7 +3564,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
l = (page + TARGET_PAGE_SIZE) - addr;
if (l > len)
l = len;
section = phys_page_find(page >> TARGET_PAGE_BITS);
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
if (todo || bounce.buffer) {
@ -3639,7 +3574,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
bounce.addr = addr;
bounce.len = l;
if (!is_write) {
cpu_physical_memory_read(addr, bounce.buffer, l);
address_space_read(as, addr, bounce.buffer, l);
}
*plen = l;
@ -3660,12 +3595,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
return ret;
}
/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
/* Unmaps a memory region previously mapped by address_space_map().
* Will also mark the memory as dirty if is_write == 1. access_len gives
* the amount of memory that was actually read or written by the caller.
*/
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len)
void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len)
{
if (buffer != bounce.buffer) {
if (is_write) {
@ -3686,13 +3621,26 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
return;
}
if (is_write) {
cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
address_space_write(as, bounce.addr, bounce.buffer, access_len);
}
qemu_vfree(bounce.buffer);
bounce.buffer = NULL;
cpu_notify_map_clients();
}
void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t *plen,
int is_write)
{
return address_space_map(&address_space_memory, addr, plen, is_write);
}
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len)
{
return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len);
}
/* warning: addr must be aligned */
static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
enum device_endian endian)
@ -3701,7 +3649,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
uint32_t val;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr) ||
memory_region_is_romd(section->mr))) {
@ -3760,7 +3708,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
uint64_t val;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr) ||
memory_region_is_romd(section->mr))) {
@ -3827,7 +3775,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
uint64_t val;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr) ||
memory_region_is_romd(section->mr))) {
@ -3886,7 +3834,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
uint8_t *ptr;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!memory_region_is_ram(section->mr) || section->readonly) {
addr = memory_region_section_addr(section, addr);
@ -3918,7 +3866,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
uint8_t *ptr;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!memory_region_is_ram(section->mr) || section->readonly) {
addr = memory_region_section_addr(section, addr);
@ -3947,7 +3895,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
uint8_t *ptr;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!memory_region_is_ram(section->mr) || section->readonly) {
addr = memory_region_section_addr(section, addr);
@ -4014,7 +3962,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
uint8_t *ptr;
MemoryRegionSection *section;
section = phys_page_find(addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!memory_region_is_ram(section->mr) || section->readonly) {
addr = memory_region_section_addr(section, addr);
@ -4250,7 +4198,8 @@ bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr)
{
MemoryRegionSection *section;
section = phys_page_find(phys_addr >> TARGET_PAGE_BITS);
section = phys_page_find(address_space_memory.dispatch,
phys_addr >> TARGET_PAGE_BITS);
return !(memory_region_is_ram(section->mr) ||
memory_region_is_romd(section->mr));

View File

@ -33,6 +33,7 @@
#include "qmp-commands.h"
#include "msi.h"
#include "msix.h"
#include "exec-memory.h"
//#define DEBUG_PCI
#ifdef DEBUG_PCI
@ -777,6 +778,17 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_dev->bus = bus;
if (bus->dma_context_fn) {
pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
} else {
/* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is
* taken unconditionally */
/* FIXME: inherit memory region from bus creator */
memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
get_system_memory(), 0,
memory_region_size(get_system_memory()));
memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
pci_dev->dma = g_new(DMAContext, 1);
dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL);
}
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
@ -830,6 +842,13 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
qemu_free_irqs(pci_dev->irq);
pci_dev->bus->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev);
if (!pci_dev->bus->dma_context_fn) {
address_space_destroy(&pci_dev->bus_master_as);
memory_region_destroy(&pci_dev->bus_master_enable_region);
g_free(pci_dev->dma);
pci_dev->dma = NULL;
}
}
static void pci_unregister_io_regions(PCIDevice *pci_dev)
@ -1051,8 +1070,12 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
range_covers_byte(addr, l, PCI_COMMAND))
pci_update_mappings(d);
if (range_covers_byte(addr, l, PCI_COMMAND))
if (range_covers_byte(addr, l, PCI_COMMAND)) {
pci_update_irq_disabled(d, was_irq_disabled);
memory_region_set_enabled(&d->bus_master_enable_region,
pci_get_word(d->config + PCI_COMMAND)
& PCI_COMMAND_MASTER);
}
msi_write_config(d, addr, val, l);
msix_write_config(d, addr, val, l);

View File

@ -211,6 +211,8 @@ struct PCIDevice {
int32_t devfn;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
AddressSpace bus_master_as;
MemoryRegion bus_master_enable_region;
DMAContext *dma;
/* do not access the following fields */

View File

@ -21,6 +21,7 @@
#include "qdev.h"
#include "kvm_ppc.h"
#include "dma.h"
#include "exec-memory.h"
#include "hw/spapr.h"
@ -124,7 +125,7 @@ DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
}
tcet = g_malloc0(sizeof(*tcet));
dma_context_init(&tcet->dma, spapr_tce_translate, NULL, NULL);
dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
tcet->liobn = liobn;
tcet->window_size = window_size;

View File

@ -930,25 +930,6 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova,
return -errno;
}
static void vfio_listener_dummy1(MemoryListener *listener)
{
/* We don't do batching (begin/commit) or care about logging */
}
static void vfio_listener_dummy2(MemoryListener *listener,
MemoryRegionSection *section)
{
/* We don't do logging or care about nops */
}
static void vfio_listener_dummy3(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
/* We don't care about eventfds */
}
static bool vfio_listener_skipped_section(MemoryRegionSection *section)
{
return !memory_region_is_ram(section->mr);
@ -1040,18 +1021,8 @@ static void vfio_listener_region_del(MemoryListener *listener,
}
static MemoryListener vfio_memory_listener = {
.begin = vfio_listener_dummy1,
.commit = vfio_listener_dummy1,
.region_add = vfio_listener_region_add,
.region_del = vfio_listener_region_del,
.region_nop = vfio_listener_dummy2,
.log_start = vfio_listener_dummy2,
.log_stop = vfio_listener_dummy2,
.log_sync = vfio_listener_dummy2,
.log_global_start = vfio_listener_dummy1,
.log_global_stop = vfio_listener_dummy1,
.eventfd_add = vfio_listener_dummy3,
.eventfd_del = vfio_listener_dummy3,
};
static void vfio_listener_release(VFIOContainer *container)
@ -1536,8 +1507,7 @@ static int vfio_connect_container(VFIOGroup *group)
container->iommu_data.listener = vfio_memory_listener;
container->iommu_data.release = vfio_listener_release;
memory_listener_register(&container->iommu_data.listener,
get_system_memory());
memory_listener_register(&container->iommu_data.listener, &address_space_memory);
} else {
error_report("vfio: No available IOMMU models\n");
g_free(container);

View File

@ -434,8 +434,7 @@ static void vhost_set_memory(MemoryListener *listener,
static bool vhost_section(MemoryRegionSection *section)
{
return section->address_space == get_system_memory()
&& memory_region_is_ram(section->mr);
return memory_region_is_ram(section->mr);
}
static void vhost_begin(MemoryListener *listener)
@ -793,7 +792,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath,
hdev->log_size = 0;
hdev->log_enabled = false;
hdev->started = false;
memory_listener_register(&hdev->memory_listener, NULL);
memory_listener_register(&hdev->memory_listener, &address_space_memory);
hdev->force = force;
return 0;
fail:

View File

@ -59,6 +59,7 @@
#include "xen_backend.h"
#include "xen_pt.h"
#include "range.h"
#include "exec-memory.h"
#define XEN_PT_NR_IRQS (256)
static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0};
@ -600,14 +601,6 @@ static void xen_pt_region_update(XenPCIPassthroughState *s,
}
}
static void xen_pt_begin(MemoryListener *l)
{
}
static void xen_pt_commit(MemoryListener *l)
{
}
static void xen_pt_region_add(MemoryListener *l, MemoryRegionSection *sec)
{
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
@ -624,36 +617,31 @@ static void xen_pt_region_del(MemoryListener *l, MemoryRegionSection *sec)
xen_pt_region_update(s, sec, false);
}
static void xen_pt_region_nop(MemoryListener *l, MemoryRegionSection *s)
static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec)
{
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
io_listener);
xen_pt_region_update(s, sec, true);
}
static void xen_pt_log_fns(MemoryListener *l, MemoryRegionSection *s)
static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec)
{
}
XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
io_listener);
static void xen_pt_log_global_fns(MemoryListener *l)
{
}
static void xen_pt_eventfd_fns(MemoryListener *l, MemoryRegionSection *s,
bool match_data, uint64_t data, EventNotifier *n)
{
xen_pt_region_update(s, sec, false);
}
static const MemoryListener xen_pt_memory_listener = {
.begin = xen_pt_begin,
.commit = xen_pt_commit,
.region_add = xen_pt_region_add,
.region_nop = xen_pt_region_nop,
.region_del = xen_pt_region_del,
.log_start = xen_pt_log_fns,
.log_stop = xen_pt_log_fns,
.log_sync = xen_pt_log_fns,
.log_global_start = xen_pt_log_global_fns,
.log_global_stop = xen_pt_log_global_fns,
.eventfd_add = xen_pt_eventfd_fns,
.eventfd_del = xen_pt_eventfd_fns,
.priority = 10,
};
static const MemoryListener xen_pt_io_listener = {
.region_add = xen_pt_io_region_add,
.region_del = xen_pt_io_region_del,
.priority = 10,
};
@ -694,6 +682,7 @@ static int xen_pt_initfn(PCIDevice *d)
}
s->memory_listener = xen_pt_memory_listener;
s->io_listener = xen_pt_io_listener;
/* Handle real device's MMIO/PIO BARs */
xen_pt_register_regions(s);
@ -760,7 +749,8 @@ static int xen_pt_initfn(PCIDevice *d)
}
out:
memory_listener_register(&s->memory_listener, NULL);
memory_listener_register(&s->memory_listener, &address_space_memory);
memory_listener_register(&s->io_listener, &address_space_io);
XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n",
bus, slot, func);
@ -815,6 +805,7 @@ static void xen_pt_unregister_device(PCIDevice *d)
xen_pt_unregister_regions(s);
memory_listener_unregister(&s->memory_listener);
memory_listener_unregister(&s->io_listener);
xen_host_pci_device_put(&s->real_device);
}

View File

@ -209,6 +209,7 @@ struct XenPCIPassthroughState {
MemoryRegion rom;
MemoryListener memory_listener;
MemoryListener io_listener;
};
int xen_pt_config_init(XenPCIPassthroughState *s);

105
kvm-all.c
View File

@ -454,9 +454,10 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section)
return ret;
}
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
static void kvm_coalesce_mmio_region(MemoryListener *listener,
MemoryRegionSection *secion,
target_phys_addr_t start, target_phys_addr_t size)
{
int ret = -ENOSYS;
KVMState *s = kvm_state;
if (s->coalesced_mmio) {
@ -466,15 +467,14 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
zone.size = size;
zone.pad = 0;
ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
(void)kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
}
return ret;
}
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
static void kvm_uncoalesce_mmio_region(MemoryListener *listener,
MemoryRegionSection *secion,
target_phys_addr_t start, target_phys_addr_t size)
{
int ret = -ENOSYS;
KVMState *s = kvm_state;
if (s->coalesced_mmio) {
@ -484,10 +484,8 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
zone.size = size;
zone.pad = 0;
ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
(void)kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
}
return ret;
}
int kvm_check_extension(KVMState *s, unsigned int extension)
@ -703,14 +701,6 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
}
}
static void kvm_begin(MemoryListener *listener)
{
}
static void kvm_commit(MemoryListener *listener)
{
}
static void kvm_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@ -723,11 +713,6 @@ static void kvm_region_del(MemoryListener *listener,
kvm_set_phys_mem(section, false);
}
static void kvm_region_nop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void kvm_log_sync(MemoryListener *listener,
MemoryRegionSection *section)
{
@ -755,9 +740,12 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
assert(r >= 0);
}
static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
static void kvm_mem_ioeventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
int fd = event_notifier_get_fd(e);
int r;
assert(match_data && section->size <= 8);
@ -769,9 +757,12 @@ static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
}
}
static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
static void kvm_mem_ioeventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
int fd = event_notifier_get_fd(e);
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
@ -781,9 +772,12 @@ static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
}
}
static void kvm_io_ioeventfd_add(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
static void kvm_io_ioeventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
int fd = event_notifier_get_fd(e);
int r;
assert(match_data && section->size == 2);
@ -795,10 +789,13 @@ static void kvm_io_ioeventfd_add(MemoryRegionSection *section,
}
}
static void kvm_io_ioeventfd_del(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
static void kvm_io_ioeventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
int fd = event_notifier_get_fd(e);
int r;
r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
@ -808,47 +805,24 @@ static void kvm_io_ioeventfd_del(MemoryRegionSection *section,
}
}
static void kvm_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
if (section->address_space == get_system_memory()) {
kvm_mem_ioeventfd_add(section, match_data, data,
event_notifier_get_fd(e));
} else {
kvm_io_ioeventfd_add(section, match_data, data,
event_notifier_get_fd(e));
}
}
static void kvm_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
if (section->address_space == get_system_memory()) {
kvm_mem_ioeventfd_del(section, match_data, data,
event_notifier_get_fd(e));
} else {
kvm_io_ioeventfd_del(section, match_data, data,
event_notifier_get_fd(e));
}
}
static MemoryListener kvm_memory_listener = {
.begin = kvm_begin,
.commit = kvm_commit,
.region_add = kvm_region_add,
.region_del = kvm_region_del,
.region_nop = kvm_region_nop,
.log_start = kvm_log_start,
.log_stop = kvm_log_stop,
.log_sync = kvm_log_sync,
.log_global_start = kvm_log_global_start,
.log_global_stop = kvm_log_global_stop,
.eventfd_add = kvm_eventfd_add,
.eventfd_del = kvm_eventfd_del,
.eventfd_add = kvm_mem_ioeventfd_add,
.eventfd_del = kvm_mem_ioeventfd_del,
.coalesced_mmio_add = kvm_coalesce_mmio_region,
.coalesced_mmio_del = kvm_uncoalesce_mmio_region,
.priority = 10,
};
static MemoryListener kvm_io_listener = {
.eventfd_add = kvm_io_ioeventfd_add,
.eventfd_del = kvm_io_ioeventfd_del,
.priority = 10,
};
@ -1401,7 +1375,8 @@ int kvm_init(void)
}
kvm_state = s;
memory_listener_register(&kvm_memory_listener, NULL);
memory_listener_register(&kvm_memory_listener, &address_space_memory);
memory_listener_register(&kvm_io_listener, &address_space_io);
s->many_ioeventfds = kvm_check_many_ioeventfds();

View File

@ -29,16 +29,6 @@ int kvm_init_vcpu(CPUArchState *env)
return -ENOSYS;
}
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
{
return -ENOSYS;
}
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
{
return -ENOSYS;
}
int kvm_init(void)
{
return -ENOSYS;

2
kvm.h
View File

@ -129,8 +129,6 @@ void *kvm_vmalloc(ram_addr_t size);
void *kvm_arch_vmalloc(ram_addr_t size);
void kvm_setup_guest_memory(void *start, size_t size);
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
void kvm_flush_coalesced_mmio_buffer(void);
#endif

View File

@ -16,16 +16,33 @@
* The functions declared here will be removed soon.
*/
#ifndef EXEC_OBSOLETE_H
#define EXEC_OBSOLETE_H
#ifndef WANT_EXEC_OBSOLETE
#error Do not include exec-obsolete.h
#endif
#ifndef MEMORY_INTERNAL_H
#define MEMORY_INTERNAL_H
#ifndef CONFIG_USER_ONLY
#include "hw/xen.h"
typedef struct PhysPageEntry PhysPageEntry;
struct PhysPageEntry {
uint16_t is_leaf : 1;
/* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */
uint16_t ptr : 15;
};
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
struct AddressSpaceDispatch {
/* This is a multi-level map on the physical address space.
* The bottom level has pointers to MemoryRegionSections.
*/
PhysPageEntry phys_map;
MemoryListener listener;
};
void address_space_init_dispatch(AddressSpace *as);
void address_space_destroy_dispatch(AddressSpace *as);
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr);
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
@ -34,8 +51,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
struct MemoryRegion;
struct MemoryRegionSection;
void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
bool readonly);
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);

173
memory.c
View File

@ -20,8 +20,7 @@
#include "kvm.h"
#include <assert.h>
#define WANT_EXEC_OBSOLETE
#include "exec-obsolete.h"
#include "memory-internal.h"
unsigned memory_region_transaction_depth = 0;
static bool global_dirty_log = false;
@ -29,6 +28,9 @@ static bool global_dirty_log = false;
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
= QTAILQ_HEAD_INITIALIZER(memory_listeners);
static QTAILQ_HEAD(, AddressSpace) address_spaces
= QTAILQ_HEAD_INITIALIZER(address_spaces);
typedef struct AddrRange AddrRange;
/*
@ -97,13 +99,17 @@ static bool memory_listener_match(MemoryListener *listener,
switch (_direction) { \
case Forward: \
QTAILQ_FOREACH(_listener, &memory_listeners, link) { \
_listener->_callback(_listener, ##_args); \
if (_listener->_callback) { \
_listener->_callback(_listener, ##_args); \
} \
} \
break; \
case Reverse: \
QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \
memory_listeners, link) { \
_listener->_callback(_listener, ##_args); \
if (_listener->_callback) { \
_listener->_callback(_listener, ##_args); \
} \
} \
break; \
default: \
@ -118,7 +124,8 @@ static bool memory_listener_match(MemoryListener *listener,
switch (_direction) { \
case Forward: \
QTAILQ_FOREACH(_listener, &memory_listeners, link) { \
if (memory_listener_match(_listener, _section)) { \
if (_listener->_callback \
&& memory_listener_match(_listener, _section)) { \
_listener->_callback(_listener, _section, ##_args); \
} \
} \
@ -126,7 +133,8 @@ static bool memory_listener_match(MemoryListener *listener,
case Reverse: \
QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \
memory_listeners, link) { \
if (memory_listener_match(_listener, _section)) { \
if (_listener->_callback \
&& memory_listener_match(_listener, _section)) { \
_listener->_callback(_listener, _section, ##_args); \
} \
} \
@ -139,7 +147,7 @@ static bool memory_listener_match(MemoryListener *listener,
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \
MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \
.mr = (fr)->mr, \
.address_space = (as)->root, \
.address_space = (as), \
.offset_within_region = (fr)->offset_in_region, \
.size = int128_get64((fr)->addr.size), \
.offset_within_address_space = int128_get64((fr)->addr.start), \
@ -217,17 +225,8 @@ struct FlatView {
unsigned nr_allocated;
};
typedef struct AddressSpace AddressSpace;
typedef struct AddressSpaceOps AddressSpaceOps;
/* A system address space - I/O, memory, etc. */
struct AddressSpace {
MemoryRegion *root;
FlatView current_map;
int ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
};
#define FOR_EACH_FLAT_RANGE(var, view) \
for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
@ -365,8 +364,6 @@ static void access_with_adjusted_size(target_phys_addr_t addr,
}
}
static AddressSpace address_space_memory;
static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
unsigned width, bool write)
{
@ -455,18 +452,17 @@ const IORangeOps memory_region_iorange_ops = {
.destructor = memory_region_iorange_destructor,
};
static AddressSpace address_space_io;
static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
{
AddressSpace *as;
while (mr->parent) {
mr = mr->parent;
}
if (mr == address_space_memory.root) {
return &address_space_memory;
}
if (mr == address_space_io.root) {
return &address_space_io;
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
if (mr == as->root) {
return as;
}
}
abort();
}
@ -568,8 +564,10 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
flatview_init(&view);
render_memory_region(&view, mr, int128_zero(),
addrrange_make(int128_zero(), int128_2_64()), false);
if (mr) {
render_memory_region(&view, mr, int128_zero(),
addrrange_make(int128_zero(), int128_2_64()), false);
}
flatview_simplify(&view);
return view;
@ -597,7 +595,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
fds_new[inew]))) {
fd = &fds_old[iold];
section = (MemoryRegionSection) {
.address_space = as->root,
.address_space = as,
.offset_within_address_space = int128_get64(fd->addr.start),
.size = int128_get64(fd->addr.size),
};
@ -610,7 +608,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
fds_old[iold]))) {
fd = &fds_new[inew];
section = (MemoryRegionSection) {
.address_space = as->root,
.address_space = as,
.offset_within_address_space = int128_get64(fd->addr.start),
.size = int128_get64(fd->addr.size),
};
@ -632,7 +630,7 @@ static void address_space_update_ioeventfds(AddressSpace *as)
AddrRange tmp;
unsigned i;
FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
int128_sub(fr->addr.start,
@ -720,13 +718,13 @@ static void address_space_update_topology_pass(AddressSpace *as,
static void address_space_update_topology(AddressSpace *as)
{
FlatView old_view = as->current_map;
FlatView old_view = *as->current_map;
FlatView new_view = generate_memory_topology(as->root);
address_space_update_topology_pass(as, old_view, new_view, false);
address_space_update_topology_pass(as, old_view, new_view, true);
as->current_map = new_view;
*as->current_map = new_view;
flatview_destroy(&old_view);
address_space_update_ioeventfds(as);
}
@ -739,16 +737,15 @@ void memory_region_transaction_begin(void)
void memory_region_transaction_commit(void)
{
AddressSpace *as;
assert(memory_region_transaction_depth);
--memory_region_transaction_depth;
if (!memory_region_transaction_depth) {
MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
if (address_space_memory.root) {
address_space_update_topology(&address_space_memory);
}
if (address_space_io.root) {
address_space_update_topology(&address_space_io);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
address_space_update_topology(as);
}
MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
@ -1082,12 +1079,14 @@ void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
{
AddressSpace *as;
FlatRange *fr;
FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
if (fr->mr == mr) {
MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory,
Forward, log_sync);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
if (fr->mr == mr) {
MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
}
}
}
}
@ -1130,16 +1129,24 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK);
}
static void memory_region_update_coalesced_range(MemoryRegion *mr)
static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
{
FlatRange *fr;
CoalescedMemoryRange *cmr;
AddrRange tmp;
MemoryRegionSection section;
FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
if (fr->mr == mr) {
qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start),
int128_get64(fr->addr.size));
section = (MemoryRegionSection) {
.address_space = as,
.offset_within_address_space = int128_get64(fr->addr.start),
.size = int128_get64(fr->addr.size),
};
MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, &section,
int128_get64(fr->addr.start),
int128_get64(fr->addr.size));
QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
tmp = addrrange_shift(cmr->addr,
int128_sub(fr->addr.start,
@ -1148,13 +1155,23 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
continue;
}
tmp = addrrange_intersection(tmp, fr->addr);
qemu_register_coalesced_mmio(int128_get64(tmp.start),
int128_get64(tmp.size));
MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, &section,
int128_get64(tmp.start),
int128_get64(tmp.size));
}
}
}
}
static void memory_region_update_coalesced_range(MemoryRegion *mr)
{
AddressSpace *as;
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
memory_region_update_coalesced_range_as(mr, as);
}
}
void memory_region_set_coalescing(MemoryRegion *mr)
{
memory_region_clear_coalescing(mr);
@ -1400,7 +1417,7 @@ static int cmp_flatrange_addr(const void *addr_, const void *fr_)
static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
{
return bsearch(&addr, as->current_map.ranges, as->current_map.nr,
return bsearch(&addr, as->current_map->ranges, as->current_map->nr,
sizeof(FlatRange), cmp_flatrange_addr);
}
@ -1417,7 +1434,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
return ret;
}
while (fr > as->current_map.ranges
while (fr > as->current_map->ranges
&& addrrange_intersects(fr[-1].addr, range)) {
--fr;
}
@ -1438,7 +1455,7 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
AddressSpace *as = memory_region_to_address_space(address_space);
FlatRange *fr;
FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
}
}
@ -1461,29 +1478,35 @@ static void listener_add_address_space(MemoryListener *listener,
FlatRange *fr;
if (listener->address_space_filter
&& listener->address_space_filter != as->root) {
&& listener->address_space_filter != as) {
return;
}
if (global_dirty_log) {
listener->log_global_start(listener);
if (listener->log_global_start) {
listener->log_global_start(listener);
}
}
FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
MemoryRegionSection section = {
.mr = fr->mr,
.address_space = as->root,
.address_space = as,
.offset_within_region = fr->offset_in_region,
.size = int128_get64(fr->addr.size),
.offset_within_address_space = int128_get64(fr->addr.start),
.readonly = fr->readonly,
};
listener->region_add(listener, &section);
if (listener->region_add) {
listener->region_add(listener, &section);
}
}
}
void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
{
MemoryListener *other = NULL;
AddressSpace *as;
listener->address_space_filter = filter;
if (QTAILQ_EMPTY(&memory_listeners)
@ -1498,8 +1521,10 @@ void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
}
QTAILQ_INSERT_BEFORE(other, listener, link);
}
listener_add_address_space(listener, &address_space_memory);
listener_add_address_space(listener, &address_space_io);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
listener_add_address_space(listener, as);
}
}
void memory_listener_unregister(MemoryListener *listener)
@ -1507,18 +1532,28 @@ void memory_listener_unregister(MemoryListener *listener)
QTAILQ_REMOVE(&memory_listeners, listener, link);
}
void set_system_memory_map(MemoryRegion *mr)
void address_space_init(AddressSpace *as, MemoryRegion *root)
{
memory_region_transaction_begin();
address_space_memory.root = mr;
as->root = root;
as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map);
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
as->name = NULL;
memory_region_transaction_commit();
address_space_init_dispatch(as);
}
void set_system_io_map(MemoryRegion *mr)
void address_space_destroy(AddressSpace *as)
{
/* Flush out anything from MemoryListeners listening in on this */
memory_region_transaction_begin();
address_space_io.root = mr;
as->root = NULL;
memory_region_transaction_commit();
QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
address_space_destroy_dispatch(as);
flatview_destroy(as->current_map);
g_free(as->current_map);
}
uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
@ -1638,16 +1673,16 @@ void mtree_info(fprintf_function mon_printf, void *f)
{
MemoryRegionListHead ml_head;
MemoryRegionList *ml, *ml2;
AddressSpace *as;
QTAILQ_INIT(&ml_head);
mon_printf(f, "memory\n");
mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head);
if (address_space_io.root &&
!QTAILQ_EMPTY(&address_space_io.root->subregions)) {
mon_printf(f, "I/O\n");
mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
if (!as->name) {
continue;
}
mon_printf(f, "%s\n", as->name);
mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head);
}
mon_printf(f, "aliases\n");

107
memory.h
View File

@ -157,6 +157,22 @@ struct MemoryRegionPortio {
#define PORTIO_END_OF_LIST() { }
typedef struct AddressSpace AddressSpace;
/**
* AddressSpace: describes a mapping of addresses to #MemoryRegion objects
*/
struct AddressSpace {
/* All fields are private. */
const char *name;
MemoryRegion *root;
struct FlatView *current_map;
int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds;
struct AddressSpaceDispatch *dispatch;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
};
typedef struct MemoryRegionSection MemoryRegionSection;
/**
@ -172,7 +188,7 @@ typedef struct MemoryRegionSection MemoryRegionSection;
*/
struct MemoryRegionSection {
MemoryRegion *mr;
MemoryRegion *address_space;
AddressSpace *address_space;
target_phys_addr_t offset_within_region;
uint64_t size;
target_phys_addr_t offset_within_address_space;
@ -202,9 +218,13 @@ struct MemoryListener {
bool match_data, uint64_t data, EventNotifier *e);
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e);
void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
target_phys_addr_t addr, target_phys_addr_t len);
void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section,
target_phys_addr_t addr, target_phys_addr_t len);
/* Lower = earlier (during add), later (during del) */
unsigned priority;
MemoryRegion *address_space_filter;
AddressSpace *address_space_filter;
QTAILQ_ENTRY(MemoryListener) link;
};
@ -755,7 +775,7 @@ void memory_region_transaction_commit(void);
* @listener: an object containing the callbacks to be called
* @filter: if non-%NULL, only regions in this address space will be observed
*/
void memory_listener_register(MemoryListener *listener, MemoryRegion *filter);
void memory_listener_register(MemoryListener *listener, AddressSpace *filter);
/**
* memory_listener_unregister: undo the effect of memory_listener_register()
@ -776,6 +796,87 @@ void memory_global_dirty_log_stop(void);
void mtree_info(fprintf_function mon_printf, void *f);
/**
* address_space_init: initializes an address space
*
* @as: an uninitialized #AddressSpace
* @root: a #MemoryRegion that routes addesses for the address space
*/
void address_space_init(AddressSpace *as, MemoryRegion *root);
/**
* address_space_destroy: destroy an address space
*
* Releases all resources associated with an address space. After an address space
* is destroyed, its root memory region (given by address_space_init()) may be destroyed
* as well.
*
* @as: address space to be destroyed
*/
void address_space_destroy(AddressSpace *as);
/**
* address_space_rw: read from or write to an address space.
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
* @buf: buffer with the data transferred
* @is_write: indicates the transfer direction
*/
void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf,
int len, bool is_write);
/**
* address_space_write: write to address space.
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
* @buf: buffer with the data transferred
*/
void address_space_write(AddressSpace *as, target_phys_addr_t addr,
const uint8_t *buf, int len);
/**
* address_space_read: read from an address space.
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
* @buf: buffer with the data transferred
*/
void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len);
/* address_space_map: map a physical memory region into a host virtual address
*
* May map a subset of the requested range, given by and returned in @plen.
* May return %NULL if resources needed to perform the mapping are exhausted.
* Use only for reads OR writes - not for read-modify-write operations.
* Use cpu_register_map_client() to know when retrying the map operation is
* likely to succeed.
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
* @plen: pointer to length of buffer; updated on return
* @is_write: indicates the transfer direction
*/
void *address_space_map(AddressSpace *as, target_phys_addr_t addr,
target_phys_addr_t *plen, bool is_write);
/* address_space_unmap: Unmaps a memory region previously mapped by address_space_map()
*
* Will also mark the memory as dirty if @is_write == %true. @access_len gives
* the amount of memory that was actually read or written by the caller.
*
* @as: #AddressSpace used
* @addr: address within that address space
* @len: buffer length as returned by address_space_map()
* @access_len: amount of data actually transferred
* @is_write: indicates the transfer direction
*/
void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len);
#endif
#endif

View File

@ -20,7 +20,6 @@
#include "cpu.h"
#include "memory.h"
#include "cputlb.h"
#include "host-utils.h"
#include "helper.h"
#include <string.h>
@ -81,7 +80,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
#endif
/* basic checks */
if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
if (cpu_physical_memory_is_io(sccb)) {
return -PGM_ADDRESSING;
}
if (sccb & ~0x7ffffff8ul) {

View File

@ -454,14 +454,6 @@ static void xen_set_memory(struct MemoryListener *listener,
}
}
static void xen_begin(MemoryListener *listener)
{
}
static void xen_commit(MemoryListener *listener)
{
}
static void xen_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@ -474,11 +466,6 @@ static void xen_region_del(MemoryListener *listener,
xen_set_memory(listener, section, false);
}
static void xen_region_nop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static void xen_sync_dirty_bitmap(XenIOState *state,
target_phys_addr_t start_addr,
ram_addr_t size)
@ -565,33 +552,14 @@ static void xen_log_global_stop(MemoryListener *listener)
xen_in_migration = false;
}
static void xen_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
}
static void xen_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data,
EventNotifier *e)
{
}
static MemoryListener xen_memory_listener = {
.begin = xen_begin,
.commit = xen_commit,
.region_add = xen_region_add,
.region_del = xen_region_del,
.region_nop = xen_region_nop,
.log_start = xen_log_start,
.log_stop = xen_log_stop,
.log_sync = xen_log_sync,
.log_global_start = xen_log_global_start,
.log_global_stop = xen_log_global_stop,
.eventfd_add = xen_eventfd_add,
.eventfd_del = xen_eventfd_del,
.priority = 10,
};
@ -1173,7 +1141,7 @@ int xen_hvm_init(void)
state->memory_listener = xen_memory_listener;
QLIST_INIT(&state->physmap);
memory_listener_register(&state->memory_listener, get_system_memory());
memory_listener_register(&state->memory_listener, &address_space_memory);
state->log_for_dirtybit = NULL;
/* Initialize backend core & drivers */