Explictly NULL it on CPU reset since it was located before breakpoints.
Change vapic_report_tpr_access() argument to CPUState. This also
resolves the use of void* for cpu.h independence.
Change vAPIC patch_instruction() argument to X86CPU.
Signed-off-by: Andreas Färber <afaerber@suse.de>
void cpu_loop_exit(CPUArchState *env)
{
void cpu_loop_exit(CPUArchState *env)
{
- env->current_tb = NULL;
+ CPUState *cpu = ENV_GET_CPU(env);
+
+ cpu->current_tb = NULL;
longjmp(env->jmp_env, 1);
}
longjmp(env->jmp_env, 1);
}
static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
TranslationBlock *orig_tb)
{
static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
TranslationBlock *orig_tb)
{
+ CPUState *cpu = ENV_GET_CPU(env);
tcg_target_ulong next_tb;
TranslationBlock *tb;
tcg_target_ulong next_tb;
TranslationBlock *tb;
tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
max_cycles);
tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
max_cycles);
/* execute the generated code */
next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
/* execute the generated code */
next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
if ((next_tb & 3) == 2) {
/* Restore PC. This may happen if async event occurs before
if ((next_tb & 3) == 2) {
/* Restore PC. This may happen if async event occurs before
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
starting execution if there is a pending interrupt. */
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
starting execution if there is a pending interrupt. */
barrier();
if (likely(!cpu->exit_request)) {
tc_ptr = tb->tc_ptr;
barrier();
if (likely(!cpu->exit_request)) {
tc_ptr = tb->tc_ptr;
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
} /* for(;;) */
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
} /* for(;;) */
*/
void tlb_flush(CPUArchState *env, int flush_global)
{
*/
void tlb_flush(CPUArchState *env, int flush_global)
{
+ CPUState *cpu = ENV_GET_CPU(env);
int i;
#if defined(DEBUG_TLB)
int i;
#if defined(DEBUG_TLB)
#endif
/* must reset current TB so that interrupts cannot modify the
links while we are modifying them */
#endif
/* must reset current TB so that interrupts cannot modify the
links while we are modifying them */
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
for (i = 0; i < CPU_TLB_SIZE; i++) {
int mmu_idx;
for (i = 0; i < CPU_TLB_SIZE; i++) {
int mmu_idx;
void tlb_flush_page(CPUArchState *env, target_ulong addr)
{
void tlb_flush_page(CPUArchState *env, target_ulong addr)
{
+ CPUState *cpu = ENV_GET_CPU(env);
}
/* must reset current TB so that interrupts cannot modify the
links while we are modifying them */
}
/* must reset current TB so that interrupts cannot modify the
links while we are modifying them */
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
addr &= TARGET_PAGE_MASK;
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
addr &= TARGET_PAGE_MASK;
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
- vapic_report_tpr_access(s->vapic, &s->cpu->env, ip, access);
+ vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
}
void apic_report_irq_delivered(int delivered)
}
void apic_report_irq_delivered(int delivered)
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, hwaddr paddr);
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, hwaddr paddr);
-void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
+void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip,
TPRAccess access);
#endif /* !QEMU_APIC_INTERNAL_H */
TPRAccess access);
#endif /* !QEMU_APIC_INTERNAL_H */
cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
}
cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
}
-static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip)
+static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
+ CPUState *cs = CPU(cpu);
+ CPUX86State *env = &cpu->env;
VAPICHandlers *handlers;
uint8_t opcode[2];
uint32_t imm32;
VAPICHandlers *handlers;
uint8_t opcode[2];
uint32_t imm32;
resume_all_vcpus();
if (!kvm_enabled()) {
resume_all_vcpus();
if (!kvm_enabled()) {
- env->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, NULL);
}
}
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, NULL);
}
}
-void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
+void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
TPRAccess access)
{
VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
TPRAccess access)
{
VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
- CPUX86State *env = cpu;
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
cpu_synchronize_state(env);
cpu_synchronize_state(env);
if (vapic_enable(s, env) < 0) {
return;
}
if (vapic_enable(s, env) < 0) {
return;
}
- patch_instruction(s, env, ip);
+ patch_instruction(s, cpu, ip);
}
typedef struct VAPICEnableTPRReporting {
}
typedef struct VAPICEnableTPRReporting {
#define CPU_TEMP_BUF_NLONGS 128
#define CPU_COMMON \
#define CPU_TEMP_BUF_NLONGS 128
#define CPU_COMMON \
- struct TranslationBlock *current_tb; /* currently executing TB */ \
/* soft mmu support */ \
/* in order to avoid passing too many arguments to the MMIO \
helpers, we store some rarely used information in the CPU \
/* soft mmu support */ \
/* in order to avoid passing too many arguments to the MMIO \
helpers, we store some rarely used information in the CPU \
instruction of a TB so that interrupts take effect immediately. */
static inline int can_do_io(CPUArchState *env)
{
instruction of a TB so that interrupts take effect immediately. */
static inline int can_do_io(CPUArchState *env)
{
+ CPUState *cpu = ENV_GET_CPU(env);
+
if (!use_icount) {
return 1;
}
/* If not executing code then assume we are ok. */
if (!use_icount) {
return 1;
}
/* If not executing code then assume we are ok. */
- if (!env->current_tb) {
+ if (cpu->current_tb == NULL) {
return 1;
}
return env->can_do_io != 0;
return 1;
}
return env->can_do_io != 0;
* @created: Indicates whether the CPU thread has been successfully created.
* @stop: Indicates a pending stop request.
* @stopped: Indicates the CPU has been artificially stopped.
* @created: Indicates whether the CPU thread has been successfully created.
* @stop: Indicates a pending stop request.
* @stopped: Indicates the CPU has been artificially stopped.
+ * @current_tb: Currently executing TB.
* @kvm_fd: vCPU file descriptor for KVM.
*
* State of one CPU core or thread.
* @kvm_fd: vCPU file descriptor for KVM.
*
* State of one CPU core or thread.
bool stopped;
volatile sig_atomic_t exit_request;
bool stopped;
volatile sig_atomic_t exit_request;
+ struct TranslationBlock *current_tb;
+
int kvm_fd;
bool kvm_vcpu_dirty;
struct KVMState *kvm_state;
int kvm_fd;
bool kvm_vcpu_dirty;
struct KVMState *kvm_state;
static void cpu_common_reset(CPUState *cpu)
{
cpu->exit_request = 0;
static void cpu_common_reset(CPUState *cpu)
{
cpu->exit_request = 0;
+ cpu->current_tb = NULL;
}
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
}
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
{
TranslationBlock *tb, *tb_next, *saved_tb;
CPUArchState *env = cpu_single_env;
{
TranslationBlock *tb, *tb_next, *saved_tb;
CPUArchState *env = cpu_single_env;
tb_page_addr_t tb_start, tb_end;
PageDesc *p;
int n;
tb_page_addr_t tb_start, tb_end;
PageDesc *p;
int n;
/* build code bitmap */
build_page_bitmap(p);
}
/* 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 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;
/* 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);
}
tb_phys_invalidate(tb, -1);
- if (env) {
- env->current_tb = saved_tb;
- if (env->interrupt_request && env->current_tb) {
+ if (cpu != NULL) {
+ cpu->current_tb = saved_tb;
+ if (env && env->interrupt_request && cpu->current_tb) {
cpu_interrupt(env, env->interrupt_request);
}
}
cpu_interrupt(env, env->interrupt_request);
}
}
/* we generate a block containing just the instruction
modifying the memory. It will ensure that it cannot modify
itself */
/* 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);
}
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;
#ifdef TARGET_HAS_PRECISE_SMC
TranslationBlock *current_tb = NULL;
CPUArchState *env = cpu_single_env;
int current_tb_modified = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
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 (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;
#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 */
/* 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);
}
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, puc);
}
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. */
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. */
+ CPUState *cpu = ENV_GET_CPU(env);
TranslationBlock *tb;
static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
spin_lock(&interrupt_lock);
TranslationBlock *tb;
static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
spin_lock(&interrupt_lock);
/* if the cpu is currently executing code, we must unlink it and
all the potentially executing TB */
if (tb) {
/* if the cpu is currently executing code, we must unlink it and
all the potentially executing TB */
if (tb) {
- env->current_tb = NULL;
+ cpu->current_tb = NULL;
tb_reset_jump_recursive(tb);
}
spin_unlock(&interrupt_lock);
tb_reset_jump_recursive(tb);
}
spin_unlock(&interrupt_lock);