summary refs log tree commit diff stats
path: root/hw/sun4m.c
diff options
context:
space:
mode:
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-27 16:42:29 +0000
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-27 16:42:29 +0000
commitb3a2319792ad5c0f0f8c3d2f4d02b95fd7efbc69 (patch)
tree00baf383db94162247f494899dcd71a3d24c033c /hw/sun4m.c
parentd7edfd27021b36c5ca065293e13639e139ddd5da (diff)
downloadfocaccia-qemu-b3a2319792ad5c0f0f8c3d2f4d02b95fd7efbc69.tar.gz
focaccia-qemu-b3a2319792ad5c0f0f8c3d2f4d02b95fd7efbc69.zip
Use qemu_irqs between CPUs and interrupt controller
Fix interrupt priority handling which prevented SMP from working


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2875 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/sun4m.c')
-rw-r--r--hw/sun4m.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/hw/sun4m.c b/hw/sun4m.c
index ed3be4e1d0..c69d732f91 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+//#define DEBUG_IRQ
 
 /*
  * Sun4m architecture was used in the following machines:
@@ -38,6 +39,13 @@
  * See for example: http://www.sunhelp.org/faq/sunref1.html
  */
 
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, args...)                           \
+    do { printf("CPUIRQ: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
 #define KERNEL_LOAD_ADDR     0x00004000
 #define CMDLINE_ADDR         0x007ff000
 #define INITRD_LOAD_ADDR     0x00800000
@@ -46,6 +54,7 @@
 #define PROM_FILENAME	     "openbios-sparc32"
 
 #define MAX_CPUS 16
+#define MAX_PILS 16
 
 struct hwdef {
     target_phys_addr_t iommu_base, slavio_base;
@@ -233,6 +242,33 @@ void irq_info()
     slavio_irq_info(slavio_intctl);
 }
 
+static void cpu_set_irq(void *opaque, int irq, int level)
+{
+    CPUState *env = opaque;
+
+    if (level) {
+        DPRINTF("Raise CPU IRQ %d\n", irq);
+
+        env->halted = 0;
+
+        if (env->interrupt_index == 0 ||
+            ((env->interrupt_index & ~15) == TT_EXTINT &&
+             (env->interrupt_index & 15) < irq)) {
+            env->interrupt_index = TT_EXTINT | irq;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            DPRINTF("Not triggered, pending exception %d\n",
+                    env->interrupt_index);
+        }
+    } else {
+        DPRINTF("Lower CPU IRQ %d\n", irq);
+    }
+}
+
+static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+{
+}
+
 static void *slavio_misc;
 
 void qemu_system_powerdown(void)
@@ -264,7 +300,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
     unsigned int i;
     void *iommu, *espdma, *ledma, *main_esp;
     const sparc_def_t *def;
-    qemu_irq *slavio_irq, *slavio_cpu_irq,
+    qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,
         *espdma_irq, *ledma_irq;
 
     /* init CPUs */
@@ -273,6 +309,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
         fprintf(stderr, "Unable to find Sparc CPU definition\n");
         exit(1);
     }
+
     for(i = 0; i < smp_cpus; i++) {
         env = cpu_init();
         cpu_sparc_register(env, def);
@@ -284,7 +321,12 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
             env->halted = 1;
         }
         register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
+        cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
     }
+
+    for (i = smp_cpus; i < MAX_CPUS; i++)
+        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, 0);
 
@@ -293,10 +335,9 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
                                        hwdef->intctl_base + 0x10000ULL,
                                        &hwdef->intbit_to_level[0],
                                        &slavio_irq, &slavio_cpu_irq,
+                                       cpu_irqs,
                                        hwdef->clock_irq);
-    for(i = 0; i < smp_cpus; i++) {
-        slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
-    }
+
     espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
                               iommu, &espdma_irq);
     ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,