memory: introduce memory_region_set_enabled()
This allows users to disable a memory region without removing it from the hierarchy, simplifying the implementation of memory routers. Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
		
							parent
							
								
									f44336c594
								
							
						
					
					
						commit
						6bba19ba4e
					
				
							
								
								
									
										40
									
								
								memory.c
								
								
								
								
							
							
						
						
									
										40
									
								
								memory.c
								
								
								
								
							| 
						 | 
				
			
			@ -528,6 +528,10 @@ static void render_memory_region(FlatView *view,
 | 
			
		|||
    FlatRange fr;
 | 
			
		||||
    AddrRange tmp;
 | 
			
		||||
 | 
			
		||||
    if (!mr->enabled) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int128_addto(&base, int128_make64(mr->addr));
 | 
			
		||||
    readonly |= mr->readonly;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -750,12 +754,16 @@ static void address_space_update_topology(AddressSpace *as)
 | 
			
		|||
    address_space_update_ioeventfds(as);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void memory_region_update_topology(void)
 | 
			
		||||
static void memory_region_update_topology(MemoryRegion *mr)
 | 
			
		||||
{
 | 
			
		||||
    if (memory_region_transaction_depth) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mr && !mr->enabled) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (address_space_memory.root) {
 | 
			
		||||
        address_space_update_topology(&address_space_memory);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -773,7 +781,7 @@ void memory_region_transaction_commit(void)
 | 
			
		|||
{
 | 
			
		||||
    assert(memory_region_transaction_depth);
 | 
			
		||||
    --memory_region_transaction_depth;
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void memory_region_destructor_none(MemoryRegion *mr)
 | 
			
		||||
| 
						 | 
				
			
			@ -813,6 +821,7 @@ void memory_region_init(MemoryRegion *mr,
 | 
			
		|||
    }
 | 
			
		||||
    mr->addr = 0;
 | 
			
		||||
    mr->offset = 0;
 | 
			
		||||
    mr->enabled = true;
 | 
			
		||||
    mr->terminates = false;
 | 
			
		||||
    mr->readable = true;
 | 
			
		||||
    mr->readonly = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1058,7 +1067,7 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 | 
			
		|||
    uint8_t mask = 1 << client;
 | 
			
		||||
 | 
			
		||||
    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(mr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
 | 
			
		||||
| 
						 | 
				
			
			@ -1090,7 +1099,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 | 
			
		|||
{
 | 
			
		||||
    if (mr->readonly != readonly) {
 | 
			
		||||
        mr->readonly = readonly;
 | 
			
		||||
        memory_region_update_topology();
 | 
			
		||||
        memory_region_update_topology(mr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1098,7 +1107,7 @@ void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
 | 
			
		|||
{
 | 
			
		||||
    if (mr->readable != readable) {
 | 
			
		||||
        mr->readable = readable;
 | 
			
		||||
        memory_region_update_topology();
 | 
			
		||||
        memory_region_update_topology(mr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1203,7 +1212,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();
 | 
			
		||||
    memory_region_update_topology(mr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memory_region_del_eventfd(MemoryRegion *mr,
 | 
			
		||||
| 
						 | 
				
			
			@ -1233,7 +1242,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();
 | 
			
		||||
    memory_region_update_topology(mr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void memory_region_add_subregion_common(MemoryRegion *mr,
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,7 +1283,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
 | 
			
		|||
    }
 | 
			
		||||
    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
 | 
			
		||||
done:
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(mr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1303,19 +1312,28 @@ void memory_region_del_subregion(MemoryRegion *mr,
 | 
			
		|||
    assert(subregion->parent == mr);
 | 
			
		||||
    subregion->parent = NULL;
 | 
			
		||||
    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(mr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    if (enabled == mr->enabled) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    mr->enabled = enabled;
 | 
			
		||||
    memory_region_update_topology(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void set_system_memory_map(MemoryRegion *mr)
 | 
			
		||||
{
 | 
			
		||||
    address_space_memory.root = mr;
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void set_system_io_map(MemoryRegion *mr)
 | 
			
		||||
{
 | 
			
		||||
    address_space_io.root = mr;
 | 
			
		||||
    memory_region_update_topology();
 | 
			
		||||
    memory_region_update_topology(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct MemoryRegionList MemoryRegionList;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								memory.h
								
								
								
								
							
							
						
						
									
										17
									
								
								memory.h
								
								
								
								
							| 
						 | 
				
			
			@ -123,6 +123,7 @@ struct MemoryRegion {
 | 
			
		|||
    bool terminates;
 | 
			
		||||
    bool readable;
 | 
			
		||||
    bool readonly; /* For RAM regions */
 | 
			
		||||
    bool enabled;
 | 
			
		||||
    MemoryRegion *alias;
 | 
			
		||||
    target_phys_addr_t alias_offset;
 | 
			
		||||
    unsigned priority;
 | 
			
		||||
| 
						 | 
				
			
			@ -501,6 +502,22 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 | 
			
		|||
void memory_region_del_subregion(MemoryRegion *mr,
 | 
			
		||||
                                 MemoryRegion *subregion);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * memory_region_set_enabled: dynamically enable or disable a region
 | 
			
		||||
 *
 | 
			
		||||
 * Enables or disables a memory region.  A disabled memory region
 | 
			
		||||
 * ignores all accesses to itself and its subregions.  It does not
 | 
			
		||||
 * obscure sibling subregions with lower priority - it simply behaves as
 | 
			
		||||
 * if it was removed from the hierarchy.
 | 
			
		||||
 *
 | 
			
		||||
 * Regions default to being enabled.
 | 
			
		||||
 *
 | 
			
		||||
 * @mr: the region to be updated
 | 
			
		||||
 * @enabled: whether to enable or disable the region
 | 
			
		||||
 */
 | 
			
		||||
void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
 | 
			
		||||
 | 
			
		||||
/* Start a transaction; changes will be accumulated and made visible only
 | 
			
		||||
 * when the transaction ends.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue