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,6 +44,7 @@ do { printf("IRQ: " fmt , ##args); } while (0)
44 */ 44 */
45 45
46 #define MAX_CPUS 16 46 #define MAX_CPUS 16
  47 +#define MAX_PILS 16
47 48
48 typedef struct SLAVIO_INTCTLState { 49 typedef struct SLAVIO_INTCTLState {
49 uint32_t intreg_pending[MAX_CPUS]; 50 uint32_t intreg_pending[MAX_CPUS];
@@ -53,9 +54,10 @@ typedef struct SLAVIO_INTCTLState { @@ -53,9 +54,10 @@ typedef struct SLAVIO_INTCTLState {
53 #ifdef DEBUG_IRQ_COUNT 54 #ifdef DEBUG_IRQ_COUNT
54 uint64_t irq_count[32]; 55 uint64_t irq_count[32];
55 #endif 56 #endif
56 - CPUState *cpu_envs[MAX_CPUS]; 57 + qemu_irq *cpu_irqs[MAX_CPUS];
57 const uint32_t *intbit_to_level; 58 const uint32_t *intbit_to_level;
58 uint32_t cputimer_bit; 59 uint32_t cputimer_bit;
  60 + uint32_t pil_out[MAX_CPUS];
59 } SLAVIO_INTCTLState; 61 } SLAVIO_INTCTLState;
60 62
61 #define INTCTL_MAXADDR 0xf 63 #define INTCTL_MAXADDR 0xf
@@ -213,67 +215,53 @@ void slavio_irq_info(void *opaque) @@ -213,67 +215,53 @@ void slavio_irq_info(void *opaque)
213 #endif 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 static void slavio_check_interrupts(void *opaque) 238 static void slavio_check_interrupts(void *opaque)
217 { 239 {
218 - CPUState *env;  
219 SLAVIO_INTCTLState *s = opaque; 240 SLAVIO_INTCTLState *s = opaque;
220 uint32_t pending = s->intregm_pending; 241 uint32_t pending = s->intregm_pending;
221 unsigned int i, j, max = 0; 242 unsigned int i, j, max = 0;
222 243
223 pending &= ~s->intregm_disabled; 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 for (i = 0; i < MAX_CPUS; i++) { 247 for (i = 0; i < MAX_CPUS; i++) {
255 max = 0; 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 for (j = 17; j < 32; j++) { 258 for (j = 17; j < 32; j++) {
260 if (s->intreg_pending[i] & (1 << j)) { 259 if (s->intreg_pending[i] & (1 << j)) {
261 if (max < j - 16) 260 if (max < j - 16)
262 max = j - 16; 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,22 +272,20 @@ static void slavio_check_interrupts(void *opaque)
284 static void slavio_set_irq(void *opaque, int irq, int level) 272 static void slavio_set_irq(void *opaque, int irq, int level)
285 { 273 {
286 SLAVIO_INTCTLState *s = opaque; 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,15 +293,12 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
307 { 293 {
308 SLAVIO_INTCTLState *s = opaque; 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 s->intreg_pending[cpu] |= s->cputimer_bit; 299 s->intreg_pending[cpu] |= s->cputimer_bit;
316 - } else { 300 + else
317 s->intreg_pending[cpu] &= ~s->cputimer_bit; 301 s->intreg_pending[cpu] &= ~s->cputimer_bit;
318 - }  
319 302
320 slavio_check_interrupts(s); 303 slavio_check_interrupts(s);
321 } 304 }
@@ -363,18 +346,10 @@ static void slavio_intctl_reset(void *opaque) @@ -363,18 +346,10 @@ static void slavio_intctl_reset(void *opaque)
363 s->target_cpu = 0; 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 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, 349 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
374 const uint32_t *intbit_to_level, 350 const uint32_t *intbit_to_level,
375 qemu_irq **irq, qemu_irq **cpu_irq, 351 qemu_irq **irq, qemu_irq **cpu_irq,
376 - unsigned int cputimer)  
377 - 352 + qemu_irq **parent_irq, unsigned int cputimer)
378 { 353 {
379 int slavio_intctl_io_memory, slavio_intctlm_io_memory, i; 354 int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
380 SLAVIO_INTCTLState *s; 355 SLAVIO_INTCTLState *s;
@@ -388,6 +363,7 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, @@ -388,6 +363,7 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
388 slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s); 363 slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
389 cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE, 364 cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
390 slavio_intctl_io_memory); 365 slavio_intctl_io_memory);
  366 + s->cpu_irqs[i] = parent_irq[i];
391 } 367 }
392 368
393 slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s); 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,6 +22,7 @@
22 * THE SOFTWARE. 22 * THE SOFTWARE.
23 */ 23 */
24 #include "vl.h" 24 #include "vl.h"
  25 +//#define DEBUG_IRQ
25 26
26 /* 27 /*
27 * Sun4m architecture was used in the following machines: 28 * Sun4m architecture was used in the following machines:
@@ -38,6 +39,13 @@ @@ -38,6 +39,13 @@
38 * See for example: http://www.sunhelp.org/faq/sunref1.html 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 #define KERNEL_LOAD_ADDR 0x00004000 49 #define KERNEL_LOAD_ADDR 0x00004000
42 #define CMDLINE_ADDR 0x007ff000 50 #define CMDLINE_ADDR 0x007ff000
43 #define INITRD_LOAD_ADDR 0x00800000 51 #define INITRD_LOAD_ADDR 0x00800000
@@ -46,6 +54,7 @@ @@ -46,6 +54,7 @@
46 #define PROM_FILENAME "openbios-sparc32" 54 #define PROM_FILENAME "openbios-sparc32"
47 55
48 #define MAX_CPUS 16 56 #define MAX_CPUS 16
  57 +#define MAX_PILS 16
49 58
50 struct hwdef { 59 struct hwdef {
51 target_phys_addr_t iommu_base, slavio_base; 60 target_phys_addr_t iommu_base, slavio_base;
@@ -233,6 +242,33 @@ void irq_info() @@ -233,6 +242,33 @@ void irq_info()
233 slavio_irq_info(slavio_intctl); 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 static void *slavio_misc; 272 static void *slavio_misc;
237 273
238 void qemu_system_powerdown(void) 274 void qemu_system_powerdown(void)
@@ -264,7 +300,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size, @@ -264,7 +300,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
264 unsigned int i; 300 unsigned int i;
265 void *iommu, *espdma, *ledma, *main_esp; 301 void *iommu, *espdma, *ledma, *main_esp;
266 const sparc_def_t *def; 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 *espdma_irq, *ledma_irq; 304 *espdma_irq, *ledma_irq;
269 305
270 /* init CPUs */ 306 /* init CPUs */
@@ -273,6 +309,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size, @@ -273,6 +309,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
273 fprintf(stderr, "Unable to find Sparc CPU definition\n"); 309 fprintf(stderr, "Unable to find Sparc CPU definition\n");
274 exit(1); 310 exit(1);
275 } 311 }
  312 +
276 for(i = 0; i < smp_cpus; i++) { 313 for(i = 0; i < smp_cpus; i++) {
277 env = cpu_init(); 314 env = cpu_init();
278 cpu_sparc_register(env, def); 315 cpu_sparc_register(env, def);
@@ -284,7 +321,12 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size, @@ -284,7 +321,12 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
284 env->halted = 1; 321 env->halted = 1;
285 } 322 }
286 register_savevm("cpu", i, 3, cpu_save, cpu_load, env); 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 /* allocate RAM */ 330 /* allocate RAM */
289 cpu_register_physical_memory(0, ram_size, 0); 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,10 +335,9 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
293 hwdef->intctl_base + 0x10000ULL, 335 hwdef->intctl_base + 0x10000ULL,
294 &hwdef->intbit_to_level[0], 336 &hwdef->intbit_to_level[0],
295 &slavio_irq, &slavio_cpu_irq, 337 &slavio_irq, &slavio_cpu_irq,
  338 + cpu_irqs,
296 hwdef->clock_irq); 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 espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq], 341 espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
301 iommu, &espdma_irq); 342 iommu, &espdma_irq);
302 ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, 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,8 +1233,7 @@ void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base,
1233 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, 1233 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
1234 const uint32_t *intbit_to_level, 1234 const uint32_t *intbit_to_level,
1235 qemu_irq **irq, qemu_irq **cpu_irq, 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 void slavio_pic_info(void *opaque); 1237 void slavio_pic_info(void *opaque);
1239 void slavio_irq_info(void *opaque); 1238 void slavio_irq_info(void *opaque);
1240 1239