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

Conflicts:
	memory.h
This commit is contained in:
Anthony Liguori 2011-12-19 09:12:25 -06:00
commit cde7fc31de
5 changed files with 143 additions and 57 deletions

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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.
*