mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
[Core Change] Port memory region aliasing from XQEMU 1.x
This commit is contained in:
parent
3f557e6d45
commit
eb4c0f18e9
@ -1133,6 +1133,25 @@ bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size);
|
||||
|
||||
bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client);
|
||||
|
||||
/**
|
||||
* memory_region_set_client_dirty: Mark a range of bytes as dirty
|
||||
* in a memory region for a specified client.
|
||||
*
|
||||
* Marks a range of bytes as dirty, after it has been dirtied outside
|
||||
* guest code.
|
||||
*
|
||||
* @mr: the memory region being dirtied.
|
||||
* @addr: the address (relative to the start of the region) being dirtied.
|
||||
* @size: size of the range being dirtied.
|
||||
* @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
|
||||
* %DIRTY_MEMORY_VGA.
|
||||
*/
|
||||
void memory_region_set_client_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client);
|
||||
|
||||
/**
|
||||
* memory_region_snapshot_and_clear_dirty: Get a snapshot of the dirty
|
||||
* bitmap and clear it.
|
||||
@ -2012,6 +2031,8 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len);
|
||||
}
|
||||
|
||||
void memory_region_destroy(MemoryRegion *mr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -184,11 +184,12 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
|
||||
|
||||
static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
|
||||
{
|
||||
bool nv2a = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_NV2A);
|
||||
bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA);
|
||||
bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE);
|
||||
bool migration =
|
||||
cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
|
||||
return !(vga && code && migration);
|
||||
return !(nv2a && vga && code && migration);
|
||||
}
|
||||
|
||||
static inline uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
|
||||
@ -197,6 +198,10 @@ static inline uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (mask & (1 << DIRTY_MEMORY_NV2A) &&
|
||||
!cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_NV2A)) {
|
||||
ret |= (1 << DIRTY_MEMORY_NV2A);
|
||||
}
|
||||
if (mask & (1 << DIRTY_MEMORY_VGA) &&
|
||||
!cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA)) {
|
||||
ret |= (1 << DIRTY_MEMORY_VGA);
|
||||
@ -269,6 +274,10 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
|
||||
bitmap_set_atomic(blocks[DIRTY_MEMORY_VGA]->blocks[idx],
|
||||
offset, next - page);
|
||||
}
|
||||
if (unlikely(mask & (1 << DIRTY_MEMORY_NV2A))) {
|
||||
bitmap_set_atomic(blocks[DIRTY_MEMORY_NV2A]->blocks[idx],
|
||||
offset, next - page);
|
||||
}
|
||||
if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) {
|
||||
bitmap_set_atomic(blocks[DIRTY_MEMORY_CODE]->blocks[idx],
|
||||
offset, next - page);
|
||||
@ -323,6 +332,7 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
|
||||
|
||||
atomic_or(&blocks[DIRTY_MEMORY_MIGRATION][idx][offset], temp);
|
||||
atomic_or(&blocks[DIRTY_MEMORY_VGA][idx][offset], temp);
|
||||
atomic_or(&blocks[DIRTY_MEMORY_NV2A][idx][offset], temp);
|
||||
if (tcg_enabled()) {
|
||||
atomic_or(&blocks[DIRTY_MEMORY_CODE][idx][offset], temp);
|
||||
}
|
||||
@ -377,6 +387,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
|
||||
{
|
||||
cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_MIGRATION);
|
||||
cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_VGA);
|
||||
cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_NV2A);
|
||||
cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_CODE);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,8 @@ typedef struct RAMBlockNotifier RAMBlockNotifier;
|
||||
#define DIRTY_MEMORY_VGA 0
|
||||
#define DIRTY_MEMORY_CODE 1
|
||||
#define DIRTY_MEMORY_MIGRATION 2
|
||||
#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */
|
||||
#define DIRTY_MEMORY_NV2A 3
|
||||
#define DIRTY_MEMORY_NUM 4 /* num of dirty bits */
|
||||
|
||||
/* The dirty memory bitmap is split into fixed-size blocks to allow growth
|
||||
* under RCU. The bitmap for a block can be accessed as follows:
|
||||
|
66
memory.c
66
memory.c
@ -1701,6 +1701,16 @@ static void memory_region_finalize(Object *obj)
|
||||
g_free(mr->ioeventfds);
|
||||
}
|
||||
|
||||
void memory_region_destroy(MemoryRegion *mr)
|
||||
{
|
||||
assert(QTAILQ_EMPTY(&mr->subregions));
|
||||
assert(memory_region_transaction_depth == 0);
|
||||
mr->destructor(mr);
|
||||
memory_region_clear_coalescing(mr);
|
||||
g_free((char *)mr->name);
|
||||
g_free(mr->ioeventfds);
|
||||
}
|
||||
|
||||
Object *memory_region_owner(MemoryRegion *mr)
|
||||
{
|
||||
Object *obj = OBJECT(mr);
|
||||
@ -1919,12 +1929,9 @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
|
||||
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
|
||||
{
|
||||
uint8_t mask = 1 << client;
|
||||
uint8_t old_logging;
|
||||
|
||||
assert(client == DIRTY_MEMORY_VGA);
|
||||
old_logging = mr->vga_logging_count;
|
||||
mr->vga_logging_count += log ? 1 : -1;
|
||||
if (!!old_logging == !!mr->vga_logging_count) {
|
||||
if (mr->alias) {
|
||||
memory_region_set_log(mr->alias, log, client);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1937,6 +1944,10 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
|
||||
bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_get_dirty(mr->alias, addr - mr->alias_offset,
|
||||
size, client);
|
||||
}
|
||||
assert(mr->ram_block);
|
||||
return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr,
|
||||
size, client);
|
||||
@ -1945,12 +1956,42 @@ bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_set_dirty(mr->alias, addr - mr->alias_offset,
|
||||
size);
|
||||
}
|
||||
assert(mr->ram_block);
|
||||
cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
|
||||
size,
|
||||
memory_region_get_dirty_log_mask(mr));
|
||||
}
|
||||
|
||||
void memory_region_set_client_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_set_client_dirty(mr->alias,
|
||||
addr - mr->alias_offset,
|
||||
size, client);
|
||||
}
|
||||
assert(mr->terminates);
|
||||
return cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
|
||||
size, 1 << client);
|
||||
}
|
||||
|
||||
bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_test_and_clear_dirty(mr->alias,
|
||||
addr - mr->alias_offset,
|
||||
size, client);
|
||||
}
|
||||
assert(mr->terminates);
|
||||
return cpu_physical_memory_test_and_clear_dirty(
|
||||
memory_region_get_ram_addr(mr) + addr, size, client);
|
||||
}
|
||||
|
||||
static void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
|
||||
{
|
||||
MemoryListener *listener;
|
||||
@ -1984,6 +2025,9 @@ DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr,
|
||||
hwaddr size,
|
||||
unsigned client)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_snapshot_and_clear_dirty(mr->alias, addr - mr->alias_offset, size, client);
|
||||
}
|
||||
assert(mr->ram_block);
|
||||
memory_region_sync_dirty_bitmap(mr);
|
||||
return cpu_physical_memory_snapshot_and_clear_dirty(
|
||||
@ -1993,6 +2037,9 @@ DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr,
|
||||
bool memory_region_snapshot_get_dirty(MemoryRegion *mr, DirtyBitmapSnapshot *snap,
|
||||
hwaddr addr, hwaddr size)
|
||||
{
|
||||
if (mr->alias) {
|
||||
return memory_region_snapshot_get_dirty(mr->alias, snap, addr - mr->alias_offset, size);
|
||||
}
|
||||
assert(mr->ram_block);
|
||||
return cpu_physical_memory_snapshot_get_dirty(snap,
|
||||
memory_region_get_ram_addr(mr) + addr, size);
|
||||
@ -2021,6 +2068,11 @@ void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode)
|
||||
void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
|
||||
hwaddr size, unsigned client)
|
||||
{
|
||||
if (mr->alias) {
|
||||
memory_region_reset_dirty(mr->alias, addr - mr->alias_offset,
|
||||
size, client);
|
||||
return;
|
||||
}
|
||||
assert(mr->ram_block);
|
||||
cpu_physical_memory_test_and_clear_dirty(
|
||||
memory_region_get_ram_addr(mr) + addr, size, client);
|
||||
@ -2045,6 +2097,10 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
|
||||
void *ptr;
|
||||
uint64_t offset = 0;
|
||||
|
||||
if (mr->alias) {
|
||||
return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
while (mr->alias) {
|
||||
offset += mr->alias_offset;
|
||||
|
Loading…
Reference in New Issue
Block a user