#include "qemu/osdep.h"
#include "qapi/error.h"
#ifndef _WIN32
-#include <sys/mman.h>
#endif
#include "qemu/cutils.h"
#include "exec/ram_addr.h"
#include "exec/log.h"
+#include "migration/vmstate.h"
+
#include "qemu/range.h"
#ifndef _WIN32
#include "qemu/mmap-alloc.h"
return cpu;
}
-void cpu_exec_exit(CPUState *cpu)
+static void cpu_release_index(CPUState *cpu)
{
- if (cpu->cpu_index == -1) {
- /* cpu_index was never allocated by this @cpu or was already freed. */
- return;
- }
-
bitmap_clear(cpu_index_map, cpu->cpu_index, 1);
- cpu->cpu_index = -1;
}
#else
return cpu_index;
}
-void cpu_exec_exit(CPUState *cpu)
+static void cpu_release_index(CPUState *cpu)
{
+ return;
}
#endif
+void cpu_exec_exit(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+#if defined(CONFIG_USER_ONLY)
+ cpu_list_lock();
+#endif
+ if (cpu->cpu_index == -1) {
+ /* cpu_index was never allocated by this @cpu or was already freed. */
+#if defined(CONFIG_USER_ONLY)
+ cpu_list_unlock();
+#endif
+ return;
+ }
+
+ QTAILQ_REMOVE(&cpus, cpu, node);
+ cpu_release_index(cpu);
+ cpu->cpu_index = -1;
+#if defined(CONFIG_USER_ONLY)
+ cpu_list_unlock();
+#endif
+
+ if (cc->vmsd != NULL) {
+ vmstate_unregister(NULL, cc->vmsd, cpu);
+ }
+ if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
+ vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
+ }
+}
+
void cpu_exec_init(CPUState *cpu, Error **errp)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
*
* Called within RCU critical section.
*/
-void *qemu_get_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
+void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
{
RAMBlock *block = ram_block;
if (block == NULL) {
block = qemu_get_ram_block(addr);
+ addr -= block->offset;
}
if (xen_enabled() && block->host == NULL) {
block->host = xen_map_cache(block->offset, block->max_length, 1);
}
- return ramblock_ptr(block, addr - block->offset);
+ return ramblock_ptr(block, addr);
}
-/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
+/* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr
* but takes a size argument.
*
* Called within RCU critical section.
hwaddr *size)
{
RAMBlock *block = ram_block;
- ram_addr_t offset_inside_block;
if (*size == 0) {
return NULL;
}
if (block == NULL) {
block = qemu_get_ram_block(addr);
+ addr -= block->offset;
}
- offset_inside_block = addr - block->offset;
- *size = MIN(*size, block->max_length - offset_inside_block);
+ *size = MIN(*size, block->max_length - addr);
if (xen_enabled() && block->host == NULL) {
/* We need to check if the requested address is in the RAM
block->host = xen_map_cache(block->offset, block->max_length, 1);
}
- return ramblock_ptr(block, offset_inside_block);
+ return ramblock_ptr(block, addr);
}
/*
* ram_addr_t.
*/
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
- ram_addr_t *ram_addr,
ram_addr_t *offset)
{
RAMBlock *block;
uint8_t *host = ptr;
if (xen_enabled()) {
+ ram_addr_t ram_addr;
rcu_read_lock();
- *ram_addr = xen_ram_addr_from_mapcache(ptr);
- block = qemu_get_ram_block(*ram_addr);
+ ram_addr = xen_ram_addr_from_mapcache(ptr);
+ block = qemu_get_ram_block(ram_addr);
if (block) {
- *offset = (host - block->host);
+ *offset = ram_addr - block->offset;
}
rcu_read_unlock();
return block;
if (round_offset) {
*offset &= TARGET_PAGE_MASK;
}
- *ram_addr = block->offset + *offset;
rcu_read_unlock();
return block;
}
/* Some of the softmmu routines need to translate from a host pointer
(typically a TLB entry) back to a ram offset. */
-MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
+ram_addr_t qemu_ram_addr_from_host(void *ptr)
{
RAMBlock *block;
- ram_addr_t offset; /* Not used */
-
- block = qemu_ram_block_from_host(ptr, false, ram_addr, &offset);
+ ram_addr_t offset;
+ block = qemu_ram_block_from_host(ptr, false, &offset);
if (!block) {
- return NULL;
+ return RAM_ADDR_INVALID;
}
- return block->mr;
+ return block->offset + offset;
}
/* Called within RCU critical section. */
}
switch (size) {
case 1:
- stb_p(qemu_get_ram_ptr(NULL, ram_addr), val);
+ stb_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 2:
- stw_p(qemu_get_ram_ptr(NULL, ram_addr), val);
+ stw_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 4:
- stl_p(qemu_get_ram_ptr(NULL, ram_addr), val);
+ stl_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
default:
abort();
} else {
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
tb_gen_code(cpu, pc, cs_base, cpu_flags, 1);
- cpu_resume_from_signal(cpu, NULL);
+ cpu_loop_exit_noexc(cpu);
}
}
} else {
hwaddr length)
{
uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
+ addr += memory_region_get_ram_addr(mr);
+
/* No early return if dirty_log_mask is or becomes 0, because
* cpu_physical_memory_set_dirty_range will still call
* xen_modified_memory.
abort();
}
} else {
- addr1 += memory_region_get_ram_addr(mr);
/* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
}
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block,
- memory_region_get_ram_addr(mr) + addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
memcpy(buf, ptr, l);
}
memory_region_is_romd(mr))) {
l = memory_access_size(mr, l, addr1);
} else {
- addr1 += memory_region_get_ram_addr(mr);
/* ROM/RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (type) {
case WRITE_DATA:
memcpy(ptr, buf, l);
hwaddr done = 0;
hwaddr l, xlat, base;
MemoryRegion *mr, *this_mr;
- ram_addr_t raddr;
void *ptr;
if (len == 0) {
}
base = xlat;
- raddr = memory_region_get_ram_addr(mr);
for (;;) {
len -= l;
memory_region_ref(mr);
*plen = done;
- ptr = qemu_ram_ptr_length(mr->ram_block, raddr + base, plen);
+ ptr = qemu_ram_ptr_length(mr->ram_block, base, plen);
rcu_read_unlock();
return ptr;
MemoryRegion *mr;
ram_addr_t addr1;
- mr = qemu_ram_addr_from_host(buffer, &addr1);
+ mr = memory_region_from_host(buffer, &addr1);
assert(mr != NULL);
if (is_write) {
invalidate_and_set_dirty(mr, addr1, access_len);
#endif
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block,
- memory_region_get_ram_addr(mr) + addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldl_le_p(ptr);
#endif
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block,
- memory_region_get_ram_addr(mr) + addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = ldq_le_p(ptr);
#endif
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_block,
- memory_region_get_ram_addr(mr) + addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
val = lduw_le_p(ptr);
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else {
- addr1 += memory_region_get_ram_addr(mr);
- ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
stl_p(ptr, val);
dirty_log_mask = memory_region_get_dirty_log_mask(mr);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
- cpu_physical_memory_set_dirty_range(addr1, 4, dirty_log_mask);
+ cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
+ 4, dirty_log_mask);
r = MEMTX_OK;
}
if (result) {
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else {
/* RAM case */
- addr1 += memory_region_get_ram_addr(mr);
- ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stl_le_p(ptr, val);
r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
} else {
/* RAM case */
- addr1 += memory_region_get_ram_addr(mr);
- ptr = qemu_get_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
switch (endian) {
case DEVICE_LITTLE_ENDIAN:
stw_le_p(ptr, val);