@@ -599,7 +599,6 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
True when it is, and we should restart on a new TB,
and via longjmp via cpu_loop_exit. */
else {
- qemu_mutex_lock_iothread();
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
replay_interrupt();
/*
@@ -614,7 +613,6 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
/* The target hook may have updated the 'cpu->interrupt_request';
* reload the 'interrupt_request' value */
interrupt_request = cpu_interrupt_request(cpu);
- qemu_mutex_unlock_iothread();
}
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
cpu_reset_interrupt(cpu, CPU_INTERRUPT_EXITTB);
@@ -218,7 +218,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;
- cc->cpu_exec_interrupt = alpha_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = alpha_cpu_exec_interrupt;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
cc->gdb_read_register = alpha_cpu_gdb_read_register;
@@ -277,7 +277,7 @@ extern const VMStateDescription vmstate_alpha_cpu;
#endif
void alpha_cpu_do_interrupt(CPUState *cpu);
-bool alpha_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -414,7 +414,7 @@ void alpha_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool alpha_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool alpha_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
@@ -458,6 +458,15 @@ bool alpha_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool alpha_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = alpha_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
static const char linux_reg_names[31][4] = {
@@ -524,7 +524,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
return unmasked || pstate_unmasked;
}
-bool arm_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool arm_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cs);
CPUARMState *env = cs->env_ptr;
@@ -577,6 +577,15 @@ bool arm_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return true;
}
+bool arm_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = arm_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
void arm_cpu_update_virq(ARMCPU *cpu)
{
/*
@@ -2217,7 +2226,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = arm_cpu_class_by_name;
cc->has_work = arm_cpu_has_work;
- cc->cpu_exec_interrupt = arm_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
@@ -995,7 +995,7 @@ 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_locked(CPUState *cpu, int int_req);
+bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
@@ -782,7 +782,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
- cc->cpu_exec_interrupt = arm_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
cc->gdb_num_core_regs = 34;
@@ -40,6 +40,15 @@ static bool arm_v7m_cpu_exec_interrupt_locked(CPUState *cs,
return ret;
}
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = arm_v7m_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void arm926_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -606,7 +615,7 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
acc->do_interrupt_locked = arm_v7m_cpu_do_interrupt_locked;
#endif
- cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
cc->gdb_core_xml_file = "arm-m-profile.xml";
}
@@ -198,7 +198,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = avr_cpu_has_work;
cc->do_interrupt = avr_cpu_do_interrupt;
- cc->cpu_exec_interrupt = avr_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = avr_cpu_exec_interrupt;
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
cc->memory_rw_debug = avr_cpu_memory_rw_debug;
@@ -157,7 +157,7 @@ typedef struct AVRCPU {
extern const struct VMStateDescription vms_avr_cpu;
void avr_cpu_do_interrupt(CPUState *cpu);
-bool avr_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
@@ -26,7 +26,7 @@
static void avr_cpu_do_interrupt_locked(CPUState *cs);
-bool avr_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool avr_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
bool ret = false;
AVRCPU *cpu = AVR_CPU(cs);
@@ -57,6 +57,15 @@ bool avr_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return ret;
}
+bool avr_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = avr_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void avr_cpu_do_interrupt_locked(CPUState *cs)
{
AVRCPU *cpu = AVR_CPU(cs);
@@ -270,7 +270,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = cris_cpu_has_work;
cc->do_interrupt = cris_cpu_do_interrupt;
ccc->do_interrupt_locked = cris_cpu_do_interrupt_locked;
- cc->cpu_exec_interrupt = cris_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = cris_cpu_exec_interrupt;
cc->dump_state = cris_cpu_dump_state;
cc->set_pc = cris_cpu_set_pc;
cc->gdb_read_register = cris_cpu_gdb_read_register;
@@ -190,7 +190,7 @@ extern const VMStateDescription vmstate_cris_cpu;
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_locked(CPUState *cpu, int int_req);
+bool cris_cpu_exec_interrupt(CPUState *cpu, int int_req);
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
@@ -296,7 +296,7 @@ hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
#endif
-bool cris_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool cris_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
CRISCPUClass *ccc = CRIS_CPU_CLASS(cs);
CRISCPU *cpu = CRIS_CPU(cs);
@@ -326,3 +326,12 @@ bool cris_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return ret;
}
+
+bool cris_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = cris_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -140,7 +140,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;
- cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt;
cc->dump_state = hppa_cpu_dump_state;
cc->set_pc = hppa_cpu_set_pc;
cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb;
@@ -324,7 +324,7 @@ 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(CPUState *cpu);
-bool hppa_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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,
MMUAccessType access_type, int mmu_idx,
@@ -253,7 +253,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool hppa_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool hppa_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
#ifndef CONFIG_USER_ONLY
HPPACPU *cpu = HPPA_CPU(cs);
@@ -268,3 +268,12 @@ bool hppa_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
#endif
return false;
}
+
+bool hppa_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = hppa_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -7298,7 +7298,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->has_work = x86_cpu_has_work;
#ifdef CONFIG_TCG
cc->do_interrupt = x86_cpu_do_interrupt;
- cc->cpu_exec_interrupt = x86_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
#endif
cc->dump_state = x86_cpu_dump_state;
cc->set_pc = x86_cpu_set_pc;
@@ -1771,7 +1771,7 @@ extern VMStateDescription vmstate_x86_cpu;
* @cpu: vCPU the interrupt is to be handled by.
*/
void x86_cpu_do_interrupt(CPUState *cpu);
-bool x86_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
@@ -1322,7 +1322,7 @@ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw)
do_interrupt_all(env_archcpu(env), intno, 0, 0, 0, is_hw);
}
-bool x86_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool x86_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@@ -1387,6 +1387,15 @@ bool x86_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return true;
}
+bool x86_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = x86_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
void helper_lldt(CPUX86State *env, int selector)
{
SegmentCache *dt;
@@ -223,7 +223,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;
- cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt;
cc->dump_state = lm32_cpu_dump_state;
cc->set_pc = lm32_cpu_set_pc;
cc->gdb_read_register = lm32_cpu_gdb_read_register;
@@ -199,7 +199,7 @@ extern const VMStateDescription vmstate_lm32_cpu;
#endif
void lm32_cpu_do_interrupt(CPUState *cpu);
-bool lm32_cpu_exec_interrupt_locked(CPUState *cs, int int_req);
+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);
int lm32_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -205,7 +205,7 @@ void lm32_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool lm32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool lm32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;
@@ -218,6 +218,15 @@ bool lm32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = lm32_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
/* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
* area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
* 0x80000000-0xffffffff is not cached and used to access IO devices. */
@@ -278,7 +278,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;
- cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = m68k_cpu_exec_interrupt;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
cc->gdb_read_register = m68k_cpu_gdb_read_register;
@@ -165,7 +165,7 @@ struct M68kCPU {
void m68k_cpu_do_interrupt(CPUState *cpu);
-bool m68k_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int m68k_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -511,7 +511,7 @@ void m68k_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool m68k_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool m68k_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
M68kCPU *cpu = M68K_CPU(cs);
CPUM68KState *env = &cpu->env;
@@ -531,6 +531,15 @@ bool m68k_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool m68k_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = m68k_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void raise_exception_ra(CPUM68KState *env, int tt, uintptr_t raddr)
{
CPUState *cs = env_cpu(env);
@@ -317,7 +317,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;
- cc->cpu_exec_interrupt = mb_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = mb_cpu_exec_interrupt;
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
cc->gdb_read_register = mb_cpu_gdb_read_register;
@@ -316,7 +316,7 @@ struct MicroBlazeCPU {
void mb_cpu_do_interrupt(CPUState *cs);
-bool mb_cpu_exec_interrupt_locked(CPUState *cs, int int_req);
+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);
int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -294,7 +294,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool mb_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool mb_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
@@ -309,3 +309,12 @@ bool mb_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
}
return false;
}
+
+bool mb_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = mb_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -197,7 +197,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;
- cc->cpu_exec_interrupt = mips_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
@@ -1405,7 +1405,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool mips_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool mips_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
MIPSCPU *cpu = MIPS_CPU(cs);
@@ -1423,6 +1423,15 @@ bool mips_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool mips_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = mips_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
#if !defined(CONFIG_USER_ONLY)
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
{
@@ -81,7 +81,7 @@ enum CPUMIPSMSADataFormat {
};
void mips_cpu_do_interrupt(CPUState *cpu);
-bool mips_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -112,6 +112,15 @@ static bool nios2_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+static bool nios2_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = nios2_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
{
@@ -193,7 +202,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;
- cc->cpu_exec_interrupt = nios2_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = nios2_cpu_exec_interrupt;
cc->dump_state = nios2_cpu_dump_state;
cc->set_pc = nios2_cpu_set_pc;
cc->disas_set_info = nios2_cpu_disas_set_info;
@@ -155,7 +155,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;
- cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
@@ -317,7 +317,7 @@ typedef struct OpenRISCCPU {
void cpu_openrisc_list(void);
void openrisc_cpu_do_interrupt(CPUState *cpu);
-bool openrisc_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -108,7 +108,8 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool openrisc_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool openrisc_cpu_exec_interrupt_locked(CPUState *cs,
+ int interrupt_request)
{
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
CPUOpenRISCState *env = &cpu->env;
@@ -127,3 +128,12 @@ bool openrisc_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
}
return false;
}
+
+bool openrisc_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = openrisc_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -1233,7 +1233,7 @@ struct PPCVirtualHypervisorClass {
void ppc_cpu_do_interrupt(CPUState *cpu);
void ppc_cpu_do_interrupt_locked(CPUState *cpu);
-bool ppc_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -1052,7 +1052,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
}
#endif /* !CONFIG_USER_ONLY */
-bool ppc_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool ppc_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
@@ -1435,3 +1435,12 @@ void ppc_cpu_do_interrupt(CPUState *cs)
ppc_cpu_do_interrupt_locked(cs);
qemu_mutex_unlock_iothread();
}
+
+bool ppc_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = ppc_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -10886,7 +10886,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->parse_features = ppc_cpu_parse_featurestr;
cc->has_work_with_iothread_lock = ppc_cpu_has_work;
cc->do_interrupt = ppc_cpu_do_interrupt;
- cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
cc->dump_state = ppc_cpu_dump_state;
cc->dump_statistics = ppc_cpu_dump_statistics;
cc->set_pc = ppc_cpu_set_pc;
@@ -538,7 +538,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;
- cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
cc->dump_state = riscv_cpu_dump_state;
cc->set_pc = riscv_cpu_set_pc;
cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
@@ -315,7 +315,7 @@ extern const char * const riscv_intr_names[];
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_locked(CPUState *cs, int interrupt_request);
+bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
bool riscv_cpu_fp_enabled(CPURISCVState *env);
bool riscv_cpu_virt_enabled(CPURISCVState *env);
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
@@ -78,7 +78,7 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
}
#endif
-bool riscv_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool riscv_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
#if !defined(CONFIG_USER_ONLY)
if (interrupt_request & CPU_INTERRUPT_HARD) {
@@ -95,6 +95,15 @@ bool riscv_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool riscv_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = riscv_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
#if !defined(CONFIG_USER_ONLY)
/* Return true is floating point support is currently enabled */
@@ -186,7 +186,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;
- cc->cpu_exec_interrupt = rx_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = rx_cpu_exec_interrupt;
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
cc->synchronize_from_tb = rx_cpu_synchronize_from_tb;
@@ -127,7 +127,7 @@ typedef RXCPU ArchCPU;
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_locked(CPUState *cpu, int int_req);
+bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
void rx_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
int rx_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int rx_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
@@ -126,7 +126,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool rx_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool rx_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
RXCPU *cpu = RXCPU(cs);
CPURXState *env = &cpu->env;
@@ -150,6 +150,15 @@ bool rx_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool rx_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = rx_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
hwaddr rx_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
return addr;
@@ -505,7 +505,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->get_crash_info = s390_cpu_get_crash_info;
cc->write_elf64_note = s390_cpu_write_elf64_note;
#ifdef CONFIG_TCG
- cc->cpu_exec_interrupt = s390_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
cc->debug_excp_handler = s390x_cpu_debug_excp_handler;
cc->do_unaligned_access = s390x_cpu_do_unaligned_access;
#endif
@@ -543,7 +543,7 @@ try_deliver:
}
}
-bool s390_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool s390_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
S390CPU *cpu = S390_CPU(cs);
@@ -567,6 +567,15 @@ bool s390_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool s390_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = s390_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
void s390x_cpu_debug_excp_handler(CPUState *cs)
{
S390CPU *cpu = S390_CPU(cs);
@@ -270,7 +270,7 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
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_locked(CPUState *cpu, int int_req);
+bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
@@ -219,7 +219,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;
- cc->cpu_exec_interrupt = superh_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = superh_cpu_exec_interrupt;
cc->dump_state = superh_cpu_dump_state;
cc->set_pc = superh_cpu_set_pc;
cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
@@ -205,7 +205,7 @@ struct SuperHCPU {
void superh_cpu_do_interrupt(CPUState *cpu);
-bool superh_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+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);
int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
@@ -789,7 +789,8 @@ void superh_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool superh_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool superh_cpu_exec_interrupt_locked(CPUState *cs,
+ int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
SuperHCPU *cpu = SUPERH_CPU(cs);
@@ -806,6 +807,15 @@ bool superh_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+bool superh_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = superh_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr)
@@ -97,6 +97,15 @@ static bool sparc_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
return false;
}
+static bool sparc_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = sparc_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
{
info->print_insn = print_insn_sparc;
@@ -864,7 +873,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->parse_features = sparc_cpu_parse_features;
cc->has_work_with_iothread_lock = sparc_cpu_has_work;
cc->do_interrupt = sparc_cpu_do_interrupt;
- cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
cc->dump_state = sparc_cpu_dump_state;
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
@@ -142,6 +142,15 @@ static bool tilegx_cpu_exec_interrupt_locked(CPUState *cs,
return false;
}
+static bool tilegx_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = tilegx_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
+
static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -156,7 +165,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;
- cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt;
cc->dump_state = tilegx_cpu_dump_state;
cc->set_pc = tilegx_cpu_set_pc;
cc->tlb_fill = tilegx_cpu_tlb_fill;
@@ -132,7 +132,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;
- cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt;
cc->dump_state = uc32_cpu_dump_state;
cc->set_pc = uc32_cpu_set_pc;
cc->tlb_fill = uc32_cpu_tlb_fill;
@@ -77,7 +77,7 @@ struct UniCore32CPU {
void uc32_cpu_do_interrupt(CPUState *cpu);
void uc32_cpu_do_interrupt_locked(CPUState *cpu);
-bool uc32_cpu_exec_interrupt_locked(CPUState *cpu, int int_req);
+bool uc32_cpu_exec_interrupt(CPUState *cpu, int int_req);
void uc32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr uc32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
@@ -167,7 +167,7 @@ void helper_cp1_putc(target_ulong regval)
}
#endif /* !CONFIG_USER_ONLY */
-bool uc32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool uc32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
UniCore32CPU *cpu = UNICORE32_CPU(cs);
@@ -181,3 +181,12 @@ bool uc32_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
}
return false;
}
+
+bool uc32_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = uc32_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
@@ -191,7 +191,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;
- cc->cpu_exec_interrupt = xtensa_cpu_exec_interrupt_locked;
+ cc->cpu_exec_interrupt = xtensa_cpu_exec_interrupt;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_pc;
cc->gdb_read_register = xtensa_cpu_gdb_read_register;
@@ -564,7 +564,7 @@ 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(CPUState *cpu);
-bool xtensa_cpu_exec_interrupt_locked(CPUState *cpu, int interrupt_request);
+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,
int mmu_idx, MemTxAttrs attrs,
@@ -266,7 +266,8 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
qemu_mutex_unlock_iothread();
}
-bool xtensa_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
+static bool xtensa_cpu_exec_interrupt_locked(CPUState *cs,
+ int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
cs->exception_index = EXC_IRQ;
@@ -275,3 +276,12 @@ bool xtensa_cpu_exec_interrupt_locked(CPUState *cs, int interrupt_request)
}
return false;
}
+
+bool xtensa_cpu_exec_interrupt(CPUState *cs, int int_req)
+{
+ bool status;
+ qemu_mutex_lock_iothread();
+ status = xtensa_cpu_exec_interrupt_locked(cs, int_req);
+ qemu_mutex_unlock_iothread();
+ return status;
+}
Push the BQL on ->cpu_exec_interrupt down into per-arch implementation. The first step is to remove the BQL from cpu_handle_interrupt, which currently calls ->cpu_exec_interrupt. We then added the *_cpu_exec_interrupt functions, which get the BQL and then call to *_cpu_exec_interrupt_locked. We also pointed the per-arch ->cpu_exec_interrupt at the new *cpu_exec_interrupt. This patch is part of a series of transitions to move the BQL down into the cpu_exec_interrupt per arch functions. This set of transitions is needed to maintain bisectability. 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/msg00784.html https://lists.gnu.org/archive/html/qemu-devel/2020-08/msg01517.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 | 11 ++++++++++- target/arm/cpu.c | 13 +++++++++++-- target/arm/cpu.h | 2 +- target/arm/cpu64.c | 2 +- target/arm/cpu_tcg.c | 11 ++++++++++- target/avr/cpu.c | 2 +- target/avr/cpu.h | 2 +- target/avr/helper.c | 11 ++++++++++- target/cris/cpu.c | 2 +- target/cris/cpu.h | 2 +- target/cris/helper.c | 11 ++++++++++- target/hppa/cpu.c | 2 +- target/hppa/cpu.h | 2 +- target/hppa/int_helper.c | 11 ++++++++++- target/i386/cpu.c | 2 +- target/i386/cpu.h | 2 +- target/i386/seg_helper.c | 11 ++++++++++- target/lm32/cpu.c | 2 +- target/lm32/cpu.h | 2 +- target/lm32/helper.c | 11 ++++++++++- 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 | 11 ++++++++++- target/mips/internal.h | 2 +- target/nios2/cpu.c | 11 ++++++++++- target/openrisc/cpu.c | 2 +- target/openrisc/cpu.h | 2 +- target/openrisc/interrupt.c | 12 +++++++++++- target/ppc/cpu.h | 2 +- target/ppc/excp_helper.c | 11 ++++++++++- 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 | 2 +- target/rx/helper.c | 11 ++++++++++- target/s390x/cpu.c | 2 +- target/s390x/excp_helper.c | 11 ++++++++++- target/s390x/internal.h | 2 +- target/sh4/cpu.c | 2 +- target/sh4/cpu.h | 2 +- target/sh4/helper.c | 12 +++++++++++- target/sparc/cpu.c | 11 ++++++++++- target/tilegx/cpu.c | 11 ++++++++++- target/unicore32/cpu.c | 2 +- target/unicore32/cpu.h | 2 +- target/unicore32/helper.c | 11 ++++++++++- target/xtensa/cpu.c | 2 +- target/xtensa/cpu.h | 2 +- target/xtensa/exc_helper.c | 12 +++++++++++- 59 files changed, 260 insertions(+), 61 deletions(-)