AddressSpace address_space_memory;
DMAContext dma_context_memory;
-MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
-static MemoryRegion io_mem_subpage_ram;
+MemoryRegion io_mem_rom, io_mem_notdirty;
+static MemoryRegion io_mem_unassigned, io_mem_subpage_ram;
#endif
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)
{
- return mr != &io_mem_ram && mr != &io_mem_rom
- && mr != &io_mem_notdirty && !mr->rom_device
+ return mr != &io_mem_rom && mr != &io_mem_notdirty && !mr->rom_device
&& mr != &io_mem_watch;
}
#endif
return env ? cpu : NULL;
}
+void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
+{
+ CPUArchState *env = first_cpu;
+
+ while (env) {
+ func(ENV_GET_CPU(env), data);
+ env = env->next_cpu;
+ }
+}
+
void cpu_exec_init(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(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);
}
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,
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)) {
#if defined (__linux__) && !defined(TARGET_S390X)
new_block->host = file_ram_alloc(new_block, size, mem_path);
if (!new_block->host) {
- new_block->host = qemu_vmalloc(size);
+ new_block->host = qemu_anon_ram_alloc(size);
memory_try_enable_merging(new_block->host, size);
}
#else
xen_ram_alloc(new_block->offset, size, mr);
} else if (kvm_enabled()) {
/* some s390/kvm configurations have special constraints */
- new_block->host = kvm_vmalloc(size);
+ new_block->host = kvm_ram_alloc(size);
} else {
- new_block->host = qemu_vmalloc(size);
+ new_block->host = qemu_anon_ram_alloc(size);
}
memory_try_enable_merging(new_block->host, size);
}
munmap(block->host, block->length);
close(block->fd);
} else {
- qemu_vfree(block->host);
+ qemu_anon_ram_free(block->host, block->length);
}
#else
abort();
#endif
} else {
-#if defined(TARGET_S390X) && defined(CONFIG_KVM)
- munmap(block->host, block->length);
-#else
if (xen_enabled()) {
xen_invalidate_map_cache_entry(block->host);
} else {
- qemu_vfree(block->host);
+ qemu_anon_ram_free(block->host, block->length);
}
-#endif
}
g_free(block);
break;
}
}
-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;
return ram_addr;
}
-static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
- unsigned size)
-{
-#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
- cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
-#endif
- return 0;
-}
-
-static void unassigned_mem_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
-#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
-#endif
-#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
- cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
-#endif
-}
-
-static const MemoryRegionOps unassigned_mem_ops = {
- .read = unassigned_mem_read,
- .write = unassigned_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t error_mem_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- abort();
-}
-
-static void error_mem_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
+static bool unassigned_mem_accepts(void *opaque, hwaddr addr,
+ unsigned size, bool is_write)
{
- abort();
+ return false;
}
-static const MemoryRegionOps error_mem_ops = {
- .read = error_mem_read,
- .write = error_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const MemoryRegionOps rom_mem_ops = {
- .read = error_mem_read,
- .write = unassigned_mem_write,
+const MemoryRegionOps unassigned_mem_ops = {
+ .valid.accepts = unassigned_mem_accepts,
.endianness = DEVICE_NATIVE_ENDIAN,
};
int dirty_flags;
dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
if (!(dirty_flags & CODE_DIRTY_FLAG)) {
-#if !defined(CONFIG_USER_ONLY)
tb_invalidate_phys_page_fast(ram_addr, size);
dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-#endif
}
switch (size) {
case 1:
tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
}
+static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
+ unsigned size, bool is_write)
+{
+ return is_write;
+}
+
static const MemoryRegionOps notdirty_mem_ops = {
- .read = error_mem_read,
.write = notdirty_mem_write,
+ .valid.accepts = notdirty_mem_accepts,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void io_mem_init(void)
{
- memory_region_init_io(&io_mem_ram, &error_mem_ops, NULL, "ram", UINT64_MAX);
- memory_region_init_io(&io_mem_rom, &rom_mem_ops, NULL, "rom", UINT64_MAX);
+ memory_region_init_io(&io_mem_rom, &unassigned_mem_ops, NULL, "rom", UINT64_MAX);
memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL,
"unassigned", UINT64_MAX);
memory_region_init_io(&io_mem_notdirty, ¬dirty_mem_ops, NULL,
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) ||
+ memory_region_section_addr(section,
addr));
memcpy(buf, ptr, l);
- qemu_put_ram_ptr(ptr);
}
}
len -= l;
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;
}
}
-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)