Commit e9df014c0b433ecd9785db4a423e472bc3db386a

Authored by j_mayer
1 parent 682c4f15

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
cpu-exec.c
... ... @@ -467,16 +467,14 @@ int cpu_exec(CPUState *env1)
467 467 }
468 468 #endif
469 469 if (interrupt_request & CPU_INTERRUPT_HARD) {
470   - if (ppc_hw_interrupt(env) == 1) {
471   - /* Some exception was raised */
472   - if (env->pending_interrupts == 0)
473   - env->interrupt_request &= ~CPU_INTERRUPT_HARD;
  470 + ppc_hw_interrupt(env);
  471 + if (env->pending_interrupts == 0)
  472 + env->interrupt_request &= ~CPU_INTERRUPT_HARD;
474 473 #if defined(__sparc__) && !defined(HOST_SOLARIS)
475   - tmp_T0 = 0;
  474 + tmp_T0 = 0;
476 475 #else
477   - T0 = 0;
  476 + T0 = 0;
478 477 #endif
479   - }
480 478 }
481 479 #elif defined(TARGET_MIPS)
482 480 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
... ...
hw/openpic.c
... ... @@ -159,18 +159,18 @@ typedef struct IRQ_dst_t {
159 159 uint32_t pcsr; /* CPU sensitivity register */
160 160 IRQ_queue_t raised;
161 161 IRQ_queue_t servicing;
162   - CPUState *env;
  162 + qemu_irq *irqs;
163 163 } IRQ_dst_t;
164 164  
165 165 typedef struct openpic_t {
166 166 PCIDevice pci_dev;
167   - SetIRQFunc *set_irq;
168 167 int mem_index;
169 168 /* Global registers */
170 169 uint32_t frep; /* Feature reporting register */
171 170 uint32_t glbc; /* Global configuration register */
172 171 uint32_t micr; /* MPIC interrupt configuration register */
173 172 uint32_t veni; /* Vendor identification register */
  173 + uint32_t pint; /* Processor initialization register */
174 174 uint32_t spve; /* Spurious vector register */
175 175 uint32_t tifr; /* Timer frequency reporting register */
176 176 /* Source registers */
... ... @@ -196,6 +196,8 @@ typedef struct openpic_t {
196 196 uint32_t mbr; /* Mailbox register */
197 197 } mailboxes[MAX_MAILBOXES];
198 198 #endif
  199 + /* IRQ out is used when in bypass mode (not implemented) */
  200 + qemu_irq irq_out;
199 201 } openpic_t;
200 202  
201 203 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
... ... @@ -255,19 +257,34 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
255 257 priority = IPVP_PRIORITY(src->ipvp);
256 258 if (priority <= dst->pctp) {
257 259 /* Too low priority */
  260 + DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
  261 + __func__, n_IRQ, n_CPU);
258 262 return;
259 263 }
260 264 if (IRQ_testbit(&dst->raised, n_IRQ)) {
261 265 /* Interrupt miss */
  266 + DPRINTF("%s: IRQ %d was missed on CPU %d\n",
  267 + __func__, n_IRQ, n_CPU);
262 268 return;
263 269 }
264 270 set_bit(&src->ipvp, IPVP_ACTIVITY);
265 271 IRQ_setbit(&dst->raised, n_IRQ);
266   - if (priority > dst->raised.priority) {
267   - IRQ_get_next(opp, &dst->raised);
268   - DPRINTF("Raise CPU IRQ fn %p env %p\n", opp->set_irq, dst->env);
269   - opp->set_irq(dst->env, OPENPIC_EVT_INT, 1);
  272 + if (priority < dst->raised.priority) {
  273 + /* An higher priority IRQ is already raised */
  274 + DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
  275 + __func__, n_IRQ, dst->raised.next, n_CPU);
  276 + return;
  277 + }
  278 + IRQ_get_next(opp, &dst->raised);
  279 + if (IRQ_get_next(opp, &dst->servicing) != -1 &&
  280 + priority < dst->servicing.priority) {
  281 + DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
  282 + __func__, n_IRQ, dst->servicing.next, n_CPU);
  283 + /* Already servicing a higher priority IRQ */
  284 + return;
270 285 }
  286 + DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
  287 + qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
271 288 }
272 289  
273 290 /* update pic state because registers for n_IRQ have changed value */
... ... @@ -280,27 +297,34 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
280 297  
281 298 if (!src->pending) {
282 299 /* no irq pending */
  300 + DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
283 301 return;
284 302 }
285 303 if (test_bit(&src->ipvp, IPVP_MASK)) {
286 304 /* Interrupt source is disabled */
  305 + DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
287 306 return;
288 307 }
289 308 if (IPVP_PRIORITY(src->ipvp) == 0) {
290 309 /* Priority set to zero */
  310 + DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
291 311 return;
292 312 }
293 313 if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
294 314 /* IRQ already active */
  315 + DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
295 316 return;
296 317 }
297 318 if (src->ide == 0x00000000) {
298 319 /* No target */
  320 + DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
299 321 return;
300 322 }
301 323  
302   - if (!test_bit(&src->ipvp, IPVP_MODE) ||
303   - src->ide == (1 << src->last_cpu)) {
  324 + if (src->ide == (1 << src->last_cpu)) {
  325 + /* Only one CPU is allowed to receive this IRQ */
  326 + IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
  327 + } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
304 328 /* Directed delivery mode */
305 329 for (i = 0; i < opp->nb_cpus; i++) {
306 330 if (test_bit(&src->ide, i))
... ... @@ -308,9 +332,8 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
308 332 }
309 333 } else {
310 334 /* Distributed delivery mode */
311   - /* XXX: incorrect code */
312   - for (i = src->last_cpu; i < src->last_cpu; i++) {
313   - if (i == MAX_IRQ)
  335 + for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
  336 + if (i == opp->nb_cpus)
314 337 i = 0;
315 338 if (test_bit(&src->ide, i)) {
316 339 IRQ_local_pipe(opp, i, n_IRQ);
... ... @@ -350,6 +373,7 @@ static void openpic_reset (openpic_t *opp)
350 373 /* Initialise controller registers */
351 374 opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
352 375 opp->veni = VENI;
  376 + opp->pint = 0x00000000;
353 377 opp->spve = 0x000000FF;
354 378 opp->tifr = 0x003F7A00;
355 379 /* ? */
... ... @@ -360,7 +384,7 @@ static void openpic_reset (openpic_t *opp)
360 384 opp->src[i].ide = 0x00000000;
361 385 }
362 386 /* Initialise IRQ destinations */
363   - for (i = 0; i < opp->nb_cpus; i++) {
  387 + for (i = 0; i < MAX_CPU; i++) {
364 388 opp->dst[i].pctp = 0x0000000F;
365 389 opp->dst[i].pcsr = 0x00000000;
366 390 memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
... ... @@ -511,6 +535,8 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx,
511 535 static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
512 536 {
513 537 openpic_t *opp = opaque;
  538 + IRQ_dst_t *dst;
  539 + int idx;
514 540  
515 541 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
516 542 if (addr & 0xF)
... ... @@ -530,11 +556,18 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
530 556 case 0x80: /* VENI */
531 557 break;
532 558 case 0x90: /* PINT */
533   - /* XXX: Should be able to reset any CPU */
534   - if (val & 1) {
535   - DPRINTF("Reset CPU IRQ\n");
536   - // opp->set_irq(dst->env, OPENPIC_EVT_RESET, 1);
  559 + for (idx = 0; idx < opp->nb_cpus; idx++) {
  560 + if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
  561 + DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
  562 + dst = &opp->dst[idx];
  563 + qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
  564 + } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
  565 + DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
  566 + dst = &opp->dst[idx];
  567 + qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
  568 + }
537 569 }
  570 + opp->pint = val;
538 571 break;
539 572 #if MAX_IPI > 0
540 573 case 0xA0: /* IPI_IPVP */
... ... @@ -735,7 +768,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
735 768 openpic_t *opp = opaque;
736 769 IRQ_src_t *src;
737 770 IRQ_dst_t *dst;
738   - int idx, n_IRQ;
  771 + int idx, s_IRQ, n_IRQ;
739 772  
740 773 DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
741 774 if (addr & 0xF)
... ... @@ -770,21 +803,21 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
770 803 break;
771 804 case 0xB0: /* PEOI */
772 805 DPRINTF("PEOI\n");
773   - n_IRQ = IRQ_get_next(opp, &dst->servicing);
774   - IRQ_resetbit(&dst->servicing, n_IRQ);
  806 + s_IRQ = IRQ_get_next(opp, &dst->servicing);
  807 + IRQ_resetbit(&dst->servicing, s_IRQ);
775 808 dst->servicing.next = -1;
776   - src = &opp->src[n_IRQ];
777 809 /* Set up next servicing IRQ */
778   - IRQ_get_next(opp, &dst->servicing);
779   - /* Check queued interrupts. */
780   - n_IRQ = IRQ_get_next(opp, &dst->raised);
781   - if (n_IRQ != -1) {
782   - src = &opp->src[n_IRQ];
783   - if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
784   - DPRINTF("Raise CPU IRQ\n");
785   - opp->set_irq(dst->env, OPENPIC_EVT_INT, 1);
786   - }
787   - }
  810 + s_IRQ = IRQ_get_next(opp, &dst->servicing);
  811 + /* Check queued interrupts. */
  812 + n_IRQ = IRQ_get_next(opp, &dst->raised);
  813 + src = &opp->src[n_IRQ];
  814 + if (n_IRQ != -1 &&
  815 + (s_IRQ == -1 ||
  816 + IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
  817 + DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
  818 + idx, n_IRQ);
  819 + qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
  820 + }
788 821 break;
789 822 default:
790 823 break;
... ... @@ -815,11 +848,13 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
815 848 retval = idx;
816 849 break;
817 850 case 0xA0: /* PIAC */
  851 + DPRINTF("Lower OpenPIC INT output\n");
  852 + qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
818 853 n_IRQ = IRQ_get_next(opp, &dst->raised);
819 854 DPRINTF("PIAC: irq=%d\n", n_IRQ);
820 855 if (n_IRQ == -1) {
821 856 /* No more interrupt pending */
822   - retval = opp->spve;
  857 + retval = IPVP_VECTOR(opp->spve);
823 858 } else {
824 859 src = &opp->src[n_IRQ];
825 860 if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
... ... @@ -964,8 +999,8 @@ static void openpic_map(PCIDevice *pci_dev, int region_num,
964 999 #endif
965 1000 }
966 1001  
967   -qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
968   - int *pmem_index, int nb_cpus, CPUState **envp)
  1002 +qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
  1003 + qemu_irq **irqs, qemu_irq irq_out)
969 1004 {
970 1005 openpic_t *opp;
971 1006 uint8_t *pci_conf;
... ... @@ -995,7 +1030,6 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
995 1030 } else {
996 1031 opp = qemu_mallocz(sizeof(openpic_t));
997 1032 }
998   - opp->set_irq = set_irq;
999 1033 opp->mem_index = cpu_register_io_memory(0, openpic_read,
1000 1034 openpic_write, opp);
1001 1035  
... ... @@ -1020,9 +1054,11 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
1020 1054 opp->src[i].type = IRQ_INTERNAL;
1021 1055 }
1022 1056 for (i = 0; i < nb_cpus; i++)
1023   - opp->dst[i].env = envp[i];
  1057 + opp->dst[i].irqs = irqs[i];
  1058 + opp->irq_out = irq_out;
1024 1059 openpic_reset(opp);
1025 1060 if (pmem_index)
1026 1061 *pmem_index = opp->mem_index;
  1062 +
1027 1063 return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
1028 1064 }
... ...
hw/ppc.c
1 1 /*
2   - * QEMU generic PPC hardware System Emulator
  2 + * QEMU generic PowerPC hardware System Emulator
3 3 *
4 4 * Copyright (c) 2003-2007 Jocelyn Mayer
5 5 *
... ... @@ -24,18 +24,13 @@
24 24 #include "vl.h"
25 25 #include "m48t59.h"
26 26  
  27 +//#define PPC_DEBUG_IRQ
  28 +
27 29 extern FILE *logfile;
28 30 extern int loglevel;
29 31  
30   -/*****************************************************************************/
31   -/* PowerPC internal fake IRQ controller
32   - * used to manage multiple sources hardware events
33   - */
34   -static void ppc_set_irq (void *opaque, int n_IRQ, int level)
  32 +void ppc_set_irq (CPUState *env, int n_IRQ, int level)
35 33 {
36   - CPUState *env;
37   -
38   - env = opaque;
39 34 if (level) {
40 35 env->pending_interrupts |= 1 << n_IRQ;
41 36 cpu_interrupt(env, CPU_INTERRUPT_HARD);
... ... @@ -44,49 +39,104 @@ static void ppc_set_irq (void *opaque, int n_IRQ, int level)
44 39 if (env->pending_interrupts == 0)
45 40 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
46 41 }
47   -#if 0
  42 +#if defined(PPC_DEBUG_IRQ)
48 43 printf("%s: %p n_IRQ %d level %d => pending %08x req %08x\n", __func__,
49 44 env, n_IRQ, level, env->pending_interrupts, env->interrupt_request);
50 45 #endif
51 46 }
52 47  
53   -void cpu_ppc_irq_init_cpu(CPUState *env)
  48 +/* PowerPC 6xx / 7xx internal IRQ controller */
  49 +static void ppc6xx_set_irq (void *opaque, int pin, int level)
54 50 {
55   - qemu_irq *qi;
56   - int i;
  51 + CPUState *env = opaque;
  52 + int cur_level;
57 53  
58   - qi = qemu_allocate_irqs(ppc_set_irq, env, 32);
59   - for (i = 0; i < 32; i++) {
60   - env->irq[i] = qi[i];
  54 +#if defined(PPC_DEBUG_IRQ)
  55 + printf("%s: env %p pin %d level %d\n", __func__, env, pin, level);
  56 +#endif
  57 + cur_level = (env->irq_input_state >> pin) & 1;
  58 + /* Don't generate spurious events */
  59 + if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0) || 0) {
  60 + switch (pin) {
  61 + case PPC_INPUT_INT:
  62 + /* Level sensitive - asserted high */
  63 +#if defined(PPC_DEBUG_IRQ)
  64 + printf("%s: set the external IRQ state to %d\n", __func__, level);
  65 +#endif
  66 + ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
  67 + break;
  68 + case PPC_INPUT_SMI:
  69 + /* Level sensitive - active high */
  70 +#if defined(PPC_DEBUG_IRQ)
  71 + printf("%s: set the SMI IRQ state to %d\n", __func__, level);
  72 +#endif
  73 + ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
  74 + break;
  75 + case PPC_INPUT_MCP:
  76 + /* Negative edge sensitive */
  77 + /* XXX: TODO: actual reaction may depends on HID0 status
  78 + * 603/604/740/750: check HID0[EMCP]
  79 + */
  80 + if (cur_level == 1 && level == 0) {
  81 +#if defined(PPC_DEBUG_IRQ)
  82 + printf("%s: raise machine check state\n", __func__);
  83 +#endif
  84 + ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
  85 + }
  86 + break;
  87 + case PPC_INPUT_CKSTP_IN:
  88 + /* Level sensitive - active low */
  89 + /* XXX: TODO: relay the signal to CKSTP_OUT pin */
  90 + if (level) {
  91 +#if defined(PPC_DEBUG_IRQ)
  92 + printf("%s: stop the CPU\n", __func__);
  93 +#endif
  94 + env->halted = 1;
  95 + } else {
  96 +#if defined(PPC_DEBUG_IRQ)
  97 + printf("%s: restart the CPU\n", __func__);
  98 +#endif
  99 + env->halted = 0;
  100 + }
  101 + break;
  102 + case PPC_INPUT_HRESET:
  103 + /* Level sensitive - active low */
  104 + if (level) {
  105 +#if 0 // XXX: TOFIX
  106 +#if defined(PPC_DEBUG_IRQ)
  107 + printf("%s: reset the CPU\n", __func__);
  108 +#endif
  109 + cpu_reset(env);
  110 +#endif
  111 + }
  112 + break;
  113 + case PPC_INPUT_SRESET:
  114 +#if defined(PPC_DEBUG_IRQ)
  115 + printf("%s: set the RESET IRQ state to %d\n", __func__, level);
  116 +#endif
  117 + ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
  118 + break;
  119 + default:
  120 + /* Unknown pin - do nothing */
  121 +#if defined(PPC_DEBUG_IRQ)
  122 + printf("%s: unknown IRQ pin %d\n", __func__, pin);
  123 +#endif
  124 + return;
  125 + }
  126 + if (level)
  127 + env->irq_input_state |= 1 << pin;
  128 + else
  129 + env->irq_input_state &= ~(1 << pin);
61 130 }
62 131 }
63 132  
64   -/* External IRQ callback from OpenPIC IRQ controller */
65   -void ppc_openpic_irq (void *opaque, int n_IRQ, int level)
  133 +void ppc6xx_irq_init (CPUState *env)
66 134 {
67   - switch (n_IRQ) {
68   - case OPENPIC_EVT_INT:
69   - n_IRQ = PPC_INTERRUPT_EXT;
70   - break;
71   - case OPENPIC_EVT_CINT:
72   - /* On PowerPC BookE, critical input use vector 0 */
73   - n_IRQ = PPC_INTERRUPT_RESET;
74   - break;
75   - case OPENPIC_EVT_MCK:
76   - n_IRQ = PPC_INTERRUPT_MCK;
77   - break;
78   - case OPENPIC_EVT_DEBUG:
79   - n_IRQ = PPC_INTERRUPT_DEBUG;
80   - break;
81   - case OPENPIC_EVT_RESET:
82   - qemu_system_reset_request();
83   - return;
84   - }
85   - ppc_set_irq(opaque, n_IRQ, level);
  135 + env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
86 136 }
87 137  
88 138 /*****************************************************************************/
89   -/* PPC time base and decrementer emulation */
  139 +/* PowerPC time base and decrementer emulation */
90 140 //#define DEBUG_TB
91 141  
92 142 struct ppc_tb_t {
... ...
hw/ppc_chrp.c
... ... @@ -23,6 +23,9 @@
23 23 */
24 24 #include "vl.h"
25 25  
  26 +/* SMP is not enabled, for now */
  27 +#define MAX_CPUS 1
  28 +
26 29 #define BIOS_FILENAME "ppc_rom.bin"
27 30 #define VGABIOS_FILENAME "video.x"
28 31 #define NVRAM_SIZE 0x2000
... ... @@ -296,9 +299,9 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
296 299 const char *cpu_model,
297 300 int is_heathrow)
298 301 {
299   - CPUState *env;
  302 + CPUState *env, *envs[MAX_CPUS];
300 303 char buf[1024];
301   - qemu_irq *pic;
  304 + qemu_irq *pic, **openpic_irqs;
302 305 m48t59_t *nvram;
303 306 int unin_memory;
304 307 int linux_boot, i;
... ... @@ -329,13 +332,13 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
329 332 if (def == NULL) {
330 333 cpu_abort(env, "Unable to find PowerPC CPU definition\n");
331 334 }
332   - cpu_ppc_register(env, def);
333   - cpu_ppc_irq_init_cpu(env);
334   -
335   - /* Set time-base frequency to 100 Mhz */
336   - cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
337   -
338   - env->osi_call = vga_osi_call;
  335 + for (i = 0; i < smp_cpus; i++) {
  336 + cpu_ppc_register(env, def);
  337 + /* Set time-base frequency to 100 Mhz */
  338 + cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
  339 + env->osi_call = vga_osi_call;
  340 + envs[i] = env;
  341 + }
339 342  
340 343 /* allocate RAM */
341 344 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
... ... @@ -458,7 +461,26 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
458 461 unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
459 462 cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
460 463  
461   - pic = openpic_init(NULL, &ppc_openpic_irq, &openpic_mem_index, 1, &env);
  464 + openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
  465 + openpic_irqs[0] =
  466 + qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
  467 + for (i = 0; i < smp_cpus; i++) {
  468 + /* Mac99 IRQ connection between OpenPIC outputs pins
  469 + * and PowerPC input pins
  470 + */
  471 + openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
  472 + openpic_irqs[i][OPENPIC_OUTPUT_INT] =
  473 + ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
  474 + openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
  475 + ((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
  476 + openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
  477 + ((qemu_irq *)env->irq_inputs)[PPC_INPUT_MCP];
  478 + openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Not connected ? */
  479 + openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
  480 + ((qemu_irq *)env->irq_inputs)[PPC_INPUT_HRESET]; /* Check this */
  481 + }
  482 + pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
  483 + openpic_irqs, NULL);
462 484 pci_bus = pci_pmac_init(pic);
463 485 /* init basic PC hardware */
464 486 pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
... ...
hw/ppc_prep.c
... ... @@ -548,7 +548,6 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
548 548 cpu_abort(env, "Unable to find PowerPC CPU definition\n");
549 549 }
550 550 cpu_ppc_register(env, def);
551   - cpu_ppc_irq_init_cpu(env);
552 551 /* Set time-base frequency to 100 Mhz */
553 552 cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
554 553  
... ... @@ -599,7 +598,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
599 598 }
600 599  
601 600 isa_mem_base = 0xc0000000;
602   - i8259 = i8259_init(first_cpu->irq[PPC_INTERRUPT_EXT]);
  601 + i8259 = i8259_init(first_cpu->irq_inputs[PPC_INPUT_INT]);
603 602 pci_bus = pci_prep_init(i8259);
604 603 // pci_bus = i440fx_init();
605 604 /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
... ...
target-ppc/cpu.h
... ... @@ -758,7 +758,13 @@ struct CPUPPCState {
758 758 int error_code;
759 759 int interrupt_request;
760 760 uint32_t pending_interrupts;
761   - void *irq[32];
  761 +#if !defined(CONFIG_USER_ONLY)
  762 + /* This is the IRQ controller, which is implementation dependant
  763 + * and only relevant when emulating a complete machine.
  764 + */
  765 + uint32_t irq_input_state;
  766 + void **irq_inputs;
  767 +#endif
762 768  
763 769 /* Those resources are used only during code translation */
764 770 /* Next instruction pointer */
... ... @@ -801,6 +807,7 @@ int cpu_ppc_signal_handler(int host_signum, void *pinfo,
801 807 void *puc);
802 808  
803 809 void do_interrupt (CPUPPCState *env);
  810 +void ppc_hw_interrupt (CPUPPCState *env);
804 811 void cpu_loop_exit(void);
805 812  
806 813 void dump_stack (CPUPPCState *env);
... ... @@ -1303,16 +1310,35 @@ enum {
1303 1310 /* Hardware interruption sources:
1304 1311 * all those exception can be raised simulteaneously
1305 1312 */
  1313 +/* Input pins definitions */
  1314 +enum {
  1315 + /* 6xx bus input pins */
  1316 + PPC_INPUT_HRESET = 0,
  1317 + PPC_INPUT_SRESET = 1,
  1318 + PPC_INPUT_CKSTP_IN = 2,
  1319 + PPC_INPUT_MCP = 3,
  1320 + PPC_INPUT_SMI = 4,
  1321 + PPC_INPUT_INT = 5,
  1322 + /* Embedded PowerPC input pins */
  1323 + PPC_INPUT_CINT = 6,
  1324 + PPC_INPUT_NB,
  1325 +};
  1326 +
  1327 +/* Hardware exceptions definitions */
1306 1328 enum {
1307   - PPC_INTERRUPT_RESET = 0, /* Reset / critical input */
1308   - PPC_INTERRUPT_MCK = 1, /* Machine check exception */
1309   - PPC_INTERRUPT_EXT = 2, /* External interrupt */
1310   - PPC_INTERRUPT_DECR = 3, /* Decrementer exception */
1311   - PPC_INTERRUPT_HDECR = 4, /* Hypervisor decrementer exception */
1312   - PPC_INTERRUPT_PIT = 5, /* Programmable inteval timer interrupt */
1313   - PPC_INTERRUPT_FIT = 6, /* Fixed interval timer interrupt */
1314   - PPC_INTERRUPT_WDT = 7, /* Watchdog timer interrupt */
1315   - PPC_INTERRUPT_DEBUG = 8, /* External debug exception */
  1329 + /* External hardware exception sources */
  1330 + PPC_INTERRUPT_RESET = 0, /* Reset exception */
  1331 + PPC_INTERRUPT_MCK = 1, /* Machine check exception */
  1332 + PPC_INTERRUPT_EXT = 2, /* External interrupt */
  1333 + PPC_INTERRUPT_SMI = 3, /* System management interrupt */
  1334 + PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */
  1335 + PPC_INTERRUPT_DEBUG = 5, /* External debug exception */
  1336 + /* Internal hardware exception sources */
  1337 + PPC_INTERRUPT_DECR = 6, /* Decrementer exception */
  1338 + PPC_INTERRUPT_HDECR = 7, /* Hypervisor decrementer exception */
  1339 + PPC_INTERRUPT_PIT = 8, /* Programmable inteval timer interrupt */
  1340 + PPC_INTERRUPT_FIT = 9, /* Fixed interval timer interrupt */
  1341 + PPC_INTERRUPT_WDT = 10, /* Watchdog timer interrupt */
1316 1342 };
1317 1343  
1318 1344 /*****************************************************************************/
... ...
target-ppc/helper.c
... ... @@ -1358,11 +1358,9 @@ void do_interrupt (CPUState *env)
1358 1358 env->exception_index = -1;
1359 1359 }
1360 1360  
1361   -int ppc_hw_interrupt (CPUState *env)
  1361 +void ppc_hw_interrupt (CPUState *env)
1362 1362 {
1363 1363 env->exception_index = -1;
1364   -
1365   - return 0;
1366 1364 }
1367 1365 #else /* defined (CONFIG_USER_ONLY) */
1368 1366 static void dump_syscall(CPUState *env)
... ... @@ -1927,7 +1925,7 @@ void do_interrupt (CPUState *env)
1927 1925 env->exception_index = EXCP_NONE;
1928 1926 }
1929 1927  
1930   -int ppc_hw_interrupt (CPUState *env)
  1928 +void ppc_hw_interrupt (CPUPPCState *env)
1931 1929 {
1932 1930 int raised = 0;
1933 1931  
... ... @@ -1940,6 +1938,9 @@ int ppc_hw_interrupt (CPUState *env)
1940 1938 /* Raise it */
1941 1939 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
1942 1940 /* External reset / critical input */
  1941 + /* XXX: critical input should be handled another way.
  1942 + * This code is not correct !
  1943 + */
1943 1944 env->exception_index = EXCP_RESET;
1944 1945 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
1945 1946 raised = 1;
... ... @@ -1984,7 +1985,12 @@ int ppc_hw_interrupt (CPUState *env)
1984 1985 /* External interrupt */
1985 1986 } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
1986 1987 env->exception_index = EXCP_EXTERNAL;
  1988 + /* Taking an external interrupt does not clear the external
  1989 + * interrupt status
  1990 + */
  1991 +#if 0
1987 1992 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
  1993 +#endif
1988 1994 raised = 1;
1989 1995 }
1990 1996 #if 0 // TODO
... ... @@ -1999,7 +2005,5 @@ int ppc_hw_interrupt (CPUState *env)
1999 2005 env->error_code = 0;
2000 2006 do_interrupt(env);
2001 2007 }
2002   -
2003   - return raised;
2004 2008 }
2005 2009 #endif /* !CONFIG_USER_ONLY */
... ...
target-ppc/translate_init.c
... ... @@ -35,6 +35,18 @@ struct ppc_def_t {
35 35 uint64_t msr_mask;
36 36 };
37 37  
  38 +/* For user-mode emulation, we don't emulate any IRQ controller */
  39 +#if defined(CONFIG_USER_ONLY)
  40 +#define PPC_IRQ_INIT_FN(name) \
  41 +static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \
  42 +{ \
  43 +}
  44 +#else
  45 +#define PPC_IRQ_INIT_FN(name) \
  46 +void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
  47 +#endif
  48 +PPC_IRQ_INIT_FN(6xx);
  49 +
38 50 /* Generic callbacks:
39 51 * do nothing but store/retrieve spr value
40 52 */
... ... @@ -1865,6 +1877,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1865 1877 env->nb_tlb = 64;
1866 1878 env->nb_ways = 1;
1867 1879 env->id_tlbs = 0;
  1880 + /* XXX: TODO: allocate internal IRQ controller */
1868 1881 break;
1869 1882  
1870 1883 case CPU_PPC_403GA: /* 403 GA family */
... ... @@ -1879,6 +1892,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1879 1892 env->nb_tlb = 64;
1880 1893 env->nb_ways = 1;
1881 1894 env->id_tlbs = 0;
  1895 + /* XXX: TODO: allocate internal IRQ controller */
1882 1896 break;
1883 1897  
1884 1898 case CPU_PPC_405CR: /* 405 GP/CR family */
... ... @@ -1895,6 +1909,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1895 1909 env->nb_tlb = 64;
1896 1910 env->nb_ways = 1;
1897 1911 env->id_tlbs = 0;
  1912 + /* XXX: TODO: allocate internal IRQ controller */
1898 1913 break;
1899 1914  
1900 1915 case CPU_PPC_NPE405H: /* NPe405 H family */
... ... @@ -1909,6 +1924,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1909 1924 env->nb_tlb = 64;
1910 1925 env->nb_ways = 1;
1911 1926 env->id_tlbs = 0;
  1927 + /* XXX: TODO: allocate internal IRQ controller */
1912 1928 break;
1913 1929  
1914 1930 #if defined (TODO)
... ... @@ -1940,6 +1956,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1940 1956 env->nb_tlb = 64;
1941 1957 env->nb_ways = 1;
1942 1958 env->id_tlbs = 0;
  1959 + /* XXX: TODO: allocate internal IRQ controller */
1943 1960 break;
1944 1961  
1945 1962 case CPU_PPC_440EP: /* 440 EP family */
... ... @@ -1959,6 +1976,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1959 1976 env->nb_tlb = 64;
1960 1977 env->nb_ways = 1;
1961 1978 env->id_tlbs = 0;
  1979 + /* XXX: TODO: allocate internal IRQ controller */
1962 1980 break;
1963 1981  
1964 1982 /* Embedded PowerPC from Freescale */
... ... @@ -1994,6 +2012,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
1994 2012 env->nb_tlb = 64;
1995 2013 env->nb_ways = 1;
1996 2014 env->id_tlbs = 0;
  2015 + /* XXX: TODO: allocate internal IRQ controller */
1997 2016 break;
1998 2017  
1999 2018 #if defined (TODO)
... ... @@ -2038,6 +2057,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2038 2057 env->nb_ways = 2;
2039 2058 env->id_tlbs = 0;
2040 2059 env->id_tlbs = 0;
  2060 + /* XXX: TODO: allocate internal IRQ controller */
2041 2061 break;
2042 2062  
2043 2063 case CPU_PPC_602: /* PowerPC 602 */
... ... @@ -2060,6 +2080,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2060 2080 SPR_NOACCESS, SPR_NOACCESS,
2061 2081 &spr_read_generic, &spr_write_generic,
2062 2082 0x00000000);
  2083 + /* Allocate hardware IRQ controller */
  2084 + ppc6xx_irq_init(env);
2063 2085 break;
2064 2086  
2065 2087 case CPU_PPC_603: /* PowerPC 603 */
... ... @@ -2087,6 +2109,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2087 2109 SPR_NOACCESS, SPR_NOACCESS,
2088 2110 &spr_read_generic, &spr_write_generic,
2089 2111 0x00000000);
  2112 + /* Allocate hardware IRQ controller */
  2113 + ppc6xx_irq_init(env);
2090 2114 break;
2091 2115  
2092 2116 case CPU_PPC_G2: /* PowerPC G2 family */
... ... @@ -2123,6 +2147,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2123 2147 SPR_NOACCESS, SPR_NOACCESS,
2124 2148 &spr_read_generic, &spr_write_generic,
2125 2149 0x00000000);
  2150 + /* Allocate hardware IRQ controller */
  2151 + ppc6xx_irq_init(env);
2126 2152 break;
2127 2153  
2128 2154 case CPU_PPC_604: /* PowerPC 604 */
... ... @@ -2146,6 +2172,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2146 2172 SPR_NOACCESS, SPR_NOACCESS,
2147 2173 &spr_read_generic, &spr_write_generic,
2148 2174 0x00000000);
  2175 + /* Allocate hardware IRQ controller */
  2176 + ppc6xx_irq_init(env);
2149 2177 break;
2150 2178  
2151 2179 case CPU_PPC_74x: /* PowerPC 740 / 750 */
... ... @@ -2178,6 +2206,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2178 2206 SPR_NOACCESS, SPR_NOACCESS,
2179 2207 &spr_read_generic, &spr_write_generic,
2180 2208 0x00000000);
  2209 + /* Allocate hardware IRQ controller */
  2210 + ppc6xx_irq_init(env);
2181 2211 break;
2182 2212  
2183 2213 case CPU_PPC_750FX10: /* IBM PowerPC 750 FX */
... ... @@ -2213,6 +2243,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2213 2243 SPR_NOACCESS, SPR_NOACCESS,
2214 2244 &spr_read_generic, &spr_write_generic,
2215 2245 0x00000000);
  2246 + /* Allocate hardware IRQ controller */
  2247 + ppc6xx_irq_init(env);
2216 2248 break;
2217 2249  
2218 2250 case CPU_PPC_755_10: /* PowerPC 755 */
... ... @@ -2257,6 +2289,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2257 2289 SPR_NOACCESS, SPR_NOACCESS,
2258 2290 &spr_read_generic, &spr_write_generic,
2259 2291 0x00000000);
  2292 + /* Allocate hardware IRQ controller */
  2293 + ppc6xx_irq_init(env);
2260 2294 break;
2261 2295  
2262 2296 #if defined (TODO)
... ... @@ -2326,6 +2360,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
2326 2360  
2327 2361 default:
2328 2362 gen_spr_generic(env);
  2363 + /* XXX: TODO: allocate internal IRQ controller */
2329 2364 break;
2330 2365 }
2331 2366 if (env->nb_BATs == -1)
... ...
... ... @@ -854,16 +854,17 @@ void i440fx_init_memory_mappings(PCIDevice *d);
854 854 int piix4_init(PCIBus *bus, int devfn);
855 855  
856 856 /* openpic.c */
  857 +/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
857 858 enum {
858   - OPENPIC_EVT_INT = 0, /* IRQ */
859   - OPENPIC_EVT_CINT, /* critical IRQ */
860   - OPENPIC_EVT_MCK, /* Machine check event */
861   - OPENPIC_EVT_DEBUG, /* Inconditional debug event */
862   - OPENPIC_EVT_RESET, /* Core reset event */
  859 + OPENPIC_OUTPUT_INT = 0, /* IRQ */
  860 + OPENPIC_OUTPUT_CINT, /* critical IRQ */
  861 + OPENPIC_OUTPUT_MCK, /* Machine check event */
  862 + OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */
  863 + OPENPIC_OUTPUT_RESET, /* Core reset event */
  864 + OPENPIC_OUTPUT_NB,
863 865 };
864   -qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
865   - int *pmem_index, int nb_cpus,
866   - struct CPUState **envp);
  866 +qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
  867 + qemu_irq **irqs, qemu_irq irq_out);
867 868  
868 869 /* heathrow_pic.c */
869 870 qemu_irq *heathrow_pic_init(int *pmem_index);
... ... @@ -1145,9 +1146,6 @@ extern QEMUMachine shix_machine;
1145 1146  
1146 1147 #ifdef TARGET_PPC
1147 1148 /* PowerPC hardware exceptions management helpers */
1148   -void cpu_ppc_irq_init_cpu(CPUState *env);
1149   -void ppc_openpic_irq (void *opaque, int n_IRQ, int level);
1150   -int ppc_hw_interrupt (CPUState *env);
1151 1149 ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
1152 1150 #endif
1153 1151 void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
... ...