Commit b3a2319792ad5c0f0f8c3d2f4d02b95fd7efbc69

Authored by blueswir1
1 parent d7edfd27

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
hw/slavio_intctl.c
... ... @@ -44,6 +44,7 @@ do { printf("IRQ: " fmt , ##args); } while (0)
44 44 */
45 45  
46 46 #define MAX_CPUS 16
  47 +#define MAX_PILS 16
47 48  
48 49 typedef struct SLAVIO_INTCTLState {
49 50 uint32_t intreg_pending[MAX_CPUS];
... ... @@ -53,9 +54,10 @@ typedef struct SLAVIO_INTCTLState {
53 54 #ifdef DEBUG_IRQ_COUNT
54 55 uint64_t irq_count[32];
55 56 #endif
56   - CPUState *cpu_envs[MAX_CPUS];
  57 + qemu_irq *cpu_irqs[MAX_CPUS];
57 58 const uint32_t *intbit_to_level;
58 59 uint32_t cputimer_bit;
  60 + uint32_t pil_out[MAX_CPUS];
59 61 } SLAVIO_INTCTLState;
60 62  
61 63 #define INTCTL_MAXADDR 0xf
... ... @@ -213,67 +215,53 @@ void slavio_irq_info(void *opaque)
213 215 #endif
214 216 }
215 217  
  218 +static void raise_pil(SLAVIO_INTCTLState *s, unsigned int pil,
  219 + unsigned int cpu)
  220 +{
  221 + qemu_irq irq;
  222 + unsigned int oldmax;
  223 +
  224 + irq = s->cpu_irqs[cpu][pil];
  225 +
  226 +#ifdef DEBUG_IRQ_COUNT
  227 + s->irq_count[pil]++;
  228 +#endif
  229 + oldmax = s->pil_out[cpu];
  230 + if (oldmax > 0 && oldmax != pil)
  231 + qemu_irq_lower(s->cpu_irqs[cpu][oldmax]);
  232 + s->pil_out[cpu] = pil;
  233 + if (pil > 0)
  234 + qemu_irq_raise(irq);
  235 + DPRINTF("cpu %d pil %d\n", cpu, pil);
  236 +}
  237 +
216 238 static void slavio_check_interrupts(void *opaque)
217 239 {
218   - CPUState *env;
219 240 SLAVIO_INTCTLState *s = opaque;
220 241 uint32_t pending = s->intregm_pending;
221 242 unsigned int i, j, max = 0;
222 243  
223 244 pending &= ~s->intregm_disabled;
224 245  
225   - if (pending && !(s->intregm_disabled & 0x80000000)) {
226   - for (i = 0; i < 32; i++) {
227   - if (pending & (1 << i)) {
228   - if (max < s->intbit_to_level[i])
229   - max = s->intbit_to_level[i];
230   - }
231   - }
232   - env = s->cpu_envs[s->target_cpu];
233   - if (!env) {
234   - DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
235   - }
236   - else {
237   - if (env->halted)
238   - env->halted = 0;
239   - if (env->interrupt_index == 0) {
240   - DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
241   -#ifdef DEBUG_IRQ_COUNT
242   - s->irq_count[max]++;
243   -#endif
244   - env->interrupt_index = TT_EXTINT | max;
245   - cpu_interrupt(env, CPU_INTERRUPT_HARD);
246   - }
247   - else
248   - DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
249   - }
250   - }
251   - else
252   - DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
253   -
  246 + DPRINTF("pending %x disabled %x\n", pending, s->intregm_disabled);
254 247 for (i = 0; i < MAX_CPUS; i++) {
255 248 max = 0;
256   - env = s->cpu_envs[i];
257   - if (!env)
258   - continue;
  249 + if (pending && !(s->intregm_disabled & 0x80000000) &&
  250 + (i == s->target_cpu)) {
  251 + for (j = 0; j < 32; j++) {
  252 + if (pending & (1 << j)) {
  253 + if (max < s->intbit_to_level[j])
  254 + max = s->intbit_to_level[j];
  255 + }
  256 + }
  257 + }
259 258 for (j = 17; j < 32; j++) {
260 259 if (s->intreg_pending[i] & (1 << j)) {
261 260 if (max < j - 16)
262 261 max = j - 16;
263 262 }
264 263 }
265   - if (max > 0) {
266   - if (env->halted)
267   - env->halted = 0;
268   - if (env->interrupt_index == 0) {
269   - DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
270   -#ifdef DEBUG_IRQ_COUNT
271   - s->irq_count[max]++;
272   -#endif
273   - env->interrupt_index = TT_EXTINT | max;
274   - cpu_interrupt(env, CPU_INTERRUPT_HARD);
275   - }
276   - }
  264 + raise_pil(s, max, i);
277 265 }
278 266 }
279 267  
... ... @@ -284,22 +272,20 @@ static void slavio_check_interrupts(void *opaque)
284 272 static void slavio_set_irq(void *opaque, int irq, int level)
285 273 {
286 274 SLAVIO_INTCTLState *s = opaque;
287   -
288   - DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
289   - if (irq < 32) {
290   - uint32_t mask = 1 << irq;
291   - uint32_t pil = s->intbit_to_level[irq];
292   - if (pil > 0) {
293   - if (level) {
294   - s->intregm_pending |= mask;
295   - s->intreg_pending[s->target_cpu] |= 1 << pil;
296   - slavio_check_interrupts(s);
297   - }
298   - else {
299   - s->intregm_pending &= ~mask;
300   - s->intreg_pending[s->target_cpu] &= ~(1 << pil);
301   - }
302   - }
  275 + uint32_t mask = 1 << irq;
  276 + uint32_t pil = s->intbit_to_level[irq];
  277 +
  278 + DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, irq, pil,
  279 + level);
  280 + if (pil > 0) {
  281 + if (level) {
  282 + s->intregm_pending |= mask;
  283 + s->intreg_pending[s->target_cpu] |= 1 << pil;
  284 + } else {
  285 + s->intregm_pending &= ~mask;
  286 + s->intreg_pending[s->target_cpu] &= ~(1 << pil);
  287 + }
  288 + slavio_check_interrupts(s);
303 289 }
304 290 }
305 291  
... ... @@ -307,15 +293,12 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
307 293 {
308 294 SLAVIO_INTCTLState *s = opaque;
309 295  
310   - DPRINTF("Set cpu %d local level %d\n", cpu, level);
311   - if (!s->cpu_envs[cpu])
312   - return;
  296 + DPRINTF("Set cpu %d local timer level %d\n", cpu, level);
313 297  
314   - if (level) {
  298 + if (level)
315 299 s->intreg_pending[cpu] |= s->cputimer_bit;
316   - } else {
  300 + else
317 301 s->intreg_pending[cpu] &= ~s->cputimer_bit;
318   - }
319 302  
320 303 slavio_check_interrupts(s);
321 304 }
... ... @@ -363,18 +346,10 @@ static void slavio_intctl_reset(void *opaque)
363 346 s->target_cpu = 0;
364 347 }
365 348  
366   -void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
367   -{
368   - SLAVIO_INTCTLState *s = opaque;
369   -
370   - s->cpu_envs[cpu] = env;
371   -}
372   -
373 349 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
374 350 const uint32_t *intbit_to_level,
375 351 qemu_irq **irq, qemu_irq **cpu_irq,
376   - unsigned int cputimer)
377   -
  352 + qemu_irq **parent_irq, unsigned int cputimer)
378 353 {
379 354 int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
380 355 SLAVIO_INTCTLState *s;
... ... @@ -388,6 +363,7 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
388 363 slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
389 364 cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
390 365 slavio_intctl_io_memory);
  366 + s->cpu_irqs[i] = parent_irq[i];
391 367 }
392 368  
393 369 slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
... ...
hw/sun4m.c
... ... @@ -22,6 +22,7 @@
22 22 * THE SOFTWARE.
23 23 */
24 24 #include "vl.h"
  25 +//#define DEBUG_IRQ
25 26  
26 27 /*
27 28 * Sun4m architecture was used in the following machines:
... ... @@ -38,6 +39,13 @@
38 39 * See for example: http://www.sunhelp.org/faq/sunref1.html
39 40 */
40 41  
  42 +#ifdef DEBUG_IRQ
  43 +#define DPRINTF(fmt, args...) \
  44 + do { printf("CPUIRQ: " fmt , ##args); } while (0)
  45 +#else
  46 +#define DPRINTF(fmt, args...)
  47 +#endif
  48 +
41 49 #define KERNEL_LOAD_ADDR 0x00004000
42 50 #define CMDLINE_ADDR 0x007ff000
43 51 #define INITRD_LOAD_ADDR 0x00800000
... ... @@ -46,6 +54,7 @@
46 54 #define PROM_FILENAME "openbios-sparc32"
47 55  
48 56 #define MAX_CPUS 16
  57 +#define MAX_PILS 16
49 58  
50 59 struct hwdef {
51 60 target_phys_addr_t iommu_base, slavio_base;
... ... @@ -233,6 +242,33 @@ void irq_info()
233 242 slavio_irq_info(slavio_intctl);
234 243 }
235 244  
  245 +static void cpu_set_irq(void *opaque, int irq, int level)
  246 +{
  247 + CPUState *env = opaque;
  248 +
  249 + if (level) {
  250 + DPRINTF("Raise CPU IRQ %d\n", irq);
  251 +
  252 + env->halted = 0;
  253 +
  254 + if (env->interrupt_index == 0 ||
  255 + ((env->interrupt_index & ~15) == TT_EXTINT &&
  256 + (env->interrupt_index & 15) < irq)) {
  257 + env->interrupt_index = TT_EXTINT | irq;
  258 + cpu_interrupt(env, CPU_INTERRUPT_HARD);
  259 + } else {
  260 + DPRINTF("Not triggered, pending exception %d\n",
  261 + env->interrupt_index);
  262 + }
  263 + } else {
  264 + DPRINTF("Lower CPU IRQ %d\n", irq);
  265 + }
  266 +}
  267 +
  268 +static void dummy_cpu_set_irq(void *opaque, int irq, int level)
  269 +{
  270 +}
  271 +
236 272 static void *slavio_misc;
237 273  
238 274 void qemu_system_powerdown(void)
... ... @@ -264,7 +300,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
264 300 unsigned int i;
265 301 void *iommu, *espdma, *ledma, *main_esp;
266 302 const sparc_def_t *def;
267   - qemu_irq *slavio_irq, *slavio_cpu_irq,
  303 + qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,
268 304 *espdma_irq, *ledma_irq;
269 305  
270 306 /* init CPUs */
... ... @@ -273,6 +309,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
273 309 fprintf(stderr, "Unable to find Sparc CPU definition\n");
274 310 exit(1);
275 311 }
  312 +
276 313 for(i = 0; i < smp_cpus; i++) {
277 314 env = cpu_init();
278 315 cpu_sparc_register(env, def);
... ... @@ -284,7 +321,12 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
284 321 env->halted = 1;
285 322 }
286 323 register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
  324 + cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
287 325 }
  326 +
  327 + for (i = smp_cpus; i < MAX_CPUS; i++)
  328 + cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
  329 +
288 330 /* allocate RAM */
289 331 cpu_register_physical_memory(0, ram_size, 0);
290 332  
... ... @@ -293,10 +335,9 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
293 335 hwdef->intctl_base + 0x10000ULL,
294 336 &hwdef->intbit_to_level[0],
295 337 &slavio_irq, &slavio_cpu_irq,
  338 + cpu_irqs,
296 339 hwdef->clock_irq);
297   - for(i = 0; i < smp_cpus; i++) {
298   - slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
299   - }
  340 +
300 341 espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
301 342 iommu, &espdma_irq);
302 343 ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
... ...
... ... @@ -1233,8 +1233,7 @@ void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base,
1233 1233 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
1234 1234 const uint32_t *intbit_to_level,
1235 1235 qemu_irq **irq, qemu_irq **cpu_irq,
1236   - unsigned int cputimer);
1237   -void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env);
  1236 + qemu_irq **parent_irq, unsigned int cputimer);
1238 1237 void slavio_pic_info(void *opaque);
1239 1238 void slavio_irq_info(void *opaque);
1240 1239  
... ...