Skip to content

Commit

Permalink
cpu: Replace do_interrupt() by CPUClass::do_interrupt method
Browse files Browse the repository at this point in the history
This removes a global per-target function and thus takes us one step
closer to compiling multiple targets into one executable.

It will also allow to override the interrupt handling for certain CPU
families.

Signed-off-by: Andreas Färber <[email protected]>
  • Loading branch information
afaerber committed Mar 12, 2013
1 parent c3affe5 commit 97a8ea5
Show file tree
Hide file tree
Showing 63 changed files with 159 additions and 67 deletions.
36 changes: 20 additions & 16 deletions cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ volatile sig_atomic_t exit_request;
int cpu_exec(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
#if !(defined(CONFIG_USER_ONLY) && \
(defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
CPUClass *cc = CPU_GET_CLASS(cpu);
#endif
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
Expand Down Expand Up @@ -265,12 +269,12 @@ int cpu_exec(CPUArchState *env)
which will be handled outside the cpu execution
loop */
#if defined(TARGET_I386)
do_interrupt(env);
cc->do_interrupt(cpu);
#endif
ret = env->exception_index;
break;
#else
do_interrupt(env);
cc->do_interrupt(cpu);
env->exception_index = -1;
#endif
}
Expand Down Expand Up @@ -380,7 +384,7 @@ int cpu_exec(CPUArchState *env)
if ((interrupt_request & CPU_INTERRUPT_HARD)
&& (env->ie & IE_IE)) {
env->exception_index = EXCP_IRQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_MICROBLAZE)
Expand All @@ -389,7 +393,7 @@ int cpu_exec(CPUArchState *env)
&& !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
&& !(env->iflags & (D_FLAG | IMM_FLAG))) {
env->exception_index = EXCP_IRQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_MIPS)
Expand All @@ -398,7 +402,7 @@ int cpu_exec(CPUArchState *env)
/* Raise it */
env->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_OPENRISC)
Expand All @@ -414,7 +418,7 @@ int cpu_exec(CPUArchState *env)
}
if (idx >= 0) {
env->exception_index = idx;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
}
Expand All @@ -429,7 +433,7 @@ int cpu_exec(CPUArchState *env)
cpu_pil_allowed(env, pil)) ||
type != TT_EXTINT) {
env->exception_index = env->interrupt_index;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
}
Expand All @@ -438,7 +442,7 @@ int cpu_exec(CPUArchState *env)
if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->uncached_cpsr & CPSR_F)) {
env->exception_index = EXCP_FIQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
/* ARMv7-M interrupt return works by loading a magic value
Expand All @@ -454,19 +458,19 @@ int cpu_exec(CPUArchState *env)
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
|| !(env->uncached_cpsr & CPSR_I))) {
env->exception_index = EXCP_IRQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_UNICORE32)
if (interrupt_request & CPU_INTERRUPT_HARD
&& !(env->uncached_asr & ASR_I)) {
env->exception_index = UC32_EXCP_INTR;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_SH4)
if (interrupt_request & CPU_INTERRUPT_HARD) {
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_ALPHA)
Expand Down Expand Up @@ -497,7 +501,7 @@ int cpu_exec(CPUArchState *env)
if (idx >= 0) {
env->exception_index = idx;
env->error_code = 0;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
}
Expand All @@ -506,7 +510,7 @@ int cpu_exec(CPUArchState *env)
&& (env->pregs[PR_CCS] & I_FLAG)
&& !env->locked_irq) {
env->exception_index = EXCP_IRQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
if (interrupt_request & CPU_INTERRUPT_NMI) {
Expand All @@ -518,7 +522,7 @@ int cpu_exec(CPUArchState *env)
}
if ((env->pregs[PR_CCS] & m_flag_archval)) {
env->exception_index = EXCP_NMI;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
}
Expand All @@ -538,13 +542,13 @@ int cpu_exec(CPUArchState *env)
#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(env->psw.mask & PSW_MASK_EXT)) {
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_XTENSA)
if (interrupt_request & CPU_INTERRUPT_HARD) {
env->exception_index = EXC_IRQ;
do_interrupt(env);
cc->do_interrupt(cpu);
next_tb = 0;
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/qom/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ typedef struct CPUState CPUState;
* @class_by_name: Callback to map -cpu command line model name to an
* instantiatable CPU type.
* @reset: Callback to reset the #CPUState to its initial state.
* @do_interrupt: Callback for interrupt handling.
* @vmsd: State description for migration.
*
* Represents a CPU family or model.
Expand All @@ -56,6 +57,7 @@ typedef struct CPUClass {
ObjectClass *(*class_by_name)(const char *cpu_model);

void (*reset)(CPUState *cpu);
void (*do_interrupt)(CPUState *cpu);

const struct VMStateDescription *vmsd;
} CPUClass;
Expand Down
2 changes: 2 additions & 0 deletions target-alpha/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,6 @@ static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)

#define ENV_OFFSET offsetof(AlphaCPU, env)

void alpha_cpu_do_interrupt(CPUState *cpu);

#endif
1 change: 1 addition & 0 deletions target-alpha/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
dc->realize = alpha_cpu_realizefn;

cc->class_by_name = alpha_cpu_class_by_name;
cc->do_interrupt = alpha_cpu_do_interrupt;
}

static const TypeInfo alpha_cpu_type_info = {
Expand Down
1 change: 0 additions & 1 deletion target-alpha/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ int cpu_alpha_signal_handler(int host_signum, void *pinfo,
int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
void do_interrupt (CPUAlphaState *env);
void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
Expand Down
4 changes: 3 additions & 1 deletion target-alpha/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,10 @@ int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw,
}
#endif /* USER_ONLY */

void do_interrupt (CPUAlphaState *env)
void alpha_cpu_do_interrupt(CPUState *cs)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
int i = env->exception_index;

if (qemu_loglevel_mask(CPU_LOG_INT)) {
Expand Down
2 changes: 2 additions & 0 deletions target-arm/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)

void register_cp_regs_for_features(ARMCPU *cpu);

void arm_cpu_do_interrupt(CPUState *cpu);

#endif
1 change: 1 addition & 0 deletions target-arm/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->reset = arm_cpu_reset;

cc->class_by_name = arm_cpu_class_by_name;
cc->do_interrupt = arm_cpu_do_interrupt;
}

static void cpu_register(const ARMCPUInfo *info)
Expand Down
1 change: 0 additions & 1 deletion target-arm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model);
void arm_translate_init(void);
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
int cpu_arm_exec(CPUARMState *s);
void do_interrupt(CPUARMState *);
int bank_number(int mode);
void switch_mode(CPUARMState *, int);
uint32_t do_arm_semihosting(CPUARMState *env);
Expand Down
11 changes: 7 additions & 4 deletions target-arm/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,8 +1567,11 @@ uint32_t HELPER(rbit)(uint32_t x)

#if defined(CONFIG_USER_ONLY)

void do_interrupt (CPUARMState *env)
void arm_cpu_do_interrupt(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;

env->exception_index = -1;
}

Expand Down Expand Up @@ -1799,9 +1802,10 @@ static void do_interrupt_v7m(CPUARMState *env)
}

/* Handle a CPU exception. */
void do_interrupt(CPUARMState *env)
void arm_cpu_do_interrupt(CPUState *cs)
{
CPUState *cs;
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
uint32_t addr;
uint32_t mask;
int new_mode;
Expand Down Expand Up @@ -1908,7 +1912,6 @@ void do_interrupt(CPUARMState *env)
}
env->regs[14] = env->regs[15] + offset;
env->regs[15] = addr;
cs = CPU(arm_env_get_cpu(env));
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}

Expand Down
2 changes: 2 additions & 0 deletions target-cris/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,6 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)

#define ENV_OFFSET offsetof(CRISCPU, env)

void cris_cpu_do_interrupt(CPUState *cpu);

#endif
1 change: 1 addition & 0 deletions target-cris/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->reset = cris_cpu_reset;

cc->class_by_name = cris_cpu_class_by_name;
cc->do_interrupt = cris_cpu_do_interrupt;
}

static const TypeInfo cris_cpu_type_info = {
Expand Down
1 change: 0 additions & 1 deletion target-cris/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ typedef struct CPUCRISState {

CRISCPU *cpu_cris_init(const char *cpu_model);
int cpu_cris_exec(CPUCRISState *s);
void do_interrupt(CPUCRISState *env);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
Expand Down
10 changes: 7 additions & 3 deletions target-cris/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@

#if defined(CONFIG_USER_ONLY)

void do_interrupt(CPUCRISState *env)
void cris_cpu_do_interrupt(CPUState *cs)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;

env->exception_index = -1;
env->pregs[PR_ERP] = env->pc;
}
Expand Down Expand Up @@ -162,9 +165,10 @@ static void do_interruptv10(CPUCRISState *env)
env->pregs[PR_ERP]);
}

void do_interrupt(CPUCRISState *env)
void cris_cpu_do_interrupt(CPUState *cs)
{
D(CPUState *cs = CPU(cris_env_get_cpu(env)));
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
int ex_vec = -1;

if (env->pregs[PR_VR] < 32) {
Expand Down
6 changes: 6 additions & 0 deletions target-i386/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,10 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
extern const struct VMStateDescription vmstate_x86_cpu;
#endif

/**
* x86_cpu_do_interrupt:
* @cpu: vCPU the interrupt is to be handled by.
*/
void x86_cpu_do_interrupt(CPUState *cpu);

#endif
1 change: 1 addition & 0 deletions target-i386/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
xcc->parent_reset = cc->reset;
cc->reset = x86_cpu_reset;

cc->do_interrupt = x86_cpu_do_interrupt;
cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
}

Expand Down
3 changes: 1 addition & 2 deletions target-i386/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
uint64_t param);
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);

/* op_helper.c */
void do_interrupt(CPUX86State *env);
/* seg_helper.c */
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);

void do_smm_enter(CPUX86State *env1);
Expand Down
5 changes: 4 additions & 1 deletion target-i386/seg_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1231,8 +1231,11 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int,
#endif
}

void do_interrupt(CPUX86State *env)
void x86_cpu_do_interrupt(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;

#if defined(CONFIG_USER_ONLY)
/* if user mode only, we simulate a fake exception
which will be handled outside the cpu execution
Expand Down
2 changes: 2 additions & 0 deletions target-lm32/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,6 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)

#define ENV_OFFSET offsetof(LM32CPU, env)

void lm32_cpu_do_interrupt(CPUState *cpu);

#endif
2 changes: 2 additions & 0 deletions target-lm32/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)

lcc->parent_reset = cc->reset;
cc->reset = lm32_cpu_reset;

cc->do_interrupt = lm32_cpu_do_interrupt;
}

static const TypeInfo lm32_cpu_type_info = {
Expand Down
1 change: 0 additions & 1 deletion target-lm32/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ struct CPULM32State {
LM32CPU *cpu_lm32_init(const char *cpu_model);
void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
int cpu_lm32_exec(CPULM32State *s);
void do_interrupt(CPULM32State *env);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
Expand Down
5 changes: 4 additions & 1 deletion target-lm32/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
return addr & TARGET_PAGE_MASK;
}

void do_interrupt(CPULM32State *env)
void lm32_cpu_do_interrupt(CPUState *cs)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;

qemu_log_mask(CPU_LOG_INT,
"exception at pc=%x type=%x\n", env->pc, env->exception_index);

Expand Down
2 changes: 2 additions & 0 deletions target-m68k/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)

#define ENV_OFFSET offsetof(M68kCPU, env)

void m68k_cpu_do_interrupt(CPUState *cpu);

#endif
1 change: 1 addition & 0 deletions target-m68k/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->reset = m68k_cpu_reset;

cc->class_by_name = m68k_cpu_class_by_name;
cc->do_interrupt = m68k_cpu_do_interrupt;
dc->vmsd = &vmstate_m68k_cpu;
}

Expand Down
Loading

0 comments on commit 97a8ea5

Please sign in to comment.