From d0dfae6e91d9b2044523ed4db890860f898af86b Mon Sep 17 00:00:00 2001 From: j_mayer Date: Mon, 16 Apr 2007 07:34:39 +0000 Subject: Add bus model (or input pins) into PowerPC CPU flags. Add PowerPC 970 bus and exceptions model. Add code provision for PowerPC 970 instanciation. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2680 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ppc.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ target-ppc/cpu.h | 119 +++++++++++++++++++++++++++--------------- target-ppc/helper.c | 7 +++ target-ppc/translate_init.c | 32 ++++++++++++ 4 files changed, 238 insertions(+), 42 deletions(-) diff --git a/hw/ppc.c b/hw/ppc.c index b16f305302..62e9e1b1e7 100644 --- a/hw/ppc.c +++ b/hw/ppc.c @@ -161,6 +161,128 @@ void ppc6xx_irq_init (CPUState *env) env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6); } +/* PowerPC 970 internal IRQ controller */ +static void ppc970_set_irq (void *opaque, int pin, int level) +{ + CPUState *env = opaque; + int cur_level; + +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: env %p pin %d level %d\n", __func__, + env, pin, level); + } +#endif + cur_level = (env->irq_input_state >> pin) & 1; + /* Don't generate spurious events */ + if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { + switch (pin) { + case PPC970_INPUT_INT: + /* Level sensitive - active high */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the external IRQ state to %d\n", + __func__, level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_EXT, level); + break; + case PPC970_INPUT_THINT: + /* Level sensitive - active high */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__, + level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_THERM, level); + break; + case PPC970_INPUT_MCP: + /* Negative edge sensitive */ + /* XXX: TODO: actual reaction may depends on HID0 status + * 603/604/740/750: check HID0[EMCP] + */ + if (cur_level == 1 && level == 0) { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: raise machine check state\n", + __func__); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); + } + break; + case PPC970_INPUT_CKSTP: + /* Level sensitive - active low */ + /* XXX: TODO: relay the signal to CKSTP_OUT pin */ + if (level) { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: stop the CPU\n", __func__); + } +#endif + env->halted = 1; + } else { +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: restart the CPU\n", __func__); + } +#endif + env->halted = 0; + } + break; + case PPC970_INPUT_HRESET: + /* Level sensitive - active low */ + if (level) { +#if 0 // XXX: TOFIX +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: reset the CPU\n", __func__); + } +#endif + cpu_reset(env); +#endif + } + break; + case PPC970_INPUT_SRESET: +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the RESET IRQ state to %d\n", + __func__, level); + } +#endif + ppc_set_irq(env, PPC_INTERRUPT_RESET, level); + break; + case PPC970_INPUT_TBEN: +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: set the TBEN state to %d\n", __func__, + level); + } +#endif + /* XXX: TODO */ + break; + default: + /* Unknown pin - do nothing */ +#if defined(PPC_DEBUG_IRQ) + if (loglevel & CPU_LOG_INT) { + fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin); + } +#endif + return; + } + if (level) + env->irq_input_state |= 1 << pin; + else + env->irq_input_state &= ~(1 << pin); + } +} + +void ppc970_irq_init (CPUState *env) +{ + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7); +} + /* PowerPC 405 internal IRQ controller */ static void ppc405_set_irq (void *opaque, int pin, int level) { diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 740bc1b4cf..1e309f91d1 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -393,51 +393,60 @@ enum { /* CPU run-time flags (MMU and exception model) */ enum { /* MMU model */ - PPC_FLAGS_MMU_MASK = 0x0000000F, + PPC_FLAGS_MMU_MASK = 0x000000FF, /* Standard 32 bits PowerPC MMU */ - PPC_FLAGS_MMU_32B = 0x00000000, + PPC_FLAGS_MMU_32B = 0x00000000, /* Standard 64 bits PowerPC MMU */ - PPC_FLAGS_MMU_64B = 0x00000001, + PPC_FLAGS_MMU_64B = 0x00000001, /* PowerPC 601 MMU */ - PPC_FLAGS_MMU_601 = 0x00000002, + PPC_FLAGS_MMU_601 = 0x00000002, /* PowerPC 6xx MMU with software TLB */ - PPC_FLAGS_MMU_SOFT_6xx = 0x00000003, + PPC_FLAGS_MMU_SOFT_6xx = 0x00000003, /* PowerPC 4xx MMU with software TLB */ - PPC_FLAGS_MMU_SOFT_4xx = 0x00000004, + PPC_FLAGS_MMU_SOFT_4xx = 0x00000004, /* PowerPC 403 MMU */ - PPC_FLAGS_MMU_403 = 0x00000005, - /* Freescale e500 MMU model */ - PPC_FLAGS_MMU_e500 = 0x00000006, + PPC_FLAGS_MMU_403 = 0x00000005, + /* BookE FSL MMU model */ + PPC_FLAGS_MMU_BOOKE_FSL = 0x00000006, /* BookE MMU model */ - PPC_FLAGS_MMU_BOOKE = 0x00000007, + PPC_FLAGS_MMU_BOOKE = 0x00000007, + /* 64 bits "bridge" PowerPC MMU */ + PPC_FLAGS_MMU_64BRIDGE = 0x00000008, /* Exception model */ - PPC_FLAGS_EXCP_MASK = 0x000000F0, + PPC_FLAGS_EXCP_MASK = 0x0000FF00, /* Standard PowerPC exception model */ - PPC_FLAGS_EXCP_STD = 0x00000000, + PPC_FLAGS_EXCP_STD = 0x00000000, /* PowerPC 40x exception model */ - PPC_FLAGS_EXCP_40x = 0x00000010, + PPC_FLAGS_EXCP_40x = 0x00000100, /* PowerPC 601 exception model */ - PPC_FLAGS_EXCP_601 = 0x00000020, + PPC_FLAGS_EXCP_601 = 0x00000200, /* PowerPC 602 exception model */ - PPC_FLAGS_EXCP_602 = 0x00000030, + PPC_FLAGS_EXCP_602 = 0x00000300, /* PowerPC 603 exception model */ - PPC_FLAGS_EXCP_603 = 0x00000040, + PPC_FLAGS_EXCP_603 = 0x00000400, /* PowerPC 604 exception model */ - PPC_FLAGS_EXCP_604 = 0x00000050, + PPC_FLAGS_EXCP_604 = 0x00000500, /* PowerPC 7x0 exception model */ - PPC_FLAGS_EXCP_7x0 = 0x00000060, + PPC_FLAGS_EXCP_7x0 = 0x00000600, /* PowerPC 7x5 exception model */ - PPC_FLAGS_EXCP_7x5 = 0x00000070, + PPC_FLAGS_EXCP_7x5 = 0x00000700, /* PowerPC 74xx exception model */ - PPC_FLAGS_EXCP_74xx = 0x00000080, + PPC_FLAGS_EXCP_74xx = 0x00000800, /* PowerPC 970 exception model */ - PPC_FLAGS_EXCP_970 = 0x00000090, + PPC_FLAGS_EXCP_970 = 0x00000900, /* BookE exception model */ - PPC_FLAGS_EXCP_BOOKE = 0x000000A0, + PPC_FLAGS_EXCP_BOOKE = 0x00000A00, + /* Input pins model */ + PPC_FLAGS_INPUT_MASK = 0x000F0000, + PPC_FLAGS_INPUT_6xx = 0x00000000, + PPC_FLAGS_INPUT_BookE = 0x00010000, + PPC_FLAGS_INPUT_40x = 0x00020000, + PPC_FLAGS_INPUT_970 = 0x00030000, }; #define PPC_MMU(env) (env->flags & PPC_FLAGS_MMU_MASK) #define PPC_EXCP(env) (env->flags & PPC_FLAGS_EXCP_MASK) +#define PPC_INPUT(env) (env->flags & PPC_FLAGS_INPUT_MASK) /*****************************************************************************/ /* Supported instruction set definitions */ @@ -454,64 +463,78 @@ enum { #define PPC_INSNS_403 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO | \ PPC_MEM_TLBIA | PPC_4xx_COMMON | PPC_40x_EXCP | \ PPC_40x_SPEC) -#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x) +#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x | \ + PPC_FLAGS_INPUT_40x) /* PowerPC 405 */ #define PPC_INSNS_405 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO | \ PPC_CACHE_OPT | PPC_MEM_TLBIA | PPC_TB | \ PPC_4xx_COMMON | PPC_40x_SPEC | PPC_40x_EXCP | \ PPC_405_MAC) -#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x) +#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x | \ + PPC_FLAGS_INPUT_40x) /* PowerPC 440 */ #define PPC_INSNS_440 (PPC_INSNS_EMB | PPC_CACHE_OPT | PPC_BOOKE | \ PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC) -#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE) +#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE | \ + PPC_FLAGS_INPUT_BookE) /* Generic BookE PowerPC */ #define PPC_INSNS_BOOKE (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO | \ PPC_FLOAT | PPC_FLOAT_OPT | PPC_CACHE_OPT) -#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE) +#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE | \ + PPC_FLAGS_INPUT_BookE) /* e500 core */ #define PPC_INSNS_E500 (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO | \ PPC_CACHE_OPT | PPC_E500_VECTOR) -#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x) +#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x | \ + PPC_FLAGS_INPUT_BookE) /* Non-embedded PowerPC */ #define PPC_INSNS_COMMON (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \ - PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE) + PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE) /* PowerPC 601 */ #define PPC_INSNS_601 (PPC_INSNS_COMMON | PPC_EXTERN | PPC_POWER_BR) -#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601) +#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 602 */ #define PPC_INSNS_602 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \ PPC_MEM_TLBSYNC | PPC_TB | PPC_602_SPEC) -#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602) +#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 603 */ #define PPC_INSNS_603 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \ PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB) -#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603) +#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC G2 */ #define PPC_INSNS_G2 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \ PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB) -#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603) +#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 604 */ #define PPC_INSNS_604 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \ PPC_MEM_TLBSYNC | PPC_TB) -#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604) +#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 740/750 (aka G3) */ #define PPC_INSNS_7x0 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \ PPC_MEM_TLBSYNC | PPC_TB) -#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0) +#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 745/755 */ #define PPC_INSNS_7x5 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \ PPC_MEM_TLBSYNC | PPC_TB | PPC_6xx_TLB) -#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5) +#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5 | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 74xx (aka G4) */ #define PPC_INSNS_74xx (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_ALTIVEC | \ PPC_MEM_TLBSYNC | PPC_TB) -#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx) +#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx | \ + PPC_FLAGS_INPUT_6xx) /* PowerPC 970 (aka G5) */ #define PPC_INSNS_970 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_FLOAT_OPT | \ PPC_ALTIVEC | PPC_MEM_TLBSYNC | PPC_TB | \ PPC_64B | PPC_64_BRIDGE | PPC_SLBI) -#define PPC_FLAGS_970 (PPC_FLAGS_MMU_64B | PPC_FLAGS_EXCP_970) +#define PPC_FLAGS_970 (PPC_FLAGS_MMU_64BRIDGE | PPC_FLAGS_EXCP_970 | \ + PPC_FLAGS_INPUT_970) /* Default PowerPC will be 604/970 */ #define PPC_INSNS_PPC32 PPC_INSNS_604 @@ -1347,6 +1370,17 @@ enum { PPC405_INPUT_DEBUG = 6, }; +enum { + /* PowerPC 970 input pins */ + PPC970_INPUT_HRESET = 0, + PPC970_INPUT_SRESET = 1, + PPC970_INPUT_CKSTP = 2, + PPC970_INPUT_TBEN = 3, + PPC970_INPUT_MCP = 4, + PPC970_INPUT_INT = 5, + PPC970_INPUT_THINT = 6, +}; + /* Hardware exceptions definitions */ enum { /* External hardware exception sources */ @@ -1356,12 +1390,13 @@ enum { PPC_INTERRUPT_SMI = 3, /* System management interrupt */ PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */ PPC_INTERRUPT_DEBUG = 5, /* External debug exception */ + PPC_INTERRUPT_THERM = 6, /* Thermal 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 */ + PPC_INTERRUPT_DECR = 7, /* Decrementer exception */ + PPC_INTERRUPT_HDECR = 8, /* Hypervisor decrementer exception */ + PPC_INTERRUPT_PIT = 9, /* Programmable inteval timer interrupt */ + PPC_INTERRUPT_FIT = 10, /* Fixed interval timer interrupt */ + PPC_INTERRUPT_WDT = 11, /* Watchdog timer interrupt */ }; /*****************************************************************************/ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index aac7907820..161cc1b14b 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2003,6 +2003,13 @@ void ppc_hw_interrupt (CPUPPCState *env) env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT); #endif raised = 1; +#if 0 // TODO + /* Thermal interrupt */ + } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { + env->exception_index = EXCP_970_THRM; + env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); + raised = 1; +#endif } #if 0 // TODO /* External debug exception */ diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index c7a732454e..018512328e 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -48,6 +48,7 @@ void glue(glue(ppc, name),_irq_init) (CPUPPCState *env); #endif PPC_IRQ_INIT_FN(405); PPC_IRQ_INIT_FN(6xx); +PPC_IRQ_INIT_FN(970); /* Generic callbacks: * do nothing but store/retrieve spr value @@ -2350,6 +2351,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) case CPU_PPC_POWER5: /* Power 5 */ case CPU_PPC_POWER5P: /* Power 5+ */ #endif + break; + case CPU_PPC_970: /* PowerPC 970 */ case CPU_PPC_970FX10: /* PowerPC 970 FX */ case CPU_PPC_970FX20: @@ -2358,12 +2361,41 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) case CPU_PPC_970FX31: case CPU_PPC_970MP10: /* PowerPC 970 MP */ case CPU_PPC_970MP11: + gen_spr_generic(env); + gen_spr_ne_601(env); + /* XXX: not correct */ + gen_low_BATs(env); + /* Time base */ + gen_tbl(env); + gen_spr_7xx(env); + /* Hardware implementation registers */ + /* XXX : not implemented */ + spr_register(env, SPR_HID0, "HID0", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_HID1, "HID1", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_750_HID2, "HID2", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* Allocate hardware IRQ controller */ + ppc970_irq_init(env); + break; + #if defined (TODO) case CPU_PPC_CELL10: /* Cell family */ case CPU_PPC_CELL20: case CPU_PPC_CELL30: case CPU_PPC_CELL31: #endif + break; + #if defined (TODO) case CPU_PPC_RS64: /* Apache (RS64/A35) */ case CPU_PPC_RS64II: /* NorthStar (RS64-II/A50) */ -- cgit v1.2.1