aboutsummaryrefslogtreecommitdiff
path: root/memory.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2012-10-11 05:00:35 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2012-10-11 05:00:35 -0300
commit6b852ae04e3aa1adfeac5a62d6ab71870bcc7c5d (patch)
treecdf94fdf09a6b4abecff647784d82bc1ad1758c5 /memory.c
parent8ed1d2756d3347c2b021748d8c272ff650f57dd0 (diff)
parentf430694188293f99a316bfa375b7cc17d23a06ed (diff)
Merge commit 'f430694188293f99a316bfa375b7cc17d23a06ed' into upstream-merge
* commit 'f430694188293f99a316bfa375b7cc17d23a06ed': (248 commits) add pc-1.3 machine type Cleanup unused global var qemu_system_powerdown target-sparc: use notifier for signaling guest system_powerdown command target-arm: use notifier for signaling guest system_powerdown command acpi: use notifier for signaling guest system_powerdown command Introduce powerdown_notifiers tcg/i386: fix build with -march < i686 tcg: Streamline movcond_i64 using movcond_i32 tcg: Streamline movcond_i64 using 32-bit arithmetic tcg: Sanity check goto_tb input tcg: Sanity check deposit inputs tcg: Add tcg_debug_assert tcg: Implement concat*_i64 with deposit_i64 tcg: Emit XORI as NOT for appropriate constants tcg: Optimize initial inputs for ori_i64 tcg: Emit ANDI as EXTU for appropriate constants tcg: Adjust descriptions of *cond opcodes tcg/mips: fix MIPS32(R2) detection block: remove keep_read_only flag from BlockDriverState struct block: convert bdrv_commit() to use bdrv_reopen() ... Conflicts: hw/pc_piix.c Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r--memory.c104
1 files changed, 61 insertions, 43 deletions
diff --git a/memory.c b/memory.c
index d528d1f7f..4f3ade06d 100644
--- a/memory.c
+++ b/memory.c
@@ -24,7 +24,6 @@
#include "exec-obsolete.h"
unsigned memory_region_transaction_depth = 0;
-static bool memory_region_update_pending = false;
static bool global_dirty_log = false;
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
@@ -311,6 +310,9 @@ static void memory_region_read_accessor(void *opaque,
MemoryRegion *mr = opaque;
uint64_t tmp;
+ if (mr->flush_coalesced_mmio) {
+ qemu_flush_coalesced_mmio_buffer();
+ }
tmp = mr->ops->read(mr->opaque, addr, size);
*value |= (tmp & mask) << shift;
}
@@ -325,6 +327,9 @@ static void memory_region_write_accessor(void *opaque,
MemoryRegion *mr = opaque;
uint64_t tmp;
+ if (mr->flush_coalesced_mmio) {
+ qemu_flush_coalesced_mmio_buffer();
+ }
tmp = (*value >> shift) & mask;
mr->ops->write(mr->opaque, addr, tmp, size);
}
@@ -726,33 +731,9 @@ static void address_space_update_topology(AddressSpace *as)
address_space_update_ioeventfds(as);
}
-static void memory_region_update_topology(MemoryRegion *mr)
-{
- if (memory_region_transaction_depth) {
- memory_region_update_pending |= !mr || mr->enabled;
- return;
- }
-
- if (mr && !mr->enabled) {
- return;
- }
-
- 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);
- }
-
- MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
-
- memory_region_update_pending = false;
-}
-
void memory_region_transaction_begin(void)
{
+ qemu_flush_coalesced_mmio_buffer();
++memory_region_transaction_depth;
}
@@ -760,8 +741,17 @@ void memory_region_transaction_commit(void)
{
assert(memory_region_transaction_depth);
--memory_region_transaction_depth;
- if (!memory_region_transaction_depth && memory_region_update_pending) {
- memory_region_update_topology(NULL);
+ 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);
+ }
+
+ MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
}
}
@@ -826,6 +816,7 @@ void memory_region_init(MemoryRegion *mr,
mr->dirty_log_mask = 0;
mr->ioeventfd_nb = 0;
mr->ioeventfds = NULL;
+ mr->flush_coalesced_mmio = false;
}
static bool memory_region_access_valid(MemoryRegion *mr,
@@ -1069,8 +1060,9 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
{
uint8_t mask = 1 << client;
+ memory_region_transaction_begin();
mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
@@ -1103,16 +1095,18 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
{
if (mr->readonly != readonly) {
+ memory_region_transaction_begin();
mr->readonly = readonly;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
}
void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
{
if (mr->readable != readable) {
+ memory_region_transaction_begin();
mr->readable = readable;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
}
@@ -1176,12 +1170,16 @@ void memory_region_add_coalescing(MemoryRegion *mr,
cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
memory_region_update_coalesced_range(mr);
+ memory_region_set_flush_coalesced(mr);
}
void memory_region_clear_coalescing(MemoryRegion *mr)
{
CoalescedMemoryRange *cmr;
+ qemu_flush_coalesced_mmio_buffer();
+ mr->flush_coalesced_mmio = false;
+
while (!QTAILQ_EMPTY(&mr->coalesced)) {
cmr = QTAILQ_FIRST(&mr->coalesced);
QTAILQ_REMOVE(&mr->coalesced, cmr, link);
@@ -1190,6 +1188,19 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
memory_region_update_coalesced_range(mr);
}
+void memory_region_set_flush_coalesced(MemoryRegion *mr)
+{
+ mr->flush_coalesced_mmio = true;
+}
+
+void memory_region_clear_flush_coalesced(MemoryRegion *mr)
+{
+ qemu_flush_coalesced_mmio_buffer();
+ if (QTAILQ_EMPTY(&mr->coalesced)) {
+ mr->flush_coalesced_mmio = false;
+ }
+}
+
void memory_region_add_eventfd(MemoryRegion *mr,
target_phys_addr_t addr,
unsigned size,
@@ -1206,6 +1217,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
};
unsigned i;
+ memory_region_transaction_begin();
for (i = 0; i < mr->ioeventfd_nb; ++i) {
if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
break;
@@ -1217,7 +1229,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
mr->ioeventfds[i] = mrfd;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
void memory_region_del_eventfd(MemoryRegion *mr,
@@ -1236,6 +1248,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
};
unsigned i;
+ memory_region_transaction_begin();
for (i = 0; i < mr->ioeventfd_nb; ++i) {
if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
break;
@@ -1247,7 +1260,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
--mr->ioeventfd_nb;
mr->ioeventfds = g_realloc(mr->ioeventfds,
sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
static void memory_region_add_subregion_common(MemoryRegion *mr,
@@ -1256,6 +1269,8 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
{
MemoryRegion *other;
+ memory_region_transaction_begin();
+
assert(!subregion->parent);
subregion->parent = mr;
subregion->addr = offset;
@@ -1288,7 +1303,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
}
QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
done:
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
@@ -1314,10 +1329,11 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
void memory_region_del_subregion(MemoryRegion *mr,
MemoryRegion *subregion)
{
+ memory_region_transaction_begin();
assert(subregion->parent == mr);
subregion->parent = NULL;
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
@@ -1325,8 +1341,9 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
if (enabled == mr->enabled) {
return;
}
+ memory_region_transaction_begin();
mr->enabled = enabled;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
@@ -1352,16 +1369,15 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
{
- target_phys_addr_t old_offset = mr->alias_offset;
-
assert(mr->alias);
- mr->alias_offset = offset;
- if (offset == old_offset || !mr->parent) {
+ if (offset == mr->alias_offset) {
return;
}
- memory_region_update_topology(mr);
+ memory_region_transaction_begin();
+ mr->alias_offset = offset;
+ memory_region_transaction_commit();
}
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
@@ -1493,14 +1509,16 @@ void memory_listener_unregister(MemoryListener *listener)
void set_system_memory_map(MemoryRegion *mr)
{
+ memory_region_transaction_begin();
address_space_memory.root = mr;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
void set_system_io_map(MemoryRegion *mr)
{
+ memory_region_transaction_begin();
address_space_io.root = mr;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)