CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-static int io_mem_nb;
+char io_mem_used[IO_MEM_NB_ENTRIES];
static int io_mem_watch;
#endif
return NULL;
pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
*lp = pd;
- for (i = 0; i < L2_SIZE; i++)
+ for (i = 0; i < L2_SIZE; i++) {
pd[i].phys_offset = IO_MEM_UNASSIGNED;
+ pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
+ }
}
return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
}
}
#else
code_gen_buffer = qemu_malloc(code_gen_buffer_size);
- if (!code_gen_buffer) {
- fprintf(stderr, "Could not allocate dynamic translator buffer\n");
- exit(1);
- }
map_exec(code_gen_buffer, code_gen_buffer_size);
#endif
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
qemu_get_be32s(f, &env->halted);
qemu_get_be32s(f, &env->interrupt_request);
+ env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
tlb_flush(env, 1);
return 0;
TranslationBlock *tb;
p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
- if (!p->code_bitmap)
- return;
tb = p->first_tb;
while (tb != NULL) {
return -EINVAL;
}
wp = qemu_malloc(sizeof(*wp));
- if (!wp)
- return -ENOMEM;
wp->vaddr = addr;
wp->len_mask = len_mask;
CPUBreakpoint *bp;
bp = qemu_malloc(sizeof(*bp));
- if (!bp)
- return -ENOMEM;
bp->pc = pc;
bp->flags = flags;
#endif
int old_mask;
+ if (mask & CPU_INTERRUPT_EXIT) {
+ env->exit_request = 1;
+ mask &= ~CPU_INTERRUPT_EXIT;
+ }
+
old_mask = env->interrupt_request;
- /* FIXME: This is probably not threadsafe. A different thread could
- be in the middle of a read-modify-write operation. */
env->interrupt_request |= mask;
#if defined(USE_NPTL)
/* FIXME: TB unchaining isn't SMP safe. For now just ignore the
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
#ifndef CONFIG_USER_ONLY
- /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means
- an async event happened and we need to process it. */
if (!can_do_io(env)
- && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) {
+ && (mask & ~old_mask) != 0) {
cpu_abort(env, "Raised interrupt while not in I/O function");
}
#endif
if (kvm_enabled())
kvm_set_phys_mem(start_addr, size, phys_offset);
+ if (phys_offset == IO_MEM_UNASSIGNED) {
+ region_offset = start_addr;
+ }
region_offset &= TARGET_PAGE_MASK;
size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
end_addr = start_addr + (target_phys_addr_t)size;
if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
subpage = subpage_init((addr & TARGET_PAGE_MASK),
&p->phys_offset, IO_MEM_UNASSIGNED,
- 0);
+ addr & TARGET_PAGE_MASK);
subpage_register(subpage, start_addr2, end_addr2,
phys_offset, region_offset);
p->region_offset = 0;
}
addr = phys_ram_alloc_offset;
phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
+
+ if (kvm_enabled())
+ kvm_setup_guest_memory(phys_ram_base + addr, size);
+
return addr;
}
int subpage_memory;
mmio = qemu_mallocz(sizeof(subpage_t));
- if (mmio != NULL) {
- mmio->base = base;
- subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
+
+ mmio->base = base;
+ subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
#if defined(DEBUG_SUBPAGE)
- printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
- mmio, base, TARGET_PAGE_SIZE, subpage_memory);
+ printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
+ mmio, base, TARGET_PAGE_SIZE, subpage_memory);
#endif
- *phys = subpage_memory | IO_MEM_SUBPAGE;
- subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
+ *phys = subpage_memory | IO_MEM_SUBPAGE;
+ subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
region_offset);
- }
return mmio;
}
+static int get_free_io_mem_idx(void)
+{
+ int i;
+
+ for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+ if (!io_mem_used[i]) {
+ io_mem_used[i] = 1;
+ return i;
+ }
+
+ return -1;
+}
+
static void io_mem_init(void)
{
+ int i;
+
cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
- io_mem_nb = 5;
+ for (i=0; i<5; i++)
+ io_mem_used[i] = 1;
io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
watch_mem_write, NULL);
int i, subwidth = 0;
if (io_index <= 0) {
- if (io_mem_nb >= IO_MEM_NB_ENTRIES)
- return -1;
- io_index = io_mem_nb++;
+ io_index = get_free_io_mem_idx();
+ if (io_index == -1)
+ return io_index;
} else {
if (io_index >= IO_MEM_NB_ENTRIES)
return -1;
return (io_index << IO_MEM_SHIFT) | subwidth;
}
+void cpu_unregister_io_memory(int io_table_address)
+{
+ int i;
+ int io_index = io_table_address >> IO_MEM_SHIFT;
+
+ for (i=0;i < 3; i++) {
+ io_mem_read[io_index][i] = unassigned_mem_read[i];
+ io_mem_write[io_index][i] = unassigned_mem_write[i];
+ }
+ io_mem_opaque[io_index] = NULL;
+ io_mem_used[io_index] = 0;
+}
+
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
{
return io_mem_write[io_index >> IO_MEM_SHIFT];
if (is_write) {
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+ target_phys_addr_t addr1 = addr;
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
- addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+ addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
/* XXX: could force cpu_single_env to NULL to avoid
potential bugs */
- if (l >= 4 && ((addr & 3) == 0)) {
+ if (l >= 4 && ((addr1 & 3) == 0)) {
/* 32 bit write access */
val = ldl_p(buf);
- io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+ io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
l = 4;
- } else if (l >= 2 && ((addr & 1) == 0)) {
+ } else if (l >= 2 && ((addr1 & 1) == 0)) {
/* 16 bit write access */
val = lduw_p(buf);
- io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
+ io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
l = 2;
} else {
/* 8 bit write access */
val = ldub_p(buf);
- io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
+ io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
l = 1;
}
} else {
} else {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
+ target_phys_addr_t addr1 = addr;
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
- addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
- if (l >= 4 && ((addr & 3) == 0)) {
+ addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+ if (l >= 4 && ((addr1 & 3) == 0)) {
/* 32 bit read access */
- val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+ val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
stl_p(buf, val);
l = 4;
- } else if (l >= 2 && ((addr & 1) == 0)) {
+ } else if (l >= 2 && ((addr1 & 1) == 0)) {
/* 16 bit read access */
- val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+ val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
stw_p(buf, val);
l = 2;
} else {
/* 8 bit read access */
- val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
+ val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
stb_p(buf, val);
l = 1;
}
MapClient *client = (MapClient *)_client;
LIST_REMOVE(client, link);
+ qemu_free(client);
}
static void cpu_notify_map_clients(void)
while (!LIST_EMPTY(&map_client_list)) {
client = LIST_FIRST(&map_client_list);
client->callback(client->opaque);
- LIST_REMOVE(client, link);
+ cpu_unregister_map_client(client);
}
}