Merge remote-tracking branch 'bonzini/iommu-for-anthony' into staging

# By Paolo Bonzini (11) and others
# Via Paolo Bonzini
* bonzini/iommu-for-anthony:
  memory: clean up phys_page_find
  memory: populate FlatView for new address spaces
  memory: limit sections in the radix tree to the actual address space size
  s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62
  memory: fix address space initialization/destruction
  memory: make memory_global_sync_dirty_bitmap take an AddressSpace
  memory: do not duplicate memory_region_destructor_none
  memory: Rename readable flag to romd_mode
  memory: Replace open-coded memory_region_is_romd
  memory: allow memory_region_find() to run on non-root memory regions
  memory: assert that PhysPageEntry's ptr does not overflow
  exec: eliminate stq_phys_notdirty
  exec: make qemu_get_ram_ptr private
  exec: eliminate qemu_put_ram_ptr
  exec: remove obsolete comment

Message-id: 1369414987-8839-1-git-send-email-pbonzini@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-05-24 13:47:42 -05:00
commit fd469df97a
14 changed files with 103 additions and 118 deletions

View File

@ -386,7 +386,7 @@ static void migration_bitmap_sync(void)
}
trace_migration_bitmap_sync_start();
memory_global_sync_dirty_bitmap(get_system_memory());
address_space_sync_dirty_bitmap(&address_space_memory);
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {

68
exec.c
View File

@ -187,19 +187,15 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
PhysPageEntry lp = d->phys_map;
PhysPageEntry *p;
int i;
uint16_t s_index = phys_section_unassigned;
for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
if (lp.ptr == PHYS_MAP_NODE_NIL) {
goto not_found;
return &phys_sections[phys_section_unassigned];
}
p = phys_map_nodes[lp.ptr];
lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
}
s_index = lp.ptr;
not_found:
return &phys_sections[s_index];
return &phys_sections[lp.ptr];
}
bool memory_region_is_unassigned(MemoryRegion *mr)
@ -639,12 +635,6 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
iotlb |= phys_section_rom;
}
} else {
/* IO handlers are currently passed a physical address.
It would be nice to pass an offset from the base address
of that region. This would avoid having to special case RAM,
and avoid full address decoding in every device.
We can't use the high bits of pd for this because
IO_MEM_ROMD uses these as a ram address. */
iotlb = section - phys_sections;
iotlb += memory_region_section_addr(section, paddr);
}
@ -719,6 +709,12 @@ static void destroy_all_mappings(AddressSpaceDispatch *d)
static uint16_t phys_section_add(MemoryRegionSection *section)
{
/* The physical section number is ORed with a page-aligned
* pointer to produce the iotlb entries. Thus it should
* never overflow into the page-aligned value.
*/
assert(phys_sections_nb < TARGET_PAGE_SIZE);
if (phys_sections_nb == phys_sections_nb_alloc) {
phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
phys_sections = g_renew(MemoryRegionSection, phys_sections,
@ -775,10 +771,21 @@ static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *sec
section_index);
}
QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > MAX_PHYS_ADDR_SPACE_BITS)
static MemoryRegionSection limit(MemoryRegionSection section)
{
section.size = MIN(section.offset_within_address_space + section.size,
MAX_PHYS_ADDR + 1)
- section.offset_within_address_space;
return section;
}
static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
{
AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
MemoryRegionSection now = *section, remain = *section;
MemoryRegionSection now = limit(*section), remain = limit(*section);
if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
|| (now.size < TARGET_PAGE_SIZE)) {
@ -1340,11 +1347,6 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
}
}
void qemu_put_ram_ptr(void *addr)
{
trace_qemu_put_ram_ptr(addr);
}
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
{
RAMBlock *block;
@ -1934,7 +1936,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
qemu_put_ram_ptr(ptr);
}
} else {
if (!(memory_region_is_ram(section->mr) ||
@ -1964,7 +1965,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
+ memory_region_section_addr(section,
addr));
memcpy(buf, ptr, l);
qemu_put_ram_ptr(ptr);
}
}
len -= l;
@ -2026,7 +2026,6 @@ void cpu_physical_memory_write_rom(hwaddr addr,
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
qemu_put_ram_ptr(ptr);
}
len -= l;
buf += l;
@ -2404,33 +2403,6 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
}
}
void stq_phys_notdirty(hwaddr addr, uint64_t val)
{
uint8_t *ptr;
MemoryRegionSection *section;
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
if (!memory_region_is_ram(section->mr) || section->readonly) {
addr = memory_region_section_addr(section, addr);
if (memory_region_is_ram(section->mr)) {
section = &phys_sections[phys_section_rom];
}
#ifdef TARGET_WORDS_BIGENDIAN
io_mem_write(section->mr, addr, val >> 32, 4);
io_mem_write(section->mr, addr + 4, (uint32_t)val, 4);
#else
io_mem_write(section->mr, addr, (uint32_t)val, 4);
io_mem_write(section->mr, addr + 4, val >> 32, 4);
#endif
} else {
ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
& TARGET_PAGE_MASK)
+ memory_region_section_addr(section, addr));
stq_p(ptr, val);
}
}
/* warning: addr must be aligned */
static inline void stl_phys_internal(hwaddr addr, uint32_t val,
enum device_endian endian)

View File

@ -105,7 +105,7 @@ static void pflash_timer (void *opaque)
DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
/* Reset flash */
pfl->status ^= 0x80;
memory_region_rom_device_set_readable(&pfl->mem, true);
memory_region_rom_device_set_romd(&pfl->mem, true);
pfl->wcycle = 0;
pfl->cmd = 0;
}
@ -281,7 +281,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
if (!pfl->wcycle) {
/* Set the device in I/O access mode */
memory_region_rom_device_set_readable(&pfl->mem, false);
memory_region_rom_device_set_romd(&pfl->mem, false);
}
switch (pfl->wcycle) {
@ -458,7 +458,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
"\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
reset_flash:
memory_region_rom_device_set_readable(&pfl->mem, true);
memory_region_rom_device_set_romd(&pfl->mem, true);
pfl->wcycle = 0;
pfl->cmd = 0;

View File

@ -111,7 +111,7 @@ static void pflash_setup_mappings(pflash_t *pfl)
static void pflash_register_memory(pflash_t *pfl, int rom_mode)
{
memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
pfl->rom_mode = rom_mode;
}

View File

@ -1959,8 +1959,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
pci_patch_ids(pdev, ptr, size);
}
qemu_put_ram_ptr(ptr);
pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
return 0;

View File

@ -711,7 +711,6 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
ptr = memory_region_get_ram_ptr(&s->dev.rom);
memcpy(biosver, ptr + 0x41, 31);
qemu_put_ram_ptr(ptr);
memcpy(info.image_component[1].name, "BIOS", 4);
memcpy(info.image_component[1].version, biosver,
strlen((const char *)biosver));

View File

@ -49,9 +49,6 @@ typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
void qemu_put_ram_ptr(void *addr);
/* This should not be used by devices. */
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
@ -105,7 +102,6 @@ uint32_t lduw_phys(hwaddr addr);
uint32_t ldl_phys(hwaddr addr);
uint64_t ldq_phys(hwaddr addr);
void stl_phys_notdirty(hwaddr addr, uint32_t val);
void stq_phys_notdirty(hwaddr addr, uint64_t val);
void stw_phys(hwaddr addr, uint32_t val);
void stl_phys(hwaddr addr, uint32_t val);
void stq_phys(hwaddr addr, uint64_t val);

View File

@ -46,6 +46,7 @@ void address_space_destroy_dispatch(AddressSpace *as);
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr);
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
void *qemu_get_ram_ptr(ram_addr_t addr);
void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr);

View File

@ -26,6 +26,9 @@
#include "exec/ioport.h"
#include "qemu/int128.h"
#define MAX_PHYS_ADDR_SPACE_BITS 62
#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
typedef struct MemoryRegionOps MemoryRegionOps;
typedef struct MemoryRegionPortio MemoryRegionPortio;
typedef struct MemoryRegionMmio MemoryRegionMmio;
@ -126,7 +129,7 @@ struct MemoryRegion {
ram_addr_t ram_addr;
bool subpage;
bool terminates;
bool readable;
bool romd_mode;
bool ram;
bool readonly; /* For RAM regions */
bool enabled;
@ -355,16 +358,16 @@ uint64_t memory_region_size(MemoryRegion *mr);
bool memory_region_is_ram(MemoryRegion *mr);
/**
* memory_region_is_romd: check whether a memory region is ROMD
* memory_region_is_romd: check whether a memory region is in ROMD mode
*
* Returns %true is a memory region is ROMD and currently set to allow
* Returns %true if a memory region is a ROM device and currently set to allow
* direct reads.
*
* @mr: the memory region being queried
*/
static inline bool memory_region_is_romd(MemoryRegion *mr)
{
return mr->rom_device && mr->readable;
return mr->rom_device && mr->romd_mode;
}
/**
@ -502,18 +505,18 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
/**
* memory_region_rom_device_set_readable: enable/disable ROM readability
* memory_region_rom_device_set_romd: enable/disable ROMD mode
*
* Allows a ROM device (initialized with memory_region_init_rom_device() to
* to be marked as readable (default) or not readable. When it is readable,
* the device is mapped to guest memory. When not readable, reads are
* forwarded to the #MemoryRegion.read function.
* set to ROMD mode (default) or MMIO mode. When it is in ROMD mode, the
* device is mapped to guest memory and satisfies read access directly.
* When in MMIO mode, reads are forwarded to the #MemoryRegion.read function.
* Writes are always handled by the #MemoryRegion.write function.
*
* @mr: the memory region to be updated
* @readable: whether reads are satisified directly (%true) or via callbacks
* (%false)
* @romd_mode: %true to put the region into ROMD mode
*/
void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable);
void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode);
/**
* memory_region_set_coalescing: Enable memory coalescing for the region.
@ -718,24 +721,34 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
hwaddr offset);
/**
* memory_region_find: locate a MemoryRegion in an address space
* memory_region_find: translate an address/size relative to a
* MemoryRegion into a #MemoryRegionSection.
*
* Locates the first #MemoryRegion within an address space given by
* @address_space that overlaps the range given by @addr and @size.
* Locates the first #MemoryRegion within @mr that overlaps the range
* given by @addr and @size.
*
* Returns a #MemoryRegionSection that describes a contiguous overlap.
* It will have the following characteristics:
* .@offset_within_address_space >= @addr
* .@offset_within_address_space + .@size <= @addr + @size
* .@size = 0 iff no overlap was found
* .@mr is non-%NULL iff an overlap was found
*
* @address_space: a top-level (i.e. parentless) region that contains
* the region to be found
* @addr: start of the area within @address_space to be searched
* Remember that in the return value the @offset_within_region is
* relative to the returned region (in the .@mr field), not to the
* @mr argument.
*
* Similarly, the .@offset_within_address_space is relative to the
* address space that contains both regions, the passed and the
* returned one. However, in the special case where the @mr argument
* has no parent (and thus is the root of the address space), the
* following will hold:
* .@offset_within_address_space >= @addr
* .@offset_within_address_space + .@size <= @addr + @size
*
* @mr: a MemoryRegion within which @addr is a relative address
* @addr: start of the area within @as to be searched
* @size: size of the area to be searched
*/
MemoryRegionSection memory_region_find(MemoryRegion *address_space,
MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size);
/**
@ -756,13 +769,12 @@ memory_region_section_addr(MemoryRegionSection *section,
}
/**
* memory_global_sync_dirty_bitmap: synchronize the dirty log for all memory
* address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
*
* Synchronizes the dirty page log for an entire address space.
* @address_space: a top-level (i.e. parentless) region that contains the
* memory being synchronized
* @as: the address space that contains the memory being synchronized
*/
void memory_global_sync_dirty_bitmap(MemoryRegion *address_space);
void address_space_sync_dirty_bitmap(AddressSpace *as);
/**
* memory_region_transaction_begin: Start a transaction.

View File

@ -42,7 +42,6 @@
#pragma GCC poison ldl_phys
#pragma GCC poison ldq_phys
#pragma GCC poison stl_phys_notdirty
#pragma GCC poison stq_phys_notdirty
#pragma GCC poison stw_phys
#pragma GCC poison stl_phys
#pragma GCC poison stq_phys

View File

@ -213,7 +213,7 @@ struct FlatRange {
hwaddr offset_in_region;
AddrRange addr;
uint8_t dirty_log_mask;
bool readable;
bool romd_mode;
bool readonly;
};
@ -236,7 +236,7 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
return a->mr == b->mr
&& addrrange_equal(a->addr, b->addr)
&& a->offset_in_region == b->offset_in_region
&& a->readable == b->readable
&& a->romd_mode == b->romd_mode
&& a->readonly == b->readonly;
}
@ -276,7 +276,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
r1->addr.size),
int128_make64(r2->offset_in_region))
&& r1->dirty_log_mask == r2->dirty_log_mask
&& r1->readable == r2->readable
&& r1->romd_mode == r2->romd_mode
&& r1->readonly == r2->readonly;
}
@ -532,7 +532,7 @@ static void render_memory_region(FlatView *view,
fr.offset_in_region = offset_in_region;
fr.addr = addrrange_make(base, now);
fr.dirty_log_mask = mr->dirty_log_mask;
fr.readable = mr->readable;
fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
flatview_insert(view, i, &fr);
++i;
@ -552,7 +552,7 @@ static void render_memory_region(FlatView *view,
fr.offset_in_region = offset_in_region;
fr.addr = addrrange_make(base, remain);
fr.dirty_log_mask = mr->dirty_log_mask;
fr.readable = mr->readable;
fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
flatview_insert(view, i, &fr);
}
@ -768,10 +768,6 @@ static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
qemu_ram_free_from_ptr(mr->ram_addr);
}
static void memory_region_destructor_iomem(MemoryRegion *mr)
{
}
static void memory_region_destructor_rom_device(MemoryRegion *mr)
{
qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
@ -801,7 +797,7 @@ void memory_region_init(MemoryRegion *mr,
mr->enabled = true;
mr->terminates = false;
mr->ram = false;
mr->readable = true;
mr->romd_mode = true;
mr->readonly = false;
mr->rom_device = false;
mr->destructor = memory_region_destructor_none;
@ -929,7 +925,6 @@ void memory_region_init_io(MemoryRegion *mr,
mr->ops = ops;
mr->opaque = opaque;
mr->terminates = true;
mr->destructor = memory_region_destructor_iomem;
mr->ram_addr = ~(ram_addr_t)0;
}
@ -1121,11 +1116,11 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
}
}
void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode)
{
if (mr->readable != readable) {
if (mr->romd_mode != romd_mode) {
memory_region_transaction_begin();
mr->readable = readable;
mr->romd_mode = romd_mode;
memory_region_update_pending |= mr->enabled;
memory_region_transaction_commit();
}
@ -1451,15 +1446,24 @@ static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
sizeof(FlatRange), cmp_flatrange_addr);
}
MemoryRegionSection memory_region_find(MemoryRegion *address_space,
MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size)
{
AddressSpace *as = memory_region_to_address_space(address_space);
AddrRange range = addrrange_make(int128_make64(addr),
int128_make64(size));
FlatRange *fr = address_space_lookup(as, range);
MemoryRegionSection ret = { .mr = NULL, .size = 0 };
MemoryRegion *root;
AddressSpace *as;
AddrRange range;
FlatRange *fr;
addr += mr->addr;
for (root = mr; root->parent; ) {
root = root->parent;
addr += root->addr;
}
as = memory_region_to_address_space(root);
range = addrrange_make(int128_make64(addr), int128_make64(size));
fr = address_space_lookup(as, range);
if (!fr) {
return ret;
}
@ -1470,6 +1474,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
}
ret.mr = fr->mr;
ret.address_space = as;
range = addrrange_intersection(range, fr->addr);
ret.offset_within_region = fr->offset_in_region;
ret.offset_within_region += int128_get64(int128_sub(range.start,
@ -1480,9 +1485,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
return ret;
}
void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
void address_space_sync_dirty_bitmap(AddressSpace *as)
{
AddressSpace *as = memory_region_to_address_space(address_space);
FlatRange *fr;
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
@ -1568,10 +1572,13 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
as->root = root;
as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map);
as->ioeventfd_nb = 0;
as->ioeventfds = NULL;
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
as->name = NULL;
memory_region_transaction_commit();
address_space_init_dispatch(as);
memory_region_update_pending |= root->enabled;
memory_region_transaction_commit();
}
void address_space_destroy(AddressSpace *as)
@ -1584,6 +1591,7 @@ void address_space_destroy(AddressSpace *as)
address_space_destroy_dispatch(as);
flatview_destroy(as->current_map);
g_free(as->current_map);
g_free(as->ioeventfds);
}
uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size)
@ -1649,9 +1657,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
base + mr->addr
+ (hwaddr)int128_get64(mr->size) - 1,
mr->priority,
mr->readable ? 'R' : '-',
!mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
: '-',
mr->romd_mode ? 'R' : '-',
!mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
: '-',
mr->name,
mr->alias->name,
mr->alias_offset,
@ -1664,9 +1672,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
base + mr->addr
+ (hwaddr)int128_get64(mr->size) - 1,
mr->priority,
mr->readable ? 'R' : '-',
!mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
: '-',
mr->romd_mode ? 'R' : '-',
!mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
: '-',
mr->name);
}

View File

@ -34,7 +34,10 @@
#include "exec/cpu-defs.h"
#define TARGET_PAGE_BITS 12
#define TARGET_PHYS_ADDR_SPACE_BITS 64
/* Actually 64-bits, limited by the memory API to 62 bits. We
* never use that much.
*/
#define TARGET_PHYS_ADDR_SPACE_BITS 62
#define TARGET_VIRT_ADDR_SPACE_BITS 64
#include "exec/cpu-all.h"

View File

@ -813,9 +813,6 @@ xen_map_cache_return(void* ptr) "%p"
xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64
xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
# exec.c
qemu_put_ram_ptr(void* addr) "%p"
# hw/xen_platform.c
xen_platform_log(char *s) "xen platform: %s"

View File

@ -1358,7 +1358,7 @@ void tb_invalidate_phys_addr(hwaddr addr)
section = phys_page_find(address_space_memory.dispatch,
addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr)
|| (section->mr->rom_device && section->mr->readable))) {
|| memory_region_is_romd(section->mr))) {
return;
}
ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)