#include "cpu.h"
#include "disas/disas.h"
#include "tcg.h"
-#include "qemu/timer.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
#if defined(CONFIG_USER_ONLY)
#include "qemu.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <libutil.h>
#endif
#endif
+#else
+#include "exec/address-spaces.h"
#endif
#include "exec/cputlb.h"
#include "translate-all.h"
+#include "qemu/timer.h"
//#define DEBUG_TB_INVALIDATE
//#define DEBUG_FLUSH
{
TranslationBlock *tb, *tb_next, *saved_tb;
CPUArchState *env = cpu_single_env;
+ CPUState *cpu = NULL;
tb_page_addr_t tb_start, tb_end;
PageDesc *p;
int n;
/* build code bitmap */
build_page_bitmap(p);
}
+ if (env != NULL) {
+ cpu = ENV_GET_CPU(env);
+ }
/* we remove all the TBs in the range [start, end[ */
/* XXX: see if in some cases it could be faster to invalidate all
/* we need to do that to handle the case where a signal
occurs while doing tb_phys_invalidate() */
saved_tb = NULL;
- if (env) {
- saved_tb = env->current_tb;
- env->current_tb = NULL;
+ if (cpu != NULL) {
+ saved_tb = cpu->current_tb;
+ cpu->current_tb = NULL;
}
tb_phys_invalidate(tb, -1);
- if (env) {
- env->current_tb = saved_tb;
- if (env->interrupt_request && env->current_tb) {
- cpu_interrupt(env, env->interrupt_request);
+ if (cpu != NULL) {
+ cpu->current_tb = saved_tb;
+ if (cpu->interrupt_request && cpu->current_tb) {
+ cpu_interrupt(cpu, cpu->interrupt_request);
}
}
}
/* we generate a block containing just the instruction
modifying the memory. It will ensure that it cannot modify
itself */
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, NULL);
}
#ifdef TARGET_HAS_PRECISE_SMC
TranslationBlock *current_tb = NULL;
CPUArchState *env = cpu_single_env;
+ CPUState *cpu = NULL;
int current_tb_modified = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
if (tb && pc != 0) {
current_tb = tb_find_pc(pc);
}
+ if (env != NULL) {
+ cpu = ENV_GET_CPU(env);
+ }
#endif
while (tb != NULL) {
n = (uintptr_t)tb & 3;
/* we generate a block containing just the instruction
modifying the memory. It will ensure that it cannot modify
itself */
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, puc);
}
/* check whether the given addr is in TCG generated code buffer or not */
bool is_tcg_gen_code(uintptr_t tc_ptr)
{
- /* This can be called during code generation, code_gen_buffer_max_size
+ /* This can be called during code generation, code_gen_buffer_size
is used instead of code_gen_ptr for upper boundary checking */
return (tc_ptr >= (uintptr_t)tcg_ctx.code_gen_buffer &&
tc_ptr < (uintptr_t)(tcg_ctx.code_gen_buffer +
- tcg_ctx.code_gen_buffer_max_size));
+ tcg_ctx.code_gen_buffer_size));
}
#endif
return &tcg_ctx.tb_ctx.tbs[m_max];
}
-static void tb_reset_jump_recursive(TranslationBlock *tb);
-
-static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
-{
- TranslationBlock *tb1, *tb_next, **ptb;
- unsigned int n1;
-
- tb1 = tb->jmp_next[n];
- if (tb1 != NULL) {
- /* find head of list */
- for (;;) {
- n1 = (uintptr_t)tb1 & 3;
- tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
- if (n1 == 2) {
- break;
- }
- tb1 = tb1->jmp_next[n1];
- }
- /* we are now sure now that tb jumps to tb1 */
- tb_next = tb1;
-
- /* remove tb from the jmp_first list */
- ptb = &tb_next->jmp_first;
- for (;;) {
- tb1 = *ptb;
- n1 = (uintptr_t)tb1 & 3;
- tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
- if (n1 == n && tb1 == tb) {
- break;
- }
- ptb = &tb1->jmp_next[n1];
- }
- *ptb = tb->jmp_next[n];
- tb->jmp_next[n] = NULL;
-
- /* suppress the jump to next tb in generated code */
- tb_reset_jump(tb, n);
-
- /* suppress jumps in the tb on which we could have jumped */
- tb_reset_jump_recursive(tb_next);
- }
-}
-
-static void tb_reset_jump_recursive(TranslationBlock *tb)
-{
- tb_reset_jump_recursive2(tb, 0);
- tb_reset_jump_recursive2(tb, 1);
-}
-
#if defined(TARGET_HAS_ICE) && !defined(CONFIG_USER_ONLY)
void tb_invalidate_phys_addr(hwaddr addr)
{
ram_addr_t ram_addr;
MemoryRegionSection *section;
+ hwaddr l = 1;
- section = phys_page_find(address_space_memory.dispatch,
- addr >> TARGET_PAGE_BITS);
+ section = address_space_translate(&address_space_memory, addr, &addr, &l, false);
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)
- + memory_region_section_addr(section, addr);
+ + addr;
tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
}
#endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */
-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
- emulation this often isn't actually as bad as it sounds. Often
- signals are used primarily to interrupt blocking syscalls. */
- TranslationBlock *tb;
- static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
-
- spin_lock(&interrupt_lock);
- tb = env->current_tb;
- /* if the cpu is currently executing code, we must unlink it and
- all the potentially executing TB */
- if (tb) {
- env->current_tb = NULL;
- tb_reset_jump_recursive(tb);
- }
- spin_unlock(&interrupt_lock);
-}
-
void tb_check_watchpoint(CPUArchState *env)
{
TranslationBlock *tb;
#ifndef CONFIG_USER_ONLY
/* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUArchState *env, int mask)
+static void tcg_handle_interrupt(CPUState *cpu, int mask)
{
- CPUState *cpu = ENV_GET_CPU(env);
+ CPUArchState *env = cpu->env_ptr;
int old_mask;
- old_mask = env->interrupt_request;
- env->interrupt_request |= mask;
+ old_mask = cpu->interrupt_request;
+ cpu->interrupt_request |= mask;
/*
* If called from iothread context, wake the target cpu in
cpu_abort(env, "Raised interrupt while not in I/O function");
}
} else {
- cpu_unlink_tb(env);
+ cpu->tcg_exit_req = 1;
}
}
#else /* CONFIG_USER_ONLY */
-void cpu_interrupt(CPUArchState *env, int mask)
+void cpu_interrupt(CPUState *cpu, int mask)
{
- env->interrupt_request |= mask;
- cpu_unlink_tb(env);
+ cpu->interrupt_request |= mask;
+ cpu->tcg_exit_req = 1;
}
/*