Merge remote-tracking branch 'qemu-kvm/memory/mutators' into staging
Conflicts: memory.h
This commit is contained in:
		
						commit
						cde7fc31de
					
				| @ -219,6 +219,18 @@ The functions to do that are inside a vmstate definition, and are called: | ||||
| Example: You can look at hpet.c, that uses the three function to | ||||
|          massage the state that is transferred. | ||||
| 
 | ||||
| If you use memory API functions that update memory layout outside | ||||
| initialization (i.e., in response to a guest action), this is a strong | ||||
| indication that you need to call these functions in a post_load callback. | ||||
| Examples of such memory API functions are: | ||||
| 
 | ||||
|   - memory_region_add_subregion() | ||||
|   - memory_region_del_subregion() | ||||
|   - memory_region_set_readonly() | ||||
|   - memory_region_set_enabled() | ||||
|   - memory_region_set_address() | ||||
|   - memory_region_set_alias_offset() | ||||
| 
 | ||||
| === Subsections === | ||||
| 
 | ||||
| The use of version_id allows to be able to migrate from older versions | ||||
|  | ||||
| @ -205,7 +205,7 @@ typedef struct CirrusVGAState { | ||||
|     bool linear_vram;  /* vga.vram mapped over cirrus_linear_io */ | ||||
|     MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */ | ||||
|     MemoryRegion low_mem;           /* always mapped, overridden by: */ | ||||
|     MemoryRegion *cirrus_bank[2];   /*   aliases at 0xa0000-0xb0000  */ | ||||
|     MemoryRegion cirrus_bank[2];    /*   aliases at 0xa0000-0xb0000  */ | ||||
|     uint32_t cirrus_addr_mask; | ||||
|     uint32_t linear_mmio_mask; | ||||
|     uint8_t cirrus_shadow_gr0; | ||||
| @ -2363,40 +2363,16 @@ static const MemoryRegionOps cirrus_linear_bitblt_io_ops = { | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| static void unmap_bank(CirrusVGAState *s, unsigned bank) | ||||
| { | ||||
|     if (s->cirrus_bank[bank]) { | ||||
|         memory_region_del_subregion(&s->low_mem_container, | ||||
|                                     s->cirrus_bank[bank]); | ||||
|         memory_region_destroy(s->cirrus_bank[bank]); | ||||
|         g_free(s->cirrus_bank[bank]); | ||||
|         s->cirrus_bank[bank] = NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank) | ||||
| { | ||||
|     MemoryRegion *mr; | ||||
|     static const char *names[] = { "vga.bank0", "vga.bank1" }; | ||||
| 
 | ||||
|     if (!(s->cirrus_srcptr != s->cirrus_srcptr_end) | ||||
|     MemoryRegion *mr = &s->cirrus_bank[bank]; | ||||
|     bool enabled = !(s->cirrus_srcptr != s->cirrus_srcptr_end) | ||||
|         && !((s->vga.sr[0x07] & 0x01) == 0) | ||||
|         && !((s->vga.gr[0x0B] & 0x14) == 0x14) | ||||
|         && !(s->vga.gr[0x0B] & 0x02)) { | ||||
|         && !(s->vga.gr[0x0B] & 0x02); | ||||
| 
 | ||||
|         mr = g_malloc(sizeof(*mr)); | ||||
|         memory_region_init_alias(mr, names[bank], &s->vga.vram, | ||||
|                                  s->cirrus_bank_base[bank], 0x8000); | ||||
|         memory_region_add_subregion_overlap( | ||||
|             &s->low_mem_container, | ||||
|             0x8000 * bank, | ||||
|             mr, | ||||
|             1); | ||||
|         unmap_bank(s, bank); | ||||
|         s->cirrus_bank[bank] = mr; | ||||
|     } else { | ||||
|         unmap_bank(s, bank); | ||||
|     } | ||||
|     memory_region_set_enabled(mr, enabled); | ||||
|     memory_region_set_alias_offset(mr, s->cirrus_bank_base[bank]); | ||||
| } | ||||
| 
 | ||||
| static void map_linear_vram(CirrusVGAState *s) | ||||
| @ -2415,8 +2391,8 @@ static void unmap_linear_vram(CirrusVGAState *s) | ||||
|         s->linear_vram = false; | ||||
|         memory_region_del_subregion(&s->pci_bar, &s->vga.vram); | ||||
|     } | ||||
|     unmap_bank(s, 0); | ||||
|     unmap_bank(s, 1); | ||||
|     memory_region_set_enabled(&s->cirrus_bank[0], false); | ||||
|     memory_region_set_enabled(&s->cirrus_bank[1], false); | ||||
| } | ||||
| 
 | ||||
| /* Compute the memory access functions */ | ||||
| @ -2856,6 +2832,14 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, | ||||
|     memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s, | ||||
|                           "cirrus-low-memory", 0x20000); | ||||
|     memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem); | ||||
|     for (i = 0; i < 2; ++i) { | ||||
|         static const char *names[] = { "vga.bank0", "vga.bank1" }; | ||||
|         MemoryRegion *bank = &s->cirrus_bank[i]; | ||||
|         memory_region_init_alias(bank, names[i], &s->vga.vram, 0, 0x8000); | ||||
|         memory_region_set_enabled(bank, false); | ||||
|         memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000, | ||||
|                                             bank, 1); | ||||
|     } | ||||
|     memory_region_add_subregion_overlap(system_memory, | ||||
|                                         isa_mem_base + 0x000a0000, | ||||
|                                         &s->low_mem_container, | ||||
|  | ||||
| @ -81,7 +81,6 @@ struct PCII440FXState { | ||||
|     PAMMemoryRegion pam_regions[13]; | ||||
|     MemoryRegion smram_region; | ||||
|     uint8_t smm_enabled; | ||||
|     bool smram_enabled; | ||||
|     PIIX3State *piix3; | ||||
| }; | ||||
| 
 | ||||
| @ -141,6 +140,7 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) | ||||
| { | ||||
|     int i, r; | ||||
|     uint32_t smram; | ||||
|     bool smram_enabled; | ||||
| 
 | ||||
|     memory_region_transaction_begin(); | ||||
|     update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3, | ||||
| @ -151,18 +151,8 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) | ||||
|                    &d->pam_regions[i+1]); | ||||
|     } | ||||
|     smram = d->dev.config[I440FX_SMRAM]; | ||||
|     if ((d->smm_enabled && (smram & 0x08)) || (smram & 0x40)) { | ||||
|         if (!d->smram_enabled) { | ||||
|             memory_region_del_subregion(d->system_memory, &d->smram_region); | ||||
|             d->smram_enabled = true; | ||||
|         } | ||||
|     } else { | ||||
|         if (d->smram_enabled) { | ||||
|             memory_region_add_subregion_overlap(d->system_memory, 0xa0000, | ||||
|                                                 &d->smram_region, 1); | ||||
|             d->smram_enabled = false; | ||||
|         } | ||||
|     } | ||||
|     smram_enabled = (d->smm_enabled && (smram & 0x08)) || (smram & 0x40); | ||||
|     memory_region_set_enabled(&d->smram_region, !smram_enabled); | ||||
|     memory_region_transaction_commit(); | ||||
| } | ||||
| 
 | ||||
| @ -308,7 +298,9 @@ static PCIBus *i440fx_common_init(const char *device_name, | ||||
|     } | ||||
|     memory_region_init_alias(&f->smram_region, "smram-region", | ||||
|                              f->pci_address_space, 0xa0000, 0x20000); | ||||
|     f->smram_enabled = true; | ||||
|     memory_region_add_subregion_overlap(f->system_memory, 0xa0000, | ||||
|                                         &f->smram_region, 1); | ||||
|     memory_region_set_enabled(&f->smram_region, false); | ||||
| 
 | ||||
|     /* Xen supports additional interrupt routes from the PCI devices to
 | ||||
|      * the IOAPIC: the four pins of each PCI device on the bus are also | ||||
|  | ||||
							
								
								
									
										81
									
								
								memory.c
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								memory.c
									
									
									
									
									
								
							| @ -19,6 +19,7 @@ | ||||
| #include <assert.h> | ||||
| 
 | ||||
| unsigned memory_region_transaction_depth = 0; | ||||
| static bool memory_region_update_pending = false; | ||||
| 
 | ||||
| typedef struct AddrRange AddrRange; | ||||
| 
 | ||||
| @ -528,6 +529,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,9 +755,14 @@ 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) { | ||||
|         memory_region_update_pending |= !mr || mr->enabled; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (mr && !mr->enabled) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -762,6 +772,8 @@ static void memory_region_update_topology(void) | ||||
|     if (address_space_io.root) { | ||||
|         address_space_update_topology(&address_space_io); | ||||
|     } | ||||
| 
 | ||||
|     memory_region_update_pending = false; | ||||
| } | ||||
| 
 | ||||
| void memory_region_transaction_begin(void) | ||||
| @ -773,7 +785,9 @@ void memory_region_transaction_commit(void) | ||||
| { | ||||
|     assert(memory_region_transaction_depth); | ||||
|     --memory_region_transaction_depth; | ||||
|     memory_region_update_topology(); | ||||
|     if (!memory_region_transaction_depth && memory_region_update_pending) { | ||||
|         memory_region_update_topology(NULL); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void memory_region_destructor_none(MemoryRegion *mr) | ||||
| @ -813,6 +827,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 +1073,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 +1105,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 +1113,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 +1218,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 +1248,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 +1289,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 +1318,63 @@ 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 memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) | ||||
| { | ||||
|     MemoryRegion *parent = mr->parent; | ||||
|     unsigned priority = mr->priority; | ||||
|     bool may_overlap = mr->may_overlap; | ||||
| 
 | ||||
|     if (addr == mr->addr || !parent) { | ||||
|         mr->addr = addr; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     memory_region_transaction_begin(); | ||||
|     memory_region_del_subregion(parent, mr); | ||||
|     if (may_overlap) { | ||||
|         memory_region_add_subregion_overlap(parent, addr, mr, priority); | ||||
|     } else { | ||||
|         memory_region_add_subregion(parent, addr, mr); | ||||
|     } | ||||
|     memory_region_transaction_commit(); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     memory_region_update_topology(mr); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|  | ||||
							
								
								
									
										39
									
								
								memory.h
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								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,44 @@ 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); | ||||
| 
 | ||||
| /*
 | ||||
|  * memory_region_set_address: dynamically update the address of a region | ||||
|  * | ||||
|  * Dynamically updates the address of a region, relative to its parent. | ||||
|  * May be used on regions are currently part of a memory hierarchy. | ||||
|  * | ||||
|  * @mr: the region to be updated | ||||
|  * @addr: new address, relative to parent region | ||||
|  */ | ||||
| void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr); | ||||
| 
 | ||||
| /*
 | ||||
|  * memory_region_set_alias_offset: dynamically update a memory alias's offset | ||||
|  * | ||||
|  * Dynamically updates the offset into the target region that an alias points | ||||
|  * to, as if the fourth argument to memory_region_init_alias() has changed. | ||||
|  * | ||||
|  * @mr: the #MemoryRegion to be updated; should be an alias. | ||||
|  * @offset: the new offset into the target memory region | ||||
|  */ | ||||
| void memory_region_set_alias_offset(MemoryRegion *mr, | ||||
|                                     target_phys_addr_t offset); | ||||
| 
 | ||||
| /**
 | ||||
|  * memory_region_transaction_begin: Start a transaction. | ||||
|  * | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anthony Liguori
						Anthony Liguori