#endif
-CPUState *first_cpu;
+CPUArchState *first_cpu;
/* current CPU in the current thread. It is only valid inside
cpu_exec() */
-DEFINE_TLS(CPUState *,cpu_single_env);
+DEFINE_TLS(CPUArchState *,cpu_single_env);
/* 0 = Do not count executed instructions.
1 = Precise instruction counting.
2 = Adaptive rate instruction counting. */
}
static void tlb_protect_code(ram_addr_t ram_addr);
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
target_ulong vaddr);
#define mmap_lock() do { } while(0)
#define mmap_unlock() do { } while(0)
static int cpu_common_post_load(void *opaque, int version_id)
{
- CPUState *env = opaque;
+ CPUArchState *env = opaque;
/* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
version_id is increased. */
.minimum_version_id_old = 1,
.post_load = cpu_common_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT32(halted, CPUState),
- VMSTATE_UINT32(interrupt_request, CPUState),
+ VMSTATE_UINT32(halted, CPUArchState),
+ VMSTATE_UINT32(interrupt_request, CPUArchState),
VMSTATE_END_OF_LIST()
}
};
#endif
-CPUState *qemu_get_cpu(int cpu)
+CPUArchState *qemu_get_cpu(int cpu)
{
- CPUState *env = first_cpu;
+ CPUArchState *env = first_cpu;
while (env) {
if (env->cpu_index == cpu)
return env;
}
-void cpu_exec_init(CPUState *env)
+void cpu_exec_init(CPUArchState *env)
{
- CPUState **penv;
+ CPUArchState **penv;
int cpu_index;
#if defined(CONFIG_USER_ONLY)
/* flush all the translation blocks */
/* XXX: tb_flush is currently not thread safe */
-void tb_flush(CPUState *env1)
+void tb_flush(CPUArchState *env1)
{
- CPUState *env;
+ CPUArchState *env;
#if defined(DEBUG_FLUSH)
printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
(unsigned long)(code_gen_ptr - code_gen_buffer),
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
{
- CPUState *env;
+ CPUArchState *env;
PageDesc *p;
unsigned int h, n1;
tb_page_addr_t phys_pc;
}
}
-TranslationBlock *tb_gen_code(CPUState *env,
+TranslationBlock *tb_gen_code(CPUArchState *env,
target_ulong pc, target_ulong cs_base,
int flags, int cflags)
{
int is_cpu_write_access)
{
TranslationBlock *tb, *tb_next, *saved_tb;
- CPUState *env = cpu_single_env;
+ CPUArchState *env = cpu_single_env;
tb_page_addr_t tb_start, tb_end;
PageDesc *p;
int n;
int n;
#ifdef TARGET_HAS_PRECISE_SMC
TranslationBlock *current_tb = NULL;
- CPUState *env = cpu_single_env;
+ CPUArchState *env = cpu_single_env;
int current_tb_modified = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
#if defined(TARGET_HAS_ICE)
#if defined(CONFIG_USER_ONLY)
-static void breakpoint_invalidate(CPUState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
tb_invalidate_phys_page_range(pc, pc + 1, 0);
}
#else
-static void breakpoint_invalidate(CPUState *env, target_ulong pc)
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
target_phys_addr_t addr;
ram_addr_t ram_addr;
#endif /* TARGET_HAS_ICE */
#if defined(CONFIG_USER_ONLY)
-void cpu_watchpoint_remove_all(CPUState *env, int mask)
+void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
{
}
-int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
int flags, CPUWatchpoint **watchpoint)
{
return -ENOSYS;
}
#else
/* Add a watchpoint. */
-int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
int flags, CPUWatchpoint **watchpoint)
{
target_ulong len_mask = ~(len - 1);
}
/* Remove a specific watchpoint. */
-int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
+int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
int flags)
{
target_ulong len_mask = ~(len - 1);
}
/* Remove a specific watchpoint by reference. */
-void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
+void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
{
QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
}
/* Remove all matching watchpoints. */
-void cpu_watchpoint_remove_all(CPUState *env, int mask)
+void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
{
CPUWatchpoint *wp, *next;
#endif
/* Add a breakpoint. */
-int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
+int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
CPUBreakpoint **breakpoint)
{
#if defined(TARGET_HAS_ICE)
}
/* Remove a specific breakpoint. */
-int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
+int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
{
#if defined(TARGET_HAS_ICE)
CPUBreakpoint *bp;
}
/* Remove a specific breakpoint by reference. */
-void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
+void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
{
#if defined(TARGET_HAS_ICE)
QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
}
/* Remove all matching breakpoints. */
-void cpu_breakpoint_remove_all(CPUState *env, int mask)
+void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
{
#if defined(TARGET_HAS_ICE)
CPUBreakpoint *bp, *next;
/* enable or disable single step mode. EXCP_DEBUG is returned by the
CPU loop after each instruction */
-void cpu_single_step(CPUState *env, int enabled)
+void cpu_single_step(CPUArchState *env, int enabled)
{
#if defined(TARGET_HAS_ICE)
if (env->singlestep_enabled != enabled) {
cpu_set_log(loglevel);
}
-static void cpu_unlink_tb(CPUState *env)
+static void cpu_unlink_tb(CPUArchState *env)
{
/* FIXME: TB unchaining isn't SMP safe. For now just ignore the
problem and hope the cpu will stop of its own accord. For userspace
#ifndef CONFIG_USER_ONLY
/* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUState *env, int mask)
+static void tcg_handle_interrupt(CPUArchState *env, int mask)
{
int old_mask;
#else /* CONFIG_USER_ONLY */
-void cpu_interrupt(CPUState *env, int mask)
+void cpu_interrupt(CPUArchState *env, int mask)
{
env->interrupt_request |= mask;
cpu_unlink_tb(env);
}
#endif /* CONFIG_USER_ONLY */
-void cpu_reset_interrupt(CPUState *env, int mask)
+void cpu_reset_interrupt(CPUArchState *env, int mask)
{
env->interrupt_request &= ~mask;
}
-void cpu_exit(CPUState *env)
+void cpu_exit(CPUArchState *env)
{
env->exit_request = 1;
cpu_unlink_tb(env);
return mask;
}
-void cpu_abort(CPUState *env, const char *fmt, ...)
+void cpu_abort(CPUArchState *env, const char *fmt, ...)
{
va_list ap;
va_list ap2;
abort();
}
-CPUState *cpu_copy(CPUState *env)
+CPUArchState *cpu_copy(CPUArchState *env)
{
- CPUState *new_env = cpu_init(env->cpu_model_str);
- CPUState *next_cpu = new_env->next_cpu;
+ CPUArchState *new_env = cpu_init(env->cpu_model_str);
+ CPUArchState *next_cpu = new_env->next_cpu;
int cpu_index = new_env->cpu_index;
#if defined(TARGET_HAS_ICE)
CPUBreakpoint *bp;
CPUWatchpoint *wp;
#endif
- memcpy(new_env, env, sizeof(CPUState));
+ memcpy(new_env, env, sizeof(CPUArchState));
/* Preserve chaining and index. */
new_env->next_cpu = next_cpu;
#if !defined(CONFIG_USER_ONLY)
-static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
+static inline void tlb_flush_jmp_cache(CPUArchState *env, target_ulong addr)
{
unsigned int i;
* entries from the TLB at any time, so flushing more entries than
* required is only an efficiency issue, not a correctness issue.
*/
-void tlb_flush(CPUState *env, int flush_global)
+void tlb_flush(CPUArchState *env, int flush_global)
{
int i;
}
}
-void tlb_flush_page(CPUState *env, target_ulong addr)
+void tlb_flush_page(CPUArchState *env, target_ulong addr)
{
int i;
int mmu_idx;
/* update the TLB so that writes in physical page 'phys_addr' are no longer
tested for self modifying code */
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
target_ulong vaddr)
{
cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
}
+static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
+{
+ return (tlbe->addr_write & (TLB_INVALID_MASK|TLB_MMIO|TLB_NOTDIRTY)) == 0;
+}
+
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
unsigned long start, unsigned long length)
{
unsigned long addr;
- if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+ if (tlb_is_dirty_ram(tlb_entry)) {
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
if ((addr - start) < length) {
- tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
+ tlb_entry->addr_write |= TLB_NOTDIRTY;
}
}
}
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
int dirty_flags)
{
- CPUState *env;
+ CPUArchState *env;
unsigned long length, start1;
int i;
ram_addr_t ram_addr;
void *p;
- if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+ if (tlb_is_dirty_ram(tlb_entry)) {
p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
+ tlb_entry->addend);
ram_addr = qemu_ram_addr_from_host_nofail(p);
}
/* update the TLB according to the current state of the dirty bits */
-void cpu_tlb_update_dirty(CPUState *env)
+void cpu_tlb_update_dirty(CPUArchState *env)
{
int i;
int mmu_idx;
/* update the TLB corresponding to virtual page vaddr
so that it is no longer dirty */
-static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
+static inline void tlb_set_dirty(CPUArchState *env, target_ulong vaddr)
{
int i;
int mmu_idx;
/* Our TLB does not support large pages, so remember the area covered by
large pages and trigger a full TLB flush if these are invalidated. */
-static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
+static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
target_ulong size)
{
target_ulong mask = ~(size - 1);
/* Add a new TLB entry. At most one entry for a given virtual address
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
supplied size is only used by tlb_flush_page. */
-void tlb_set_page(CPUState *env, target_ulong vaddr,
+void tlb_set_page(CPUArchState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int mmu_idx, target_ulong size)
{
#else
-void tlb_flush(CPUState *env, int flush_global)
+void tlb_flush(CPUArchState *env, int flush_global)
{
}
-void tlb_flush_page(CPUState *env, target_ulong addr)
+void tlb_flush_page(CPUArchState *env, target_ulong addr)
{
}
return 0;
}
-static inline void tlb_set_dirty(CPUState *env,
+static inline void tlb_set_dirty(CPUArchState *env,
unsigned long addr, target_ulong vaddr)
{
}
/* Generate a debug exception if a watchpoint has been hit. */
static void check_watchpoint(int offset, int len_mask, int flags)
{
- CPUState *env = cpu_single_env;
+ CPUArchState *env = cpu_single_env;
target_ulong pc, cs_base;
TranslationBlock *tb;
target_ulong vaddr;
static void core_commit(MemoryListener *listener)
{
- CPUState *env;
+ CPUArchState *env;
/* since each CPU stores ram addresses in its TLB cache, we must
reset the modified entries */
/* physical memory access (slow version, mainly for debug) */
#if defined(CONFIG_USER_ONLY)
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
uint8_t *buf, int len, int is_write)
{
int l, flags;
}
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(section->mr->ram_addr)
- + section_addr(section, addr);
+ ptr = qemu_get_ram_ptr(section->mr->ram_addr
+ + section_addr(section, addr));
memcpy(buf, ptr, l);
qemu_put_ram_ptr(ptr);
}
}
/* virtual memory access for debug (includes writing to ROM) */
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
uint8_t *buf, int len, int is_write)
{
int l;
/* in deterministic execution mode, instructions doing device I/Os
must be at the end of the TB */
-void cpu_io_recompile(CPUState *env, void *retaddr)
+void cpu_io_recompile(CPUArchState *env, void *retaddr)
{
TranslationBlock *tb;
uint32_t n, cflags;
/* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it
is the offset relative to phys_ram_base */
-tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
+tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
{
int mmu_idx, page_index, pd;
void *p;
mmu_idx = cpu_mmu_index(env1);
if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
(addr & TARGET_PAGE_MASK))) {
+#ifdef CONFIG_TCG_PASS_AREG0
+ cpu_ldub_code(env1, addr);
+#else
ldub_code(addr);
+#endif
}
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(pd);
if (mr != &io_mem_ram && mr != &io_mem_rom
- && mr != &io_mem_notdirty && !mr->rom_device) {
+ && mr != &io_mem_notdirty && !mr->rom_device
+ && mr != &io_mem_watch) {
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
#else