Commit 4de9b249d37c1b382cc3e5a21fad1b4a11cec2fa
1 parent
30c4bbac
Reworking MIPS interrupt handling, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2350 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
13 changed files
with
76 additions
and
75 deletions
Makefile.target
... | ... | @@ -376,7 +376,7 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o |
376 | 376 | CPPFLAGS += -DHAS_AUDIO |
377 | 377 | endif |
378 | 378 | ifeq ($(TARGET_ARCH), mips) |
379 | -VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o | |
379 | +VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o | |
380 | 380 | VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o |
381 | 381 | VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV) |
382 | 382 | DEFINES += -DHAS_AUDIO | ... | ... |
cpu-exec.c
... | ... | @@ -535,7 +535,6 @@ int cpu_exec(CPUState *env1) |
535 | 535 | env->exception_index = EXCP_EXT_INTERRUPT; |
536 | 536 | env->error_code = 0; |
537 | 537 | do_interrupt(env); |
538 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
539 | 538 | #if defined(__sparc__) && !defined(HOST_SOLARIS) |
540 | 539 | tmp_T0 = 0; |
541 | 540 | #else | ... | ... |
hw/gt64xxx.c
1 | 1 | /* |
2 | 2 | * QEMU GT64120 PCI host |
3 | 3 | * |
4 | - * Copyright (c) 2006 Aurelien Jarno | |
4 | + * Copyright (c) 2006,2007 Aurelien Jarno | |
5 | 5 | * |
6 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 | * of this software and associated documentation files (the "Software"), to deal |
... | ... | @@ -433,7 +433,8 @@ static uint32_t gt64120_readl (void *opaque, |
433 | 433 | val = s->regs[saddr]; |
434 | 434 | break; |
435 | 435 | case GT_PCI0_IACK: |
436 | - val = pic_intack_read(isa_pic); | |
436 | + /* Read the IRQ number */ | |
437 | + val = pic_read_irq(isa_pic); | |
437 | 438 | break; |
438 | 439 | |
439 | 440 | /* SDRAM Parameters */ | ... | ... |
hw/i8259.c
... | ... | @@ -161,6 +161,13 @@ void pic_update_irq(PicState2 *s) |
161 | 161 | #endif |
162 | 162 | s->irq_request(s->irq_request_opaque, 1); |
163 | 163 | } |
164 | + | |
165 | +/* all targets should do this rather than acking the IRQ in the cpu */ | |
166 | +#if defined(TARGET_MIPS) | |
167 | + else { | |
168 | + s->irq_request(s->irq_request_opaque, 0); | |
169 | + } | |
170 | +#endif | |
164 | 171 | } |
165 | 172 | |
166 | 173 | #ifdef DEBUG_IRQ_LATENCY | ... | ... |
hw/mips_int.c
0 → 100644
1 | +#include "vl.h" | |
2 | +#include "cpu.h" | |
3 | + | |
4 | +/* Raise IRQ to CPU if necessary. It must be called every time the active | |
5 | + IRQ may change */ | |
6 | +void cpu_mips_update_irq(CPUState *env) | |
7 | +{ | |
8 | + if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) && | |
9 | + (env->CP0_Status & (1 << CP0St_IE)) && | |
10 | + !(env->hflags & MIPS_HFLAG_EXL) && | |
11 | + !(env->hflags & MIPS_HFLAG_ERL) && | |
12 | + !(env->hflags & MIPS_HFLAG_DM)) { | |
13 | + if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) { | |
14 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
15 | + } | |
16 | + } else { | |
17 | + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | |
18 | + } | |
19 | +} | |
20 | + | |
21 | +void cpu_mips_irq_request(void *opaque, int irq, int level) | |
22 | +{ | |
23 | + CPUState *env = first_cpu; | |
24 | + | |
25 | + uint32_t mask; | |
26 | + | |
27 | + if (irq >= 16) | |
28 | + return; | |
29 | + | |
30 | + mask = 1 << (irq + CP0Ca_IP); | |
31 | + | |
32 | + if (level) { | |
33 | + env->CP0_Cause |= mask; | |
34 | + } else { | |
35 | + env->CP0_Cause &= ~mask; | |
36 | + } | |
37 | + cpu_mips_update_irq(env); | |
38 | +} | |
39 | + | ... | ... |
hw/mips_malta.c
... | ... | @@ -54,16 +54,10 @@ typedef struct { |
54 | 54 | |
55 | 55 | static PITState *pit; |
56 | 56 | |
57 | +/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */ | |
57 | 58 | static void pic_irq_request(void *opaque, int level) |
58 | 59 | { |
59 | - CPUState *env = first_cpu; | |
60 | - if (level) { | |
61 | - env->CP0_Cause |= 0x00000400; | |
62 | - cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
63 | - } else { | |
64 | - env->CP0_Cause &= ~0x00000400; | |
65 | - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | |
66 | - } | |
60 | + cpu_mips_irq_request(opaque, 2, level); | |
67 | 61 | } |
68 | 62 | |
69 | 63 | /* Malta FPGA */ | ... | ... |
hw/mips_r4k.c
... | ... | @@ -38,14 +38,7 @@ static PITState *pit; /* PIT i8254 */ |
38 | 38 | /*The PIC is attached to the MIPS CPU INT0 pin */ |
39 | 39 | static void pic_irq_request(void *opaque, int level) |
40 | 40 | { |
41 | - CPUState *env = first_cpu; | |
42 | - if (level) { | |
43 | - env->CP0_Cause |= 0x00000400; | |
44 | - cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
45 | - } else { | |
46 | - env->CP0_Cause &= ~0x00000400; | |
47 | - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | |
48 | - } | |
41 | + cpu_mips_irq_request(opaque, 2, level); | |
49 | 42 | } |
50 | 43 | |
51 | 44 | static void mips_qemu_writel (void *opaque, target_phys_addr_t addr, | ... | ... |
hw/mips_timer.c
... | ... | @@ -57,8 +57,7 @@ void cpu_mips_store_count (CPUState *env, uint32_t value) |
57 | 57 | void cpu_mips_store_compare (CPUState *env, uint32_t value) |
58 | 58 | { |
59 | 59 | cpu_mips_update_count(env, cpu_mips_get_count(env), value); |
60 | - env->CP0_Cause &= ~0x00008000; | |
61 | - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | |
60 | + cpu_mips_irq_request(env, 7, 0); | |
62 | 61 | } |
63 | 62 | |
64 | 63 | static void mips_timer_cb (void *opaque) |
... | ... | @@ -72,8 +71,7 @@ static void mips_timer_cb (void *opaque) |
72 | 71 | } |
73 | 72 | #endif |
74 | 73 | cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare); |
75 | - env->CP0_Cause |= 0x00008000; | |
76 | - cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
74 | + cpu_mips_irq_request(env, 7, 1); | |
77 | 75 | } |
78 | 76 | |
79 | 77 | void cpu_mips_clock_init (CPUState *env) | ... | ... |
target-mips/cpu.h
target-mips/exec.h
... | ... | @@ -164,6 +164,7 @@ uint32_t cpu_mips_get_random (CPUState *env); |
164 | 164 | uint32_t cpu_mips_get_count (CPUState *env); |
165 | 165 | void cpu_mips_store_count (CPUState *env, uint32_t value); |
166 | 166 | void cpu_mips_store_compare (CPUState *env, uint32_t value); |
167 | +void cpu_mips_update_irq(CPUState *env); | |
167 | 168 | void cpu_mips_clock_init (CPUState *env); |
168 | 169 | void cpu_mips_tlb_flush (CPUState *env, int flush_global); |
169 | 170 | ... | ... |
target-mips/op.c
... | ... | @@ -1357,7 +1357,7 @@ void op_mtc0_compare (void) |
1357 | 1357 | |
1358 | 1358 | void op_mtc0_status (void) |
1359 | 1359 | { |
1360 | - uint32_t val, old, mask; | |
1360 | + uint32_t val, old; | |
1361 | 1361 | |
1362 | 1362 | val = (int32_t)T0 & 0xFA78FF01; |
1363 | 1363 | old = env->CP0_Status; |
... | ... | @@ -1374,21 +1374,9 @@ void op_mtc0_status (void) |
1374 | 1374 | else |
1375 | 1375 | env->hflags &= ~MIPS_HFLAG_EXL; |
1376 | 1376 | env->CP0_Status = val; |
1377 | - /* If we unmasked an asserted IRQ, raise it */ | |
1378 | - mask = 0x0000FF00; | |
1379 | 1377 | if (loglevel & CPU_LOG_TB_IN_ASM) |
1380 | 1378 | CALL_FROM_TB2(do_mtc0_status_debug, old, val); |
1381 | - if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && | |
1382 | - !(env->hflags & MIPS_HFLAG_EXL) && | |
1383 | - !(env->hflags & MIPS_HFLAG_ERL) && | |
1384 | - !(env->hflags & MIPS_HFLAG_DM) && | |
1385 | - (env->CP0_Status & env->CP0_Cause & mask)) { | |
1386 | - env->interrupt_request |= CPU_INTERRUPT_HARD; | |
1387 | - if (logfile) | |
1388 | - CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | |
1389 | - } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { | |
1390 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
1391 | - } | |
1379 | + CALL_FROM_TB1(cpu_mips_update_irq, env); | |
1392 | 1380 | RETURN(); |
1393 | 1381 | } |
1394 | 1382 | |
... | ... | @@ -1415,22 +1403,13 @@ void op_mtc0_srsmap (void) |
1415 | 1403 | |
1416 | 1404 | void op_mtc0_cause (void) |
1417 | 1405 | { |
1418 | - uint32_t val, old; | |
1406 | + env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300); | |
1419 | 1407 | |
1420 | - val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300); | |
1421 | - old = env->CP0_Cause; | |
1422 | - env->CP0_Cause = val; | |
1423 | -#if 0 | |
1424 | - { | |
1425 | - int i, mask; | |
1426 | - /* Check if we ever asserted a software IRQ */ | |
1427 | - for (i = 0; i < 2; i++) { | |
1428 | - mask = 0x100 << i; | |
1429 | - if ((val & mask) & !(old & mask)) | |
1430 | - CALL_FROM_TB1(mips_set_irq, i); | |
1431 | - } | |
1408 | + /* Handle the software interrupt as an hardware one, as they | |
1409 | + are very similar */ | |
1410 | + if (T0 & CP0Ca_IP_mask) { | |
1411 | + CALL_FROM_TB1(cpu_mips_update_irq, env); | |
1432 | 1412 | } |
1433 | -#endif | |
1434 | 1413 | RETURN(); |
1435 | 1414 | } |
1436 | 1415 | |
... | ... | @@ -2074,36 +2053,17 @@ void op_pmon (void) |
2074 | 2053 | |
2075 | 2054 | void op_di (void) |
2076 | 2055 | { |
2077 | - uint32_t val; | |
2078 | - | |
2079 | 2056 | T0 = env->CP0_Status; |
2080 | - val = T0 & ~(1 << CP0St_IE); | |
2081 | - if (val != T0) { | |
2082 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
2083 | - env->CP0_Status = val; | |
2084 | - } | |
2057 | + env->CP0_Status = T0 & ~(1 << CP0St_IE); | |
2058 | + CALL_FROM_TB1(cpu_mips_update_irq, env); | |
2085 | 2059 | RETURN(); |
2086 | 2060 | } |
2087 | 2061 | |
2088 | 2062 | void op_ei (void) |
2089 | 2063 | { |
2090 | - uint32_t val; | |
2091 | - | |
2092 | 2064 | T0 = env->CP0_Status; |
2093 | - val = T0 | (1 << CP0St_IE); | |
2094 | - if (val != T0) { | |
2095 | - const uint32_t mask = 0x0000FF00; | |
2096 | - | |
2097 | - env->CP0_Status = val; | |
2098 | - if (!(env->hflags & MIPS_HFLAG_EXL) && | |
2099 | - !(env->hflags & MIPS_HFLAG_ERL) && | |
2100 | - !(env->hflags & MIPS_HFLAG_DM) && | |
2101 | - (env->CP0_Status & env->CP0_Cause & mask)) { | |
2102 | - env->interrupt_request |= CPU_INTERRUPT_HARD; | |
2103 | - if (logfile) | |
2104 | - CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | |
2105 | - } | |
2106 | - } | |
2065 | + env->CP0_Status = T0 | (1 << CP0St_IE); | |
2066 | + CALL_FROM_TB1(cpu_mips_update_irq, env); | |
2107 | 2067 | RETURN(); |
2108 | 2068 | } |
2109 | 2069 | ... | ... |
target-mips/op_helper.c
... | ... | @@ -265,6 +265,11 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value) |
265 | 265 | cpu_abort(env, "mtc0 compare\n"); |
266 | 266 | } |
267 | 267 | |
268 | +void cpu_mips_update_irq(CPUState *env) | |
269 | +{ | |
270 | + cpu_abort(env, "mtc0 status / mtc0 cause\n"); | |
271 | +} | |
272 | + | |
268 | 273 | void do_mtc0_status_debug(uint32_t old, uint32_t val) |
269 | 274 | { |
270 | 275 | cpu_abort(env, "mtc0 status debug\n"); | ... | ... |
vl.h
... | ... | @@ -1067,6 +1067,9 @@ extern QEMUMachine mips_machine; |
1067 | 1067 | /* mips_malta.c */ |
1068 | 1068 | extern QEMUMachine mips_malta_machine; |
1069 | 1069 | |
1070 | +/* mips_int */ | |
1071 | +extern void cpu_mips_irq_request(void *opaque, int irq, int level); | |
1072 | + | |
1070 | 1073 | /* mips_timer.c */ |
1071 | 1074 | extern void cpu_mips_clock_init(CPUState *); |
1072 | 1075 | extern void cpu_mips_irqctrl_init (void); | ... | ... |