aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-09 22:45:36 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-09 22:45:36 +0000
commite9df014c0b433ecd9785db4a423e472bc3db386a (patch)
treee16e40d4fd68aff979be0d8e57ffdc17ee108ca7 /target-ppc
parent682c4f15598fa82eb00973b9b14be86d1e5a726c (diff)
downloadqemu-e9df014c0b433ecd9785db4a423e472bc3db386a.zip
qemu-e9df014c0b433ecd9785db4a423e472bc3db386a.tar.gz
qemu-e9df014c0b433ecd9785db4a423e472bc3db386a.tar.bz2
Implement embedded IRQ controller for PowerPC 6xx/740 & 750.
Fix PowerPC external interrupt input handling and lowering. Fix OpenPIC output pins management. Fix multiples bugs in OpenPIC IRQ management. Fix OpenPIC CPU(s) reset function. Fix Mac99 machine to properly route OpenPIC outputs to the PowerPC input pins. Fix PREP machine to properly route i8259 output to the PowerPC external interrupt pin. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2647 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/cpu.h46
-rw-r--r--target-ppc/helper.c16
-rw-r--r--target-ppc/translate_init.c35
3 files changed, 81 insertions, 16 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 1515af9..0560a38 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -758,7 +758,13 @@ struct CPUPPCState {
int error_code;
int interrupt_request;
uint32_t pending_interrupts;
- void *irq[32];
+#if !defined(CONFIG_USER_ONLY)
+ /* This is the IRQ controller, which is implementation dependant
+ * and only relevant when emulating a complete machine.
+ */
+ uint32_t irq_input_state;
+ void **irq_inputs;
+#endif
/* Those resources are used only during code translation */
/* Next instruction pointer */
@@ -801,6 +807,7 @@ int cpu_ppc_signal_handler(int host_signum, void *pinfo,
void *puc);
void do_interrupt (CPUPPCState *env);
+void ppc_hw_interrupt (CPUPPCState *env);
void cpu_loop_exit(void);
void dump_stack (CPUPPCState *env);
@@ -1303,16 +1310,35 @@ enum {
/* Hardware interruption sources:
* all those exception can be raised simulteaneously
*/
+/* Input pins definitions */
+enum {
+ /* 6xx bus input pins */
+ PPC_INPUT_HRESET = 0,
+ PPC_INPUT_SRESET = 1,
+ PPC_INPUT_CKSTP_IN = 2,
+ PPC_INPUT_MCP = 3,
+ PPC_INPUT_SMI = 4,
+ PPC_INPUT_INT = 5,
+ /* Embedded PowerPC input pins */
+ PPC_INPUT_CINT = 6,
+ PPC_INPUT_NB,
+};
+
+/* Hardware exceptions definitions */
enum {
- PPC_INTERRUPT_RESET = 0, /* Reset / critical input */
- PPC_INTERRUPT_MCK = 1, /* Machine check exception */
- PPC_INTERRUPT_EXT = 2, /* External interrupt */
- PPC_INTERRUPT_DECR = 3, /* Decrementer exception */
- PPC_INTERRUPT_HDECR = 4, /* Hypervisor decrementer exception */
- PPC_INTERRUPT_PIT = 5, /* Programmable inteval timer interrupt */
- PPC_INTERRUPT_FIT = 6, /* Fixed interval timer interrupt */
- PPC_INTERRUPT_WDT = 7, /* Watchdog timer interrupt */
- PPC_INTERRUPT_DEBUG = 8, /* External debug exception */
+ /* External hardware exception sources */
+ PPC_INTERRUPT_RESET = 0, /* Reset exception */
+ PPC_INTERRUPT_MCK = 1, /* Machine check exception */
+ PPC_INTERRUPT_EXT = 2, /* External interrupt */
+ PPC_INTERRUPT_SMI = 3, /* System management interrupt */
+ PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */
+ PPC_INTERRUPT_DEBUG = 5, /* External debug exception */
+ /* Internal hardware exception sources */
+ PPC_INTERRUPT_DECR = 6, /* Decrementer exception */
+ PPC_INTERRUPT_HDECR = 7, /* Hypervisor decrementer exception */
+ PPC_INTERRUPT_PIT = 8, /* Programmable inteval timer interrupt */
+ PPC_INTERRUPT_FIT = 9, /* Fixed interval timer interrupt */
+ PPC_INTERRUPT_WDT = 10, /* Watchdog timer interrupt */
};
/*****************************************************************************/
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 69ed260..b9a55b1 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1358,11 +1358,9 @@ void do_interrupt (CPUState *env)
env->exception_index = -1;
}
-int ppc_hw_interrupt (CPUState *env)
+void ppc_hw_interrupt (CPUState *env)
{
env->exception_index = -1;
-
- return 0;
}
#else /* defined (CONFIG_USER_ONLY) */
static void dump_syscall(CPUState *env)
@@ -1927,7 +1925,7 @@ void do_interrupt (CPUState *env)
env->exception_index = EXCP_NONE;
}
-int ppc_hw_interrupt (CPUState *env)
+void ppc_hw_interrupt (CPUPPCState *env)
{
int raised = 0;
@@ -1940,6 +1938,9 @@ int ppc_hw_interrupt (CPUState *env)
/* Raise it */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
/* External reset / critical input */
+ /* XXX: critical input should be handled another way.
+ * This code is not correct !
+ */
env->exception_index = EXCP_RESET;
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
raised = 1;
@@ -1984,7 +1985,12 @@ int ppc_hw_interrupt (CPUState *env)
/* External interrupt */
} else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
env->exception_index = EXCP_EXTERNAL;
+ /* Taking an external interrupt does not clear the external
+ * interrupt status
+ */
+#if 0
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
+#endif
raised = 1;
}
#if 0 // TODO
@@ -1999,7 +2005,5 @@ int ppc_hw_interrupt (CPUState *env)
env->error_code = 0;
do_interrupt(env);
}
-
- return raised;
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d562631..805c897 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -35,6 +35,18 @@ struct ppc_def_t {
uint64_t msr_mask;
};
+/* For user-mode emulation, we don't emulate any IRQ controller */
+#if defined(CONFIG_USER_ONLY)
+#define PPC_IRQ_INIT_FN(name) \
+static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \
+{ \
+}
+#else
+#define PPC_IRQ_INIT_FN(name) \
+void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
+#endif
+PPC_IRQ_INIT_FN(6xx);
+
/* Generic callbacks:
* do nothing but store/retrieve spr value
*/
@@ -1865,6 +1877,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
case CPU_PPC_403GA: /* 403 GA family */
@@ -1879,6 +1892,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
case CPU_PPC_405CR: /* 405 GP/CR family */
@@ -1895,6 +1909,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
case CPU_PPC_NPE405H: /* NPe405 H family */
@@ -1909,6 +1924,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
#if defined (TODO)
@@ -1940,6 +1956,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
case CPU_PPC_440EP: /* 440 EP family */
@@ -1959,6 +1976,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
/* Embedded PowerPC from Freescale */
@@ -1994,6 +2012,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
#if defined (TODO)
@@ -2038,6 +2057,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_ways = 2;
env->id_tlbs = 0;
env->id_tlbs = 0;
+ /* XXX: TODO: allocate internal IRQ controller */
break;
case CPU_PPC_602: /* PowerPC 602 */
@@ -2060,6 +2080,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_603: /* PowerPC 603 */
@@ -2087,6 +2109,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_G2: /* PowerPC G2 family */
@@ -2123,6 +2147,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_604: /* PowerPC 604 */
@@ -2146,6 +2172,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_74x: /* PowerPC 740 / 750 */
@@ -2178,6 +2206,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_750FX10: /* IBM PowerPC 750 FX */
@@ -2213,6 +2243,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
case CPU_PPC_755_10: /* PowerPC 755 */
@@ -2257,6 +2289,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
break;
#if defined (TODO)
@@ -2326,6 +2360,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
default:
gen_spr_generic(env);
+ /* XXX: TODO: allocate internal IRQ controller */
break;
}
if (env->nb_BATs == -1)