@@ -517,9 +517,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
#else
if (replay_exception()) {
CPUClass *cc = CPU_GET_CLASS(cpu);
- qemu_mutex_lock_iothread();
cc->do_interrupt(cpu);
- qemu_mutex_unlock_iothread();
cpu->exception_index = -1;
if (unlikely(cpu->singlestep_enabled)) {
@@ -217,7 +217,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = alpha_cpu_class_by_name;
cc->has_work = alpha_cpu_has_work;
- cc->do_interrupt = alpha_cpu_do_interrupt_locked;
+ cc->do_interrupt = alpha_cpu_do_interrupt;
cc->cpu_exec_interrupt = alpha_cpu_exec_interrupt;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
@@ -276,7 +276,7 @@ struct AlphaCPU {
extern const VMStateDescription vmstate_alpha_cpu;
#endif
-void alpha_cpu_do_interrupt_locked(CPUState *cpu);
+void alpha_cpu_do_interrupt(CPUState *cpu);
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -295,7 +295,7 @@ bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
}
#endif /* USER_ONLY */
-void alpha_cpu_do_interrupt_locked(CPUState *cs)
+static void alpha_cpu_do_interrupt_locked(CPUState *cs)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
@@ -407,6 +407,13 @@ void alpha_cpu_do_interrupt_locked(CPUState *cs)
#endif /* !USER_ONLY */
}
+void alpha_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ alpha_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
@@ -2224,7 +2224,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->do_interrupt = arm_cpu_do_interrupt_locked;
+ cc->do_interrupt = arm_cpu_do_interrupt;
acc->do_interrupt_locked = arm_cpu_do_interrupt_locked;
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
cc->asidx_from_attrs = arm_asidx_from_attrs;
@@ -991,7 +991,9 @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
extern const VMStateDescription vmstate_arm_cpu;
#endif
+void arm_cpu_do_interrupt(CPUState *cpu);
void arm_cpu_do_interrupt_locked(CPUState *cpu);
+void arm_v7m_cpu_do_interrupt(CPUState *cpu);
void arm_v7m_cpu_do_interrupt_locked(CPUState *cpu);
bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
@@ -601,7 +601,7 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
acc->info = data;
#ifndef CONFIG_USER_ONLY
- cc->do_interrupt = arm_v7m_cpu_do_interrupt_locked;
+ cc->do_interrupt = arm_cpu_do_interrupt;
acc->do_interrupt_locked = arm_v7m_cpu_do_interrupt_locked;
#endif
@@ -9840,6 +9840,14 @@ static void handle_semihosting(CPUState *cs)
}
#endif
+void arm_cpu_do_interrupt(CPUState *cs)
+{
+ ARMCPUClass *acc = ARM_CPU_GET_CLASS(cs);
+ qemu_mutex_lock_iothread();
+ acc->do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
/* Handle a CPU exception for A and R profile CPUs.
* Do any appropriate logging, handle PSCI calls, and then hand off
* to the AArch64-entry or AArch32-entry function depending on the
@@ -197,7 +197,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = avr_cpu_class_by_name;
cc->has_work = avr_cpu_has_work;
- cc->do_interrupt = avr_cpu_do_interrupt_locked;
+ cc->do_interrupt = avr_cpu_do_interrupt;
cc->cpu_exec_interrupt = avr_cpu_exec_interrupt;
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
@@ -156,7 +156,7 @@ typedef struct AVRCPU {
extern const struct VMStateDescription vms_avr_cpu;
-void avr_cpu_do_interrupt_locked(CPUState *cpu);
+void avr_cpu_do_interrupt(CPUState *cpu);
bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -24,17 +24,18 @@
#include "exec/address-spaces.h"
#include "exec/helper-proto.h"
+static void avr_cpu_do_interrupt_locked(CPUState *cs);
+
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
bool ret = false;
- CPUClass *cc = CPU_GET_CLASS(cs);
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
if (interrupt_request & CPU_INTERRUPT_RESET) {
if (cpu_interrupts_enabled(env)) {
cs->exception_index = EXCP_RESET;
- cc->do_interrupt(cs);
+ avr_cpu_do_interrupt_locked(cs);
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
@@ -45,7 +46,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
int index = ctz32(env->intsrc);
cs->exception_index = EXCP_INT(index);
- cc->do_interrupt(cs);
+ avr_cpu_do_interrupt_locked(cs);
env->intsrc &= env->intsrc - 1; /* clear the interrupt */
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
@@ -56,7 +57,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
return ret;
}
-void avr_cpu_do_interrupt_locked(CPUState *cs)
+static void avr_cpu_do_interrupt_locked(CPUState *cs)
{
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
@@ -89,6 +90,13 @@ void avr_cpu_do_interrupt_locked(CPUState *cs)
cs->exception_index = -1;
}
+void avr_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ avr_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
int avr_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf,
int len, bool is_write)
{
@@ -199,7 +199,6 @@ static void crisv8_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 8;
- cc->do_interrupt = crisv10_cpu_do_interrupt_locked;
ccc->do_interrupt_locked = crisv10_cpu_do_interrupt_locked;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
cc->tcg_initialize = cris_initialize_crisv10_tcg;
@@ -211,7 +210,6 @@ static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 9;
- cc->do_interrupt = crisv10_cpu_do_interrupt_locked;
ccc->do_interrupt_locked = crisv10_cpu_do_interrupt_locked;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
cc->tcg_initialize = cris_initialize_crisv10_tcg;
@@ -223,7 +221,6 @@ static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 10;
- cc->do_interrupt = crisv10_cpu_do_interrupt_locked;
ccc->do_interrupt_locked = crisv10_cpu_do_interrupt_locked;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
cc->tcg_initialize = cris_initialize_crisv10_tcg;
@@ -235,7 +232,6 @@ static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 11;
- cc->do_interrupt = crisv10_cpu_do_interrupt_locked;
ccc->do_interrupt_locked = crisv10_cpu_do_interrupt_locked;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
cc->tcg_initialize = cris_initialize_crisv10_tcg;
@@ -247,7 +243,6 @@ static void crisv17_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 17;
- cc->do_interrupt = crisv10_cpu_do_interrupt_locked;
ccc->do_interrupt_locked = crisv10_cpu_do_interrupt_locked;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
cc->tcg_initialize = cris_initialize_crisv10_tcg;
@@ -273,7 +268,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = cris_cpu_class_by_name;
cc->has_work = cris_cpu_has_work;
- cc->do_interrupt = cris_cpu_do_interrupt_locked;
+ cc->do_interrupt = cris_cpu_do_interrupt;
ccc->do_interrupt_locked = cris_cpu_do_interrupt_locked;
cc->cpu_exec_interrupt = cris_cpu_exec_interrupt;
cc->dump_state = cris_cpu_dump_state;
@@ -187,6 +187,7 @@ struct CRISCPU {
extern const VMStateDescription vmstate_cris_cpu;
#endif
+void cris_cpu_do_interrupt(CPUState *cpu);
void cris_cpu_do_interrupt_locked(CPUState *cpu);
void crisv10_cpu_do_interrupt_locked(CPUState *cpu);
bool cris_cpu_exec_interrupt(CPUState *cpu, int int_req);
@@ -38,6 +38,14 @@
#define D_LOG(...) do { } while (0)
#endif
+void cris_cpu_do_interrupt(CPUState *cs)
+{
+ CRISCPUClass *acc = CRIS_CPU_GET_CLASS(cs);
+ qemu_mutex_lock_iothread();
+ acc->do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
#if defined(CONFIG_USER_ONLY)
void cris_cpu_do_interrupt_locked(CPUState *cs)
@@ -139,7 +139,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = hppa_cpu_class_by_name;
cc->has_work = hppa_cpu_has_work;
- cc->do_interrupt = hppa_cpu_do_interrupt_locked;
+ cc->do_interrupt = hppa_cpu_do_interrupt;
cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt;
cc->dump_state = hppa_cpu_dump_state;
cc->set_pc = hppa_cpu_set_pc;
@@ -323,7 +323,7 @@ int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-void hppa_cpu_do_interrupt_locked(CPUState *cpu);
+void hppa_cpu_do_interrupt(CPUState *cpu);
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
void hppa_cpu_dump_state(CPUState *cs, FILE *f, int);
bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
@@ -90,7 +90,7 @@ void HELPER(write_eiem)(CPUHPPAState *env, target_ureg val)
}
#endif /* !CONFIG_USER_ONLY */
-void hppa_cpu_do_interrupt_locked(CPUState *cs)
+static void hppa_cpu_do_interrupt_locked(CPUState *cs)
{
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
@@ -246,6 +246,13 @@ void hppa_cpu_do_interrupt_locked(CPUState *cs)
cs->exception_index = -1;
}
+void hppa_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ hppa_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
#ifndef CONFIG_USER_ONLY
@@ -7297,7 +7297,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->parse_features = x86_cpu_parse_featurestr;
cc->has_work = x86_cpu_has_work;
#ifdef CONFIG_TCG
- cc->do_interrupt = x86_cpu_do_interrupt_locked;
+ cc->do_interrupt = x86_cpu_do_interrupt;
cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
#endif
cc->dump_state = x86_cpu_dump_state;
@@ -1770,7 +1770,7 @@ extern VMStateDescription vmstate_x86_cpu;
* x86_cpu_do_interrupt:
* @cpu: vCPU the interrupt is to be handled by.
*/
-void x86_cpu_do_interrupt_locked(CPUState *cpu);
+void x86_cpu_do_interrupt(CPUState *cpu);
bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
@@ -1280,7 +1280,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
#endif
}
-void x86_cpu_do_interrupt_locked(CPUState *cs)
+static void x86_cpu_do_interrupt_locked(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@@ -1310,6 +1310,13 @@ void x86_cpu_do_interrupt_locked(CPUState *cs)
#endif
}
+void x86_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ x86_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw)
{
do_interrupt_all(env_archcpu(env), intno, 0, 0, 0, is_hw);
@@ -222,7 +222,7 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = lm32_cpu_class_by_name;
cc->has_work = lm32_cpu_has_work;
- cc->do_interrupt = lm32_cpu_do_interrupt_locked;
+ cc->do_interrupt = lm32_cpu_do_interrupt;
cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt;
cc->dump_state = lm32_cpu_dump_state;
cc->set_pc = lm32_cpu_set_pc;
@@ -198,7 +198,7 @@ struct LM32CPU {
extern const VMStateDescription vmstate_lm32_cpu;
#endif
-void lm32_cpu_do_interrupt_locked(CPUState *cpu);
+void lm32_cpu_do_interrupt(CPUState *cpu);
bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req);
void lm32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -148,7 +148,7 @@ void lm32_debug_excp_handler(CPUState *cs)
}
}
-void lm32_cpu_do_interrupt_locked(CPUState *cs)
+static void lm32_cpu_do_interrupt_locked(CPUState *cs)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;
@@ -198,6 +198,13 @@ void lm32_cpu_do_interrupt_locked(CPUState *cs)
}
}
+void lm32_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ lm32_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool lm32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
LM32CPU *cpu = LM32_CPU(cs);
@@ -277,7 +277,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->class_by_name = m68k_cpu_class_by_name;
cc->has_work = m68k_cpu_has_work;
- cc->do_interrupt = m68k_cpu_do_interrupt_locked;
+ cc->do_interrupt = m68k_cpu_do_interrupt;
cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
@@ -164,7 +164,7 @@ struct M68kCPU {
};
-void m68k_cpu_do_interrupt_locked(CPUState *cpu);
+void m68k_cpu_do_interrupt(CPUState *cpu);
bool m68k_cpu_exec_interrupt(CPUState *cpu, int int_req);
void m68k_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -25,7 +25,7 @@
#if defined(CONFIG_USER_ONLY)
-void m68k_cpu_do_interrupt_locked(CPUState *cs)
+static void m68k_cpu_do_interrupt_locked(CPUState *cs)
{
cs->exception_index = -1;
}
@@ -443,7 +443,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
cf_interrupt_all(env, is_hw);
}
-void m68k_cpu_do_interrupt_locked(CPUState *cs)
+static void m68k_cpu_do_interrupt_locked(CPUState *cs)
{
M68kCPU *cpu = M68K_CPU(cs);
CPUM68KState *env = &cpu->env;
@@ -504,6 +504,13 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
}
#endif
+void m68k_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ m68k_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
M68kCPU *cpu = M68K_CPU(cs);
@@ -316,7 +316,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = mb_cpu_class_by_name;
cc->has_work = mb_cpu_has_work;
- cc->do_interrupt = mb_cpu_do_interrupt_locked;
+ cc->do_interrupt = mb_cpu_do_interrupt;
cc->cpu_exec_interrupt = mb_cpu_exec_interrupt;
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
@@ -315,7 +315,7 @@ struct MicroBlazeCPU {
};
-void mb_cpu_do_interrupt_locked(CPUState *cs);
+void mb_cpu_do_interrupt(CPUState *cs);
bool mb_cpu_exec_interrupt(CPUState *cs, int int_req);
void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -28,7 +28,7 @@
#if defined(CONFIG_USER_ONLY)
-void mb_cpu_do_interrupt_locked(CPUState *cs)
+static void mb_cpu_do_interrupt_locked(CPUState *cs)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
@@ -108,7 +108,7 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
-void mb_cpu_do_interrupt_locked(CPUState *cs)
+static void mb_cpu_do_interrupt_locked(CPUState *cs)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
@@ -287,6 +287,13 @@ hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
#endif
+void mb_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ mb_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
@@ -196,7 +196,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->class_by_name = mips_cpu_class_by_name;
cc->has_work_with_iothread_lock = mips_cpu_has_work;
- cc->do_interrupt = mips_cpu_do_interrupt_locked;
+ cc->do_interrupt = mips_cpu_do_interrupt;
cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
@@ -1083,7 +1083,7 @@ static inline void set_badinstr_registers(CPUMIPSState *env)
}
#endif
-void mips_cpu_do_interrupt_locked(CPUState *cs)
+static void mips_cpu_do_interrupt_locked(CPUState *cs)
{
#if !defined(CONFIG_USER_ONLY)
MIPSCPU *cpu = MIPS_CPU(cs);
@@ -1398,6 +1398,13 @@ void mips_cpu_do_interrupt_locked(CPUState *cs)
cs->exception_index = EXCP_NONE;
}
+void mips_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ mips_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
@@ -80,7 +80,7 @@ enum CPUMIPSMSADataFormat {
DF_DOUBLE
};
-void mips_cpu_do_interrupt_locked(CPUState *cpu);
+void mips_cpu_do_interrupt(CPUState *cpu);
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -192,7 +192,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = nios2_cpu_class_by_name;
cc->has_work = nios2_cpu_has_work;
- cc->do_interrupt = nios2_cpu_do_interrupt_locked;
+ cc->do_interrupt = nios2_cpu_do_interrupt;
cc->cpu_exec_interrupt = nios2_cpu_exec_interrupt;
cc->dump_state = nios2_cpu_dump_state;
cc->set_pc = nios2_cpu_set_pc;
@@ -195,6 +195,7 @@ typedef struct Nios2CPU {
void nios2_tcg_init(void);
+void nios2_cpu_do_interrupt(CPUState *cs);
void nios2_cpu_do_interrupt_locked(CPUState *cs);
int cpu_nios2_signal_handler(int host_signum, void *pinfo, void *puc);
void dump_mmu(CPUNios2State *env);
@@ -312,3 +312,12 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
#endif /* !CONFIG_USER_ONLY */
+
+void nios2_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ nios2_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
+
@@ -154,7 +154,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = openrisc_cpu_class_by_name;
cc->has_work = openrisc_cpu_has_work;
- cc->do_interrupt = openrisc_cpu_do_interrupt_locked;
+ cc->do_interrupt = openrisc_cpu_do_interrupt;
cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
@@ -316,7 +316,7 @@ typedef struct OpenRISCCPU {
void cpu_openrisc_list(void);
-void openrisc_cpu_do_interrupt_locked(CPUState *cpu);
+void openrisc_cpu_do_interrupt(CPUState *cpu);
bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -26,7 +26,7 @@
#include "hw/loader.h"
#endif
-void openrisc_cpu_do_interrupt_locked(CPUState *cs)
+static void openrisc_cpu_do_interrupt_locked(CPUState *cs)
{
#ifndef CONFIG_USER_ONLY
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
@@ -101,6 +101,13 @@ void openrisc_cpu_do_interrupt_locked(CPUState *cs)
cs->exception_index = -1;
}
+void openrisc_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ openrisc_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
@@ -1231,6 +1231,7 @@ struct PPCVirtualHypervisorClass {
TYPE_PPC_VIRTUAL_HYPERVISOR)
#endif /* CONFIG_USER_ONLY */
+void ppc_cpu_do_interrupt(CPUState *cpu);
void ppc_cpu_do_interrupt_locked(CPUState *cpu);
bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
@@ -1428,3 +1428,10 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
env->error_code = insn & 0x03FF0000;
cpu_loop_exit(cs);
}
+
+void ppc_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ ppc_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
@@ -10885,7 +10885,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
pcc->parent_parse_features = cc->parse_features;
cc->parse_features = ppc_cpu_parse_featurestr;
cc->has_work_with_iothread_lock = ppc_cpu_has_work;
- cc->do_interrupt = ppc_cpu_do_interrupt_locked;
+ cc->do_interrupt = ppc_cpu_do_interrupt;
cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
cc->dump_state = ppc_cpu_dump_state;
cc->dump_statistics = ppc_cpu_dump_statistics;
@@ -537,7 +537,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
cc->class_by_name = riscv_cpu_class_by_name;
cc->has_work_with_iothread_lock = riscv_cpu_has_work;
- cc->do_interrupt = riscv_cpu_do_interrupt_locked;
+ cc->do_interrupt = riscv_cpu_do_interrupt;
cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
cc->dump_state = riscv_cpu_dump_state;
cc->set_pc = riscv_cpu_set_pc;
@@ -312,7 +312,7 @@ extern const char * const riscv_fpr_regnames[];
extern const char * const riscv_excp_names[];
extern const char * const riscv_intr_names[];
-void riscv_cpu_do_interrupt_locked(CPUState *cpu);
+void riscv_cpu_do_interrupt(CPUState *cpu);
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
@@ -25,6 +25,8 @@
#include "tcg/tcg-op.h"
#include "trace.h"
+static void riscv_cpu_do_interrupt_locked(CPUState *cs);
+
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
{
#ifdef CONFIG_USER_ONLY
@@ -814,13 +816,20 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
#endif
}
+void riscv_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ riscv_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
/*
* Handle Traps
*
* Adapted from Spike's processor_t::take_trap.
*
*/
-void riscv_cpu_do_interrupt_locked(CPUState *cs)
+static void riscv_cpu_do_interrupt_locked(CPUState *cs)
{
#if !defined(CONFIG_USER_ONLY)
@@ -185,7 +185,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
cc->class_by_name = rx_cpu_class_by_name;
cc->has_work = rx_cpu_has_work;
- cc->do_interrupt = rx_cpu_do_interrupt_locked;
+ cc->do_interrupt = rx_cpu_do_interrupt;
cc->cpu_exec_interrupt = rx_cpu_exec_interrupt;
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
@@ -125,6 +125,7 @@ typedef RXCPU ArchCPU;
#define CPU_RESOLVING_TYPE TYPE_RX_CPU
const char *rx_crname(uint8_t cr);
+void rx_cpu_do_interrupt(CPUState *cpu);
void rx_cpu_do_interrupt_locked(CPUState *cpu);
bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
@@ -119,6 +119,13 @@ void rx_cpu_do_interrupt_locked(CPUState *cs)
env->regs[0] = env->isp;
}
+void rx_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ rx_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
RXCPU *cpu = RXCPU(cs);
@@ -493,7 +493,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work_with_iothread_lock = s390_cpu_has_work;
#ifdef CONFIG_TCG
- cc->do_interrupt = s390_cpu_do_interrupt_locked;
+ cc->do_interrupt = s390_cpu_do_interrupt;
#endif
cc->dump_state = s390_cpu_dump_state;
cc->set_pc = s390_cpu_set_pc;
@@ -611,3 +611,10 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
}
#endif /* CONFIG_USER_ONLY */
+
+void s390_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ s390_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
@@ -268,6 +268,7 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
/* excp_helper.c */
void s390x_cpu_debug_excp_handler(CPUState *cs);
+void s390_cpu_do_interrupt(CPUState *cpu);
void s390_cpu_do_interrupt_locked(CPUState *cpu);
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
@@ -218,7 +218,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = superh_cpu_class_by_name;
cc->has_work = superh_cpu_has_work;
- cc->do_interrupt = superh_cpu_do_interrupt_locked;
+ cc->do_interrupt = superh_cpu_do_interrupt;
cc->cpu_exec_interrupt = superh_cpu_exec_interrupt;
cc->dump_state = superh_cpu_dump_state;
cc->set_pc = superh_cpu_set_pc;
@@ -204,7 +204,7 @@ struct SuperHCPU {
};
-void superh_cpu_do_interrupt_locked(CPUState *cpu);
+void superh_cpu_do_interrupt(CPUState *cpu);
bool superh_cpu_exec_interrupt(CPUState *cpu, int int_req);
void superh_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -45,7 +45,7 @@
#if defined(CONFIG_USER_ONLY)
-void superh_cpu_do_interrupt_locked(CPUState *cs)
+static void superh_cpu_do_interrupt_locked(CPUState *cs)
{
cs->exception_index = -1;
}
@@ -58,7 +58,7 @@ int cpu_sh4_is_cached(CPUSH4State *env, target_ulong addr)
#else /* !CONFIG_USER_ONLY */
-void superh_cpu_do_interrupt_locked(CPUState *cs)
+static void superh_cpu_do_interrupt_locked(CPUState *cs)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
CPUSH4State *env = &cpu->env;
@@ -782,6 +782,13 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
#endif
+void superh_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ superh_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
@@ -863,7 +863,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = sparc_cpu_class_by_name;
cc->parse_features = sparc_cpu_parse_features;
cc->has_work_with_iothread_lock = sparc_cpu_has_work;
- cc->do_interrupt = sparc_cpu_do_interrupt_locked;
+ cc->do_interrupt = sparc_cpu_do_interrupt;
cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
cc->dump_state = sparc_cpu_dump_state;
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
@@ -568,6 +568,7 @@ struct SPARCCPU {
extern const VMStateDescription vmstate_sparc_cpu;
#endif
+void sparc_cpu_do_interrupt(CPUState *cpu);
void sparc_cpu_do_interrupt_locked(CPUState *cpu);
void sparc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -138,6 +138,13 @@ void sparc_cpu_do_interrupt_locked(CPUState *cs)
#endif
}
+void sparc_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ sparc_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
#if !defined(CONFIG_USER_ONLY)
static void leon3_cache_control_int(CPUSPARCState *env)
{
@@ -198,6 +198,13 @@ void sparc_cpu_do_interrupt_locked(CPUState *cs)
cs->exception_index = -1;
}
+void sparc_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ sparc_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
trap_state *cpu_tsptr(CPUSPARCState* env)
{
return &env->ts[env->tl & MAXTL_MASK];
@@ -125,6 +125,13 @@ static bool tilegx_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
+static void tilegx_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ tilegx_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
@@ -147,7 +154,7 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = tilegx_cpu_class_by_name;
cc->has_work = tilegx_cpu_has_work;
- cc->do_interrupt = tilegx_cpu_do_interrupt_locked;
+ cc->do_interrupt = tilegx_cpu_do_interrupt;
cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt;
cc->dump_state = tilegx_cpu_dump_state;
cc->set_pc = tilegx_cpu_set_pc;
@@ -131,7 +131,7 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = uc32_cpu_class_by_name;
cc->has_work = uc32_cpu_has_work;
- cc->do_interrupt = uc32_cpu_do_interrupt_locked;
+ cc->do_interrupt = uc32_cpu_do_interrupt;
cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt;
cc->dump_state = uc32_cpu_dump_state;
cc->set_pc = uc32_cpu_set_pc;
@@ -75,6 +75,7 @@ struct UniCore32CPU {
};
+void uc32_cpu_do_interrupt(CPUState *cpu);
void uc32_cpu_do_interrupt_locked(CPUState *cpu);
bool uc32_cpu_exec_interrupt(CPUState *cpu, int int_req);
void uc32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
@@ -120,6 +120,13 @@ void uc32_cpu_do_interrupt_locked(CPUState *cs)
cpu_interrupt_request_or(cs, CPU_INTERRUPT_EXITTB);
}
+void uc32_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ uc32_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
int access_type, int is_user, uint32_t *phys_ptr, int *prot,
target_ulong *page_size)
@@ -190,7 +190,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = xtensa_cpu_class_by_name;
cc->has_work_with_iothread_lock = xtensa_cpu_has_work;
- cc->do_interrupt = xtensa_cpu_do_interrupt_locked;
+ cc->do_interrupt = xtensa_cpu_do_interrupt;
cc->cpu_exec_interrupt = xtensa_cpu_exec_interrupt;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_pc;
@@ -563,7 +563,7 @@ struct XtensaCPU {
bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
-void xtensa_cpu_do_interrupt_locked(CPUState *cpu);
+void xtensa_cpu_do_interrupt(CPUState *cpu);
bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request);
void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
unsigned size, MMUAccessType access_type,
@@ -195,7 +195,7 @@ static void handle_interrupt(CPUXtensaState *env)
}
/* Called from cpu_handle_interrupt with BQL held */
-void xtensa_cpu_do_interrupt_locked(CPUState *cs)
+static void xtensa_cpu_do_interrupt_locked(CPUState *cs)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;
@@ -254,11 +254,18 @@ void xtensa_cpu_do_interrupt_locked(CPUState *cs)
check_interrupts(env);
}
#else
-void xtensa_cpu_do_interrupt_locked(CPUState *cs)
+static void xtensa_cpu_do_interrupt_locked(CPUState *cs)
{
}
#endif
+void xtensa_cpu_do_interrupt(CPUState *cs)
+{
+ qemu_mutex_lock_iothread();
+ xtensa_cpu_do_interrupt_locked(cs);
+ qemu_mutex_unlock_iothread();
+}
+
bool xtensa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
As part of pushing the BQL down into the per-arch implementation, the first change is to remove the holding of BQL from cpu_handle_exception. Next, we made changes per-arch to re-add a new *_do_interrupt function, which gets the BQL and then calls to *_do_interrupt_locked. We also pointed the per-arch ->do_interrupt at the new *_do_interrupt. This patch is part of a series of transitions to move the BQL down into the do_interrupt per arch functions. This set of transitions is needed to maintain bisectability. It is worth mentioning that arm and cris are slightly different. In a prior patch for these arches, we added a new CPUClass method ->do_interrupt_locked. The only difference for arm and cris is that their new *_do_interrupt functions will be able to utilize this new ->do_interrupt_locked method. avr is another exception. avr, arm and cris all had a similar case where their *_cpu_exec_interrupt was calling to the CPUClass ->do_interrupt. This causes an issue when we push the lock down since ->do_interrupt will try to acquire the BQL, but the calling context already has it. To solve this for arm and cris, we added a new CPUCLass method as explained above. Moreover, it was actually required for these arches since they have more than one possible value of ->do_interrupt. In the case of avr, there is only one possible value of ->do_interrupt, so for that reason we changed the avr_cpu_exec_interrupt to call directly to avr_cpu_do_interrupt_locked rather than call cc->do_interrupt. The purpose of this set of changes is to set the groundwork so that an arch could move towards removing the BQL from the cpu_handle_interrupt/exception paths. This approach was suggested by Paolo Bonzini. For reference, here are key posts in the discussion, explaining the reasoning/benefits of this approach. https://lists.gnu.org/archive/html/qemu-devel/2020-08/msg01517.html https://lists.gnu.org/archive/html/qemu-devel/2020-08/msg00784.html https://lists.gnu.org/archive/html/qemu-devel/2020-07/msg08731.html https://lists.gnu.org/archive/html/qemu-devel/2020-08/msg00044.html Signed-off-by: Robert Foley <robert.foley@linaro.org> --- accel/tcg/cpu-exec.c | 2 -- target/alpha/cpu.c | 2 +- target/alpha/cpu.h | 2 +- target/alpha/helper.c | 9 ++++++++- target/arm/cpu.c | 2 +- target/arm/cpu.h | 2 ++ target/arm/cpu_tcg.c | 2 +- target/arm/helper.c | 8 ++++++++ target/avr/cpu.c | 2 +- target/avr/cpu.h | 2 +- target/avr/helper.c | 16 ++++++++++++---- target/cris/cpu.c | 7 +------ target/cris/cpu.h | 1 + target/cris/helper.c | 8 ++++++++ target/hppa/cpu.c | 2 +- target/hppa/cpu.h | 2 +- target/hppa/int_helper.c | 9 ++++++++- target/i386/cpu.c | 2 +- target/i386/cpu.h | 2 +- target/i386/seg_helper.c | 9 ++++++++- target/lm32/cpu.c | 2 +- target/lm32/cpu.h | 2 +- target/lm32/helper.c | 9 ++++++++- target/m68k/cpu.c | 2 +- target/m68k/cpu.h | 2 +- target/m68k/op_helper.c | 11 +++++++++-- target/microblaze/cpu.c | 2 +- target/microblaze/cpu.h | 2 +- target/microblaze/helper.c | 11 +++++++++-- target/mips/cpu.c | 2 +- target/mips/helper.c | 9 ++++++++- target/mips/internal.h | 2 +- target/nios2/cpu.c | 2 +- target/nios2/cpu.h | 1 + target/nios2/helper.c | 9 +++++++++ target/openrisc/cpu.c | 2 +- target/openrisc/cpu.h | 2 +- target/openrisc/interrupt.c | 9 ++++++++- target/ppc/cpu.h | 1 + target/ppc/excp_helper.c | 7 +++++++ target/ppc/translate_init.inc.c | 2 +- target/riscv/cpu.c | 2 +- target/riscv/cpu.h | 2 +- target/riscv/cpu_helper.c | 11 ++++++++++- target/rx/cpu.c | 2 +- target/rx/cpu.h | 1 + target/rx/helper.c | 7 +++++++ target/s390x/cpu.c | 2 +- target/s390x/excp_helper.c | 7 +++++++ target/s390x/internal.h | 1 + target/sh4/cpu.c | 2 +- target/sh4/cpu.h | 2 +- target/sh4/helper.c | 11 +++++++++-- target/sparc/cpu.c | 2 +- target/sparc/cpu.h | 1 + target/sparc/int32_helper.c | 7 +++++++ target/sparc/int64_helper.c | 7 +++++++ target/tilegx/cpu.c | 9 ++++++++- target/unicore32/cpu.c | 2 +- target/unicore32/cpu.h | 1 + target/unicore32/softmmu.c | 7 +++++++ target/xtensa/cpu.c | 2 +- target/xtensa/cpu.h | 2 +- target/xtensa/exc_helper.c | 11 +++++++++-- 64 files changed, 223 insertions(+), 60 deletions(-)