提交 14655e48 编写于 作者: A Anthony Liguori

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

* qemu-kvm/memory/core: (30 commits)
  memory: allow phys_map tree paths to terminate early
  memory: unify PhysPageEntry::node and ::leaf
  memory: change phys_page_set() to set multiple pages
  memory: switch phys_page_set() to a recursive implementation
  memory: replace phys_page_find_alloc() with phys_page_set()
  memory: simplify multipage/subpage registration
  memory: give phys_page_find() its own tree search loop
  memory: make phys_page_find() return a MemoryRegionSection
  memory: move tlb flush to MemoryListener commit callback
  memory: unify the two branches of cpu_register_physical_memory_log()
  memory: fix RAM subpages in newly initialized pages
  memory: compress phys_map node pointers to 16 bits
  memory: store MemoryRegionSection pointers in phys_map
  memory: unify phys_map last level with intermediate levels
  memory: remove first level of l1_phys_map
  memory: change memory registration to rebuild the memory map on each change
  memory: support stateless memory listeners
  memory: split memory listener for the two address spaces
  xen: ignore I/O memory regions
  memory: allow MemoryListeners to observe a specific address space
  ...
......@@ -37,7 +37,7 @@ void cpu_unregister_io_memory(int table_address);
struct MemoryRegionSection;
void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
bool readable, bool readonly);
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);
......@@ -121,6 +121,9 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
int dirty_flags);
extern const IORangeOps memory_region_iorange_ops;
#endif
#endif
此差异已折叠。
......@@ -436,6 +436,14 @@ static bool vhost_section(MemoryRegionSection *section)
&& memory_region_is_ram(section->mr);
}
static void vhost_begin(MemoryListener *listener)
{
}
static void vhost_commit(MemoryListener *listener)
{
}
static void vhost_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
......@@ -476,6 +484,11 @@ static void vhost_region_del(MemoryListener *listener,
}
}
static void vhost_region_nop(MemoryListener *listener,
MemoryRegionSection *section)
{
}
static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
unsigned idx, bool enable_log)
......@@ -720,6 +733,18 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
0, virtio_queue_get_desc_size(vdev, idx));
}
static void vhost_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
}
static void vhost_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
}
int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
{
uint64_t features;
......@@ -744,13 +769,19 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
hdev->features = features;
hdev->memory_listener = (MemoryListener) {
.begin = vhost_begin,
.commit = vhost_commit,
.region_add = vhost_region_add,
.region_del = vhost_region_del,
.region_nop = vhost_region_nop,
.log_start = vhost_log_start,
.log_stop = vhost_log_stop,
.log_sync = vhost_log_sync,
.log_global_start = vhost_log_global_start,
.log_global_stop = vhost_log_global_stop,
.eventfd_add = vhost_eventfd_add,
.eventfd_del = vhost_eventfd_del,
.priority = 10
};
hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
hdev->n_mem_sections = 0;
......@@ -759,7 +790,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
hdev->log_size = 0;
hdev->log_enabled = false;
hdev->started = false;
memory_listener_register(&hdev->memory_listener);
memory_listener_register(&hdev->memory_listener, NULL);
hdev->force = force;
return 0;
fail:
......
......@@ -328,6 +328,7 @@ void portio_list_init(PortioList *piolist,
piolist->ports = callbacks;
piolist->nr = 0;
piolist->regions = g_new0(MemoryRegion *, n);
piolist->aliases = g_new0(MemoryRegion *, n);
piolist->address_space = NULL;
piolist->opaque = opaque;
piolist->name = name;
......@@ -336,6 +337,7 @@ void portio_list_init(PortioList *piolist,
void portio_list_destroy(PortioList *piolist)
{
g_free(piolist->regions);
g_free(piolist->aliases);
}
static void portio_list_add_1(PortioList *piolist,
......@@ -345,7 +347,7 @@ static void portio_list_add_1(PortioList *piolist,
{
MemoryRegionPortio *pio;
MemoryRegionOps *ops;
MemoryRegion *region;
MemoryRegion *region, *alias;
unsigned i;
/* Copy the sub-list and null-terminate it. */
......@@ -362,12 +364,20 @@ static void portio_list_add_1(PortioList *piolist,
ops->old_portio = pio;
region = g_new(MemoryRegion, 1);
alias = g_new(MemoryRegion, 1);
/*
* Use an alias so that the callback is called with an absolute address,
* rather than an offset relative to to start + off_low.
*/
memory_region_init_io(region, ops, piolist->opaque, piolist->name,
off_high - off_low);
memory_region_set_offset(region, start + off_low);
UINT64_MAX);
memory_region_init_alias(alias, piolist->name,
region, start + off_low, off_high - off_low);
memory_region_add_subregion(piolist->address_space,
start + off_low, region);
piolist->regions[piolist->nr++] = region;
start + off_low, alias);
piolist->regions[piolist->nr] = region;
piolist->aliases[piolist->nr] = alias;
++piolist->nr;
}
void portio_list_add(PortioList *piolist,
......@@ -409,15 +419,19 @@ void portio_list_add(PortioList *piolist,
void portio_list_del(PortioList *piolist)
{
MemoryRegion *mr;
MemoryRegion *mr, *alias;
unsigned i;
for (i = 0; i < piolist->nr; ++i) {
mr = piolist->regions[i];
memory_region_del_subregion(piolist->address_space, mr);
alias = piolist->aliases[i];
memory_region_del_subregion(piolist->address_space, alias);
memory_region_destroy(alias);
memory_region_destroy(mr);
g_free((MemoryRegionOps *)mr->ops);
g_free(mr);
g_free(alias);
piolist->regions[i] = NULL;
piolist->aliases[i] = NULL;
}
}
......@@ -60,6 +60,7 @@ typedef struct PortioList {
struct MemoryRegion *address_space;
unsigned nr;
struct MemoryRegion **regions;
struct MemoryRegion **aliases;
void *opaque;
const char *name;
} PortioList;
......
......@@ -28,6 +28,7 @@
#include "kvm.h"
#include "bswap.h"
#include "memory.h"
#include "exec-memory.h"
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
......@@ -674,6 +675,14 @@ 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)
{
......@@ -686,6 +695,11 @@ 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)
{
......@@ -713,14 +727,95 @@ 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)
{
int r;
assert(match_data && section->size == 4);
r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
data, true);
if (r < 0) {
abort();
}
}
static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
int r;
r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
data, false);
if (r < 0) {
abort();
}
}
static void kvm_io_ioeventfd_add(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
int r;
assert(match_data && section->size == 2);
r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
data, true);
if (r < 0) {
abort();
}
}
static void kvm_io_ioeventfd_del(MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
int r;
r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
data, false);
if (r < 0) {
abort();
}
}
static void kvm_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
if (section->address_space == get_system_memory()) {
kvm_mem_ioeventfd_add(section, match_data, data, fd);
} else {
kvm_io_ioeventfd_add(section, match_data, data, fd);
}
}
static void kvm_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
if (section->address_space == get_system_memory()) {
kvm_mem_ioeventfd_del(section, match_data, data, fd);
} else {
kvm_io_ioeventfd_del(section, match_data, data, fd);
}
}
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,
.priority = 10,
};
static void kvm_handle_interrupt(CPUState *env, int mask)
......@@ -965,7 +1060,7 @@ int kvm_init(void)
}
kvm_state = s;
memory_listener_register(&kvm_memory_listener);
memory_listener_register(&kvm_memory_listener, NULL);
s->many_ioeventfds = kvm_check_many_ioeventfds();
......
此差异已折叠。
......@@ -115,7 +115,6 @@ struct MemoryRegion {
MemoryRegion *parent;
Int128 size;
target_phys_addr_t addr;
target_phys_addr_t offset;
void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr;
IORange iorange;
......@@ -161,6 +160,7 @@ typedef struct MemoryRegionSection MemoryRegionSection;
* @size: the size of the section; will not exceed @mr's boundaries
* @offset_within_address_space: the address of the first byte of the section
* relative to the region's address space
* @readonly: writes to this section are ignored
*/
struct MemoryRegionSection {
MemoryRegion *mr;
......@@ -168,6 +168,7 @@ struct MemoryRegionSection {
target_phys_addr_t offset_within_region;
uint64_t size;
target_phys_addr_t offset_within_address_space;
bool readonly;
};
typedef struct MemoryListener MemoryListener;
......@@ -179,14 +180,24 @@ typedef struct MemoryListener MemoryListener;
* Use with memory_listener_register() and memory_listener_unregister().
*/
struct MemoryListener {
void (*begin)(MemoryListener *listener);
void (*commit)(MemoryListener *listener);
void (*region_add)(MemoryListener *listener, MemoryRegionSection *section);
void (*region_del)(MemoryListener *listener, MemoryRegionSection *section);
void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_start)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_global_start)(MemoryListener *listener);
void (*log_global_stop)(MemoryListener *listener);
QLIST_ENTRY(MemoryListener) link;
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, int fd);
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, int fd);
/* Lower = earlier (during add), later (during del) */
unsigned priority;
MemoryRegion *address_space_filter;
QTAILQ_ENTRY(MemoryListener) link;
};
/**
......@@ -358,14 +369,6 @@ bool memory_region_is_rom(MemoryRegion *mr);
*/
void *memory_region_get_ram_ptr(MemoryRegion *mr);
/**
* memory_region_set_offset: Sets an offset to be added to MemoryRegionOps
* callbacks.
*
* This function is deprecated and should not be used in new code.
*/
void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
/**
* memory_region_set_log: Turn dirty logging on or off for a region.
*
......@@ -686,8 +689,9 @@ void memory_region_transaction_commit(void);
* space
*
* @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);
void memory_listener_register(MemoryListener *listener, MemoryRegion *filter);
/**
* memory_listener_unregister: undo the effect of memory_listener_register()
......
......@@ -392,6 +392,14 @@ 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)
{
......@@ -404,6 +412,11 @@ 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)
......@@ -485,14 +498,32 @@ static void xen_log_global_stop(MemoryListener *listener)
{
}
static void xen_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
}
static void xen_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, int fd)
{
}
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,
};
/* VCPU Operations, MMIO, IO ring ... */
......@@ -975,7 +1006,7 @@ int xen_hvm_init(void)
state->memory_listener = xen_memory_listener;
QLIST_INIT(&state->physmap);
memory_listener_register(&state->memory_listener);
memory_listener_register(&state->memory_listener, get_system_memory());
state->log_for_dirtybit = NULL;
/* Initialize backend core & drivers */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册